@vrplatform/kysely 1.3.40 → 1.3.41-stage.1
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/build/.data.tar +0 -0
- package/build/main/camel-case/index.js.map +1 -1
- package/build/main/control-plane/index.d.ts +141 -0
- package/build/main/control-plane/index.js +3 -0
- package/build/main/control-plane/index.js.map +1 -0
- package/build/main/error.js.map +1 -1
- package/build/main/index.d.ts +6 -3
- package/build/main/index.js +8 -9
- package/build/main/index.js.map +1 -1
- package/build/main/isomorphic.d.ts +2 -1
- package/build/main/isomorphic.js +2 -2
- package/build/main/isomorphic.js.map +1 -1
- package/build/main/local/digest.js.map +1 -1
- package/build/main/local/generate.js +12 -0
- package/build/main/local/generate.js.map +1 -1
- package/build/main/local/index.d.ts +3 -2
- package/build/main/local/index.js +56 -3
- package/build/main/local/index.js.map +1 -1
- package/build/main/local/prune-pulled-schema.js.map +1 -1
- package/build/main/pganalyze-comment-plugin/comment-transformer.js +0 -1
- package/build/main/pganalyze-comment-plugin/comment-transformer.js.map +1 -1
- package/build/main/pganalyze-comment-plugin/index.js +16 -3
- package/build/main/pganalyze-comment-plugin/index.js.map +1 -1
- package/build/main/plugins.js.map +1 -1
- package/build/main/query/listing/status.d.ts +4 -4
- package/build/main/query/listing/status.js +19 -2
- package/build/main/query/listing/status.js.map +1 -1
- package/build/main/regional.d.ts +34 -0
- package/build/main/regional.js +139 -0
- package/build/main/regional.js.map +1 -0
- package/build/main/test/index.js.map +1 -1
- package/build/main/transaction.d.ts +7 -0
- package/build/main/transaction.js +32 -0
- package/build/main/transaction.js.map +1 -0
- package/build/main/v1.generated.d.ts +133 -2
- package/build/main/v1.generated.js.map +1 -1
- package/build/migrations/0000000000001-init.ts +5 -0
- package/build/migrations/0000000000009-drop-store-schema.ts +14 -0
- package/build/migrations/0000000000010-bank-rules.ts +190 -0
- package/build/migrations/0000000000011-bank-rule-line-adjustments.ts +65 -0
- package/build/migrations/0000000000012-bank-rule-conditions.ts +45 -0
- package/build/migrations/0000000000013-bank-rule-name-unique.ts +15 -0
- package/build/migrations/0000000000014-bank-rule-drop-legacy-conditions.ts +41 -0
- package/build/migrations/0000000000015-booking-channel-logo-dev-provider.ts +70 -0
- package/build/migrations/0000000000016-owner-statement-draft-status.ts +22 -0
- package/build/migrations/0000000000017-tenant-migration-markers.ts +18 -0
- package/build/migrations/0000000000018-security-deposits-payable-category.ts +63 -0
- package/build/migrations/0000000000019-tenant-app-settings.ts +76 -0
- package/build/migrations/0000000000020-operating-opening-trial-balance.ts +36 -0
- package/build/migrations/0000000000021-audit-foreign-key-indexes.ts +77 -0
- package/build/migrations/0000000000022-opening-trial-balance-combined-columns.ts +30 -0
- package/build/migrations/0000000000023-journal-entry-currency-mismatch-reason.ts +14 -0
- package/build/migrations/0000000000024-listing-parent.ts +37 -0
- package/build/migrations/0000000000025-journal-entry-parent-listing.ts +26 -0
- package/build/migrations/0000000000026-booking-channel-logo-slots.ts +89 -0
- package/build/migrations/0000000000027-list-browse-performance-indexes.ts +52 -0
- package/build/migrations/0000000000028-flow-setting-status-jsonb.ts +20 -0
- package/build/migrations/0000000000029-tenant-slug.ts +328 -0
- package/build/migrations/0000000000030-pms-accounting-windows.ts +50 -0
- package/build/migrations/0000000000031-owner-statement-projection-listing-revision.ts +20 -0
- package/build/migrations/0000000000032-flow-event-listening.ts +28 -0
- package/build/migrations/0000000000033-opening-trial-balance-transaction.ts +272 -0
- package/build/migrations/0000000000034-historic-general-ledger.ts +24 -0
- package/build/migrations/0000000000035-tenant-regional-placement.ts +37 -0
- package/build/migrations/0000000000036-control-plane-projection-events.ts +43 -0
- package/build/migrations/0000000000037-tenant-guide-onboarding.ts +21 -0
- package/build/migrations/0000000000038-ramp-staging-connect-params.ts +35 -0
- package/build/migrations/0000000000038-tracking-event-analytics-sink.ts +31 -0
- package/build/migrations/0000000000039-crunchy-region.ts +86 -0
- package/build/migrations/0000000000039-gl-pms-accounting-window-guard.ts +125 -0
- package/build/module/camel-case/index.js.map +1 -1
- package/build/module/control-plane/index.d.ts +141 -0
- package/build/module/control-plane/index.js +2 -0
- package/build/module/control-plane/index.js.map +1 -0
- package/build/module/error.js.map +1 -1
- package/build/module/index.d.ts +6 -3
- package/build/module/index.js +8 -9
- package/build/module/index.js.map +1 -1
- package/build/module/isomorphic.d.ts +2 -1
- package/build/module/isomorphic.js.map +1 -1
- package/build/module/local/digest.js.map +1 -1
- package/build/module/local/generate.js +12 -0
- package/build/module/local/generate.js.map +1 -1
- package/build/module/local/index.d.ts +3 -2
- package/build/module/local/index.js +23 -3
- package/build/module/local/index.js.map +1 -1
- package/build/module/local/prune-pulled-schema.js.map +1 -1
- package/build/module/pganalyze-comment-plugin/comment-transformer.js.map +1 -1
- package/build/module/pganalyze-comment-plugin/index.js.map +1 -1
- package/build/module/plugins.js.map +1 -1
- package/build/module/query/listing/status.d.ts +4 -4
- package/build/module/query/listing/status.js +19 -2
- package/build/module/query/listing/status.js.map +1 -1
- package/build/module/regional.d.ts +34 -0
- package/build/module/regional.js +97 -0
- package/build/module/regional.js.map +1 -0
- package/build/module/test/index.js.map +1 -1
- package/build/module/transaction.d.ts +7 -0
- package/build/module/transaction.js +25 -0
- package/build/module/transaction.js.map +1 -0
- package/build/module/v1.generated.d.ts +133 -2
- package/build/module/v1.generated.js.map +1 -1
- package/package.json +13 -4
- package/build/main/tsconfig.main.tsbuildinfo +0 -1
- package/build/module/tsconfig.esm.tsbuildinfo +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
create index if not exists audit_action_parent_action_idx
|
|
7
|
+
on audit.action (parent_action_id)
|
|
8
|
+
where parent_action_id is not null;
|
|
9
|
+
`.execute(db);
|
|
10
|
+
|
|
11
|
+
await sql`
|
|
12
|
+
create index if not exists audit_journal_delta_action_idx
|
|
13
|
+
on audit.journal_delta (action_id);
|
|
14
|
+
`.execute(db);
|
|
15
|
+
|
|
16
|
+
await sql`
|
|
17
|
+
create index if not exists audit_journal_delta_effect_idx
|
|
18
|
+
on audit.journal_delta (effect_id)
|
|
19
|
+
where effect_id is not null;
|
|
20
|
+
`.execute(db);
|
|
21
|
+
|
|
22
|
+
await sql`
|
|
23
|
+
create index if not exists audit_journal_delta_mutation_idx
|
|
24
|
+
on audit.journal_delta (mutation_id)
|
|
25
|
+
where mutation_id is not null;
|
|
26
|
+
`.execute(db);
|
|
27
|
+
|
|
28
|
+
await sql`
|
|
29
|
+
create index if not exists audit_mutation_action_idx
|
|
30
|
+
on audit.mutation (action_id);
|
|
31
|
+
`.execute(db);
|
|
32
|
+
|
|
33
|
+
await sql`
|
|
34
|
+
create index if not exists audit_mutation_effect_idx
|
|
35
|
+
on audit.mutation (effect_id)
|
|
36
|
+
where effect_id is not null;
|
|
37
|
+
`.execute(db);
|
|
38
|
+
|
|
39
|
+
await sql`
|
|
40
|
+
create index if not exists audit_effect_action_idx
|
|
41
|
+
on audit.effect (action_id);
|
|
42
|
+
`.execute(db);
|
|
43
|
+
|
|
44
|
+
await sql`
|
|
45
|
+
create index if not exists audit_effect_attempt_action_idx
|
|
46
|
+
on audit.effect_attempt (action_id);
|
|
47
|
+
`.execute(db);
|
|
48
|
+
|
|
49
|
+
await sql`
|
|
50
|
+
create index if not exists audit_effect_attempt_effect_idx
|
|
51
|
+
on audit.effect_attempt (effect_id);
|
|
52
|
+
`.execute(db);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
56
|
+
await sql`drop index if exists audit.audit_action_parent_action_idx;`.execute(
|
|
57
|
+
db
|
|
58
|
+
);
|
|
59
|
+
await sql`drop index if exists audit.audit_effect_attempt_effect_idx;`.execute(
|
|
60
|
+
db
|
|
61
|
+
);
|
|
62
|
+
await sql`drop index if exists audit.audit_effect_attempt_action_idx;`.execute(
|
|
63
|
+
db
|
|
64
|
+
);
|
|
65
|
+
await sql`drop index if exists audit.audit_effect_action_idx;`.execute(db);
|
|
66
|
+
await sql`drop index if exists audit.audit_mutation_effect_idx;`.execute(db);
|
|
67
|
+
await sql`drop index if exists audit.audit_mutation_action_idx;`.execute(db);
|
|
68
|
+
await sql`drop index if exists audit.audit_journal_delta_mutation_idx;`.execute(
|
|
69
|
+
db
|
|
70
|
+
);
|
|
71
|
+
await sql`drop index if exists audit.audit_journal_delta_effect_idx;`.execute(
|
|
72
|
+
db
|
|
73
|
+
);
|
|
74
|
+
await sql`drop index if exists audit.audit_journal_delta_action_idx;`.execute(
|
|
75
|
+
db
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter table accounting.account
|
|
7
|
+
rename column operating_opening_trial_balance_cent_total
|
|
8
|
+
to opening_trial_balance_combined_cent_total;
|
|
9
|
+
`.execute(db);
|
|
10
|
+
|
|
11
|
+
await sql`
|
|
12
|
+
alter table accounting.account
|
|
13
|
+
rename column operating_opening_trial_balance_updated_at
|
|
14
|
+
to opening_trial_balance_updated_at;
|
|
15
|
+
`.execute(db);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
19
|
+
await sql`
|
|
20
|
+
alter table accounting.account
|
|
21
|
+
rename column opening_trial_balance_combined_cent_total
|
|
22
|
+
to operating_opening_trial_balance_cent_total;
|
|
23
|
+
`.execute(db);
|
|
24
|
+
|
|
25
|
+
await sql`
|
|
26
|
+
alter table accounting.account
|
|
27
|
+
rename column opening_trial_balance_updated_at
|
|
28
|
+
to operating_opening_trial_balance_updated_at;
|
|
29
|
+
`.execute(db);
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter type accounting.journal_entry_inactive_reason
|
|
7
|
+
add value if not exists 'currencyMismatch'
|
|
8
|
+
before 'unknownInactiveReason';
|
|
9
|
+
`.execute(db);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function down(_db: Kysely<any>): Promise<void> {
|
|
13
|
+
// PostgreSQL enum values cannot be removed safely without rebuilding the type.
|
|
14
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter table public.listing
|
|
7
|
+
add column parent_id uuid null references public.listing(id)
|
|
8
|
+
on update restrict on delete restrict;
|
|
9
|
+
`.execute(db);
|
|
10
|
+
|
|
11
|
+
await sql`
|
|
12
|
+
create index listing_tenant_id_parent_id_idx
|
|
13
|
+
on public.listing(tenant_id, parent_id);
|
|
14
|
+
`.execute(db);
|
|
15
|
+
|
|
16
|
+
await sql`
|
|
17
|
+
alter table public.listing
|
|
18
|
+
add constraint listing_parent_not_self_check
|
|
19
|
+
check (parent_id is null or parent_id <> id);
|
|
20
|
+
`.execute(db);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
24
|
+
await sql`
|
|
25
|
+
alter table public.listing
|
|
26
|
+
drop constraint if exists listing_parent_not_self_check;
|
|
27
|
+
`.execute(db);
|
|
28
|
+
|
|
29
|
+
await sql`
|
|
30
|
+
drop index if exists listing_tenant_id_parent_id_idx;
|
|
31
|
+
`.execute(db);
|
|
32
|
+
|
|
33
|
+
await sql`
|
|
34
|
+
alter table public.listing
|
|
35
|
+
drop column if exists parent_id;
|
|
36
|
+
`.execute(db);
|
|
37
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter table accounting.journal_entry
|
|
7
|
+
add column parent_listing_id uuid null references public.listing(id)
|
|
8
|
+
on update restrict on delete restrict;
|
|
9
|
+
`.execute(db);
|
|
10
|
+
|
|
11
|
+
await sql`
|
|
12
|
+
create index journal_entry_tenant_id_parent_listing_id_idx
|
|
13
|
+
on accounting.journal_entry(tenant_id, parent_listing_id);
|
|
14
|
+
`.execute(db);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
18
|
+
await sql`
|
|
19
|
+
drop index if exists accounting.journal_entry_tenant_id_parent_listing_id_idx;
|
|
20
|
+
`.execute(db);
|
|
21
|
+
|
|
22
|
+
await sql`
|
|
23
|
+
alter table accounting.journal_entry
|
|
24
|
+
drop column if exists parent_listing_id;
|
|
25
|
+
`.execute(db);
|
|
26
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter table public.booking_channel
|
|
7
|
+
add column if not exists logo text null,
|
|
8
|
+
add column if not exists logo_provider text null,
|
|
9
|
+
add column if not exists selected_booking_channel_logo_candidate_id uuid null;
|
|
10
|
+
`.execute(db);
|
|
11
|
+
|
|
12
|
+
await sql`
|
|
13
|
+
alter table public.booking_channel
|
|
14
|
+
drop constraint if exists booking_channel_logo_provider_check;
|
|
15
|
+
`.execute(db);
|
|
16
|
+
|
|
17
|
+
await sql`
|
|
18
|
+
alter table public.booking_channel
|
|
19
|
+
add constraint booking_channel_logo_provider_check
|
|
20
|
+
check (
|
|
21
|
+
logo_provider is null
|
|
22
|
+
or logo_provider in ('cloudflare', 'logo_dev')
|
|
23
|
+
);
|
|
24
|
+
`.execute(db);
|
|
25
|
+
|
|
26
|
+
await sql`
|
|
27
|
+
alter table public.booking_channel_icon_candidate
|
|
28
|
+
add column if not exists width integer null,
|
|
29
|
+
add column if not exists height integer null;
|
|
30
|
+
`.execute(db);
|
|
31
|
+
|
|
32
|
+
await sql`
|
|
33
|
+
alter table public.booking_channel_icon_candidate
|
|
34
|
+
drop constraint if exists booking_channel_icon_candidate_dimensions_check;
|
|
35
|
+
`.execute(db);
|
|
36
|
+
|
|
37
|
+
await sql`
|
|
38
|
+
alter table public.booking_channel_icon_candidate
|
|
39
|
+
add constraint booking_channel_icon_candidate_dimensions_check
|
|
40
|
+
check (
|
|
41
|
+
(width is null or width > 0)
|
|
42
|
+
and (height is null or height > 0)
|
|
43
|
+
);
|
|
44
|
+
`.execute(db);
|
|
45
|
+
|
|
46
|
+
await sql`
|
|
47
|
+
alter table public.booking_channel
|
|
48
|
+
drop constraint if exists booking_channel_selected_logo_candidate_same_booking_channel_fk;
|
|
49
|
+
`.execute(db);
|
|
50
|
+
|
|
51
|
+
await sql`
|
|
52
|
+
alter table public.booking_channel
|
|
53
|
+
add constraint booking_channel_selected_logo_candidate_same_booking_channel_fk
|
|
54
|
+
foreign key (id, selected_booking_channel_logo_candidate_id)
|
|
55
|
+
references public.booking_channel_icon_candidate(booking_channel_id, id)
|
|
56
|
+
on update restrict
|
|
57
|
+
on delete restrict;
|
|
58
|
+
`.execute(db);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
62
|
+
await sql`
|
|
63
|
+
alter table public.booking_channel
|
|
64
|
+
drop constraint if exists booking_channel_selected_logo_candidate_same_booking_channel_fk;
|
|
65
|
+
`.execute(db);
|
|
66
|
+
|
|
67
|
+
await sql`
|
|
68
|
+
alter table public.booking_channel
|
|
69
|
+
drop constraint if exists booking_channel_logo_provider_check;
|
|
70
|
+
`.execute(db);
|
|
71
|
+
|
|
72
|
+
await sql`
|
|
73
|
+
alter table public.booking_channel_icon_candidate
|
|
74
|
+
drop constraint if exists booking_channel_icon_candidate_dimensions_check;
|
|
75
|
+
`.execute(db);
|
|
76
|
+
|
|
77
|
+
await sql`
|
|
78
|
+
alter table public.booking_channel
|
|
79
|
+
drop column if exists selected_booking_channel_logo_candidate_id,
|
|
80
|
+
drop column if exists logo_provider,
|
|
81
|
+
drop column if exists logo;
|
|
82
|
+
`.execute(db);
|
|
83
|
+
|
|
84
|
+
await sql`
|
|
85
|
+
alter table public.booking_channel_icon_candidate
|
|
86
|
+
drop column if exists height,
|
|
87
|
+
drop column if exists width;
|
|
88
|
+
`.execute(db);
|
|
89
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
create index if not exists reservation_tenant_gl_status_effective_check_in_idx
|
|
7
|
+
on public.reservation (
|
|
8
|
+
tenant_id,
|
|
9
|
+
general_ledger_status,
|
|
10
|
+
effective_check_in desc
|
|
11
|
+
)
|
|
12
|
+
include (id, status, connection_id, source_id, listing_id)
|
|
13
|
+
where status not in ('inactive', 'inquiry');
|
|
14
|
+
`.execute(db);
|
|
15
|
+
|
|
16
|
+
await sql`
|
|
17
|
+
create index if not exists listing_ownership_period_inactive_lookup_idx
|
|
18
|
+
on public.listing_ownership_period (
|
|
19
|
+
tenant_id,
|
|
20
|
+
listing_id,
|
|
21
|
+
start_at,
|
|
22
|
+
end_at
|
|
23
|
+
)
|
|
24
|
+
where set_listing_inactive = true;
|
|
25
|
+
`.execute(db);
|
|
26
|
+
|
|
27
|
+
await sql`
|
|
28
|
+
create index if not exists transaction_tenant_type_status_date_idx
|
|
29
|
+
on accounting.transaction (
|
|
30
|
+
tenant_id,
|
|
31
|
+
type,
|
|
32
|
+
status,
|
|
33
|
+
is_opening_balance,
|
|
34
|
+
date desc
|
|
35
|
+
)
|
|
36
|
+
include (id, account_id, connection_id, source_id, contact_id);
|
|
37
|
+
`.execute(db);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
41
|
+
await sql`
|
|
42
|
+
drop index if exists accounting.transaction_tenant_type_status_date_idx;
|
|
43
|
+
`.execute(db);
|
|
44
|
+
|
|
45
|
+
await sql`
|
|
46
|
+
drop index if exists public.listing_ownership_period_inactive_lookup_idx;
|
|
47
|
+
`.execute(db);
|
|
48
|
+
|
|
49
|
+
await sql`
|
|
50
|
+
drop index if exists public.reservation_tenant_gl_status_effective_check_in_idx;
|
|
51
|
+
`.execute(db);
|
|
52
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
update core.flow_setting
|
|
7
|
+
set value = case value #>> '{}'
|
|
8
|
+
when '"active"' then to_jsonb('active'::text)
|
|
9
|
+
when '"inactive"' then to_jsonb('inactive'::text)
|
|
10
|
+
else value
|
|
11
|
+
end
|
|
12
|
+
where setting_key = 'status'
|
|
13
|
+
and jsonb_typeof(value) = 'string'
|
|
14
|
+
and value #>> '{}' in ('"active"', '"inactive"');
|
|
15
|
+
`.execute(db);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function down(_db: Kysely<any>): Promise<void> {
|
|
19
|
+
// Data repair is intentionally irreversible.
|
|
20
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import { sql } from 'kysely';
|
|
3
|
+
|
|
4
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
5
|
+
await sql`
|
|
6
|
+
alter table public.tenant
|
|
7
|
+
add column slug text;
|
|
8
|
+
`.execute(db);
|
|
9
|
+
|
|
10
|
+
await sql`
|
|
11
|
+
create or replace function public.normalize_tenant_slug(value text)
|
|
12
|
+
returns text
|
|
13
|
+
language sql
|
|
14
|
+
immutable
|
|
15
|
+
as $$
|
|
16
|
+
select trim(
|
|
17
|
+
both '-'
|
|
18
|
+
from regexp_replace(
|
|
19
|
+
regexp_replace(lower(coalesce(value, '')), '[^a-z0-9]+', '-', 'g'),
|
|
20
|
+
'-+',
|
|
21
|
+
'-',
|
|
22
|
+
'g'
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
$$;
|
|
26
|
+
`.execute(db);
|
|
27
|
+
|
|
28
|
+
await sql`
|
|
29
|
+
create or replace function public.build_unique_tenant_slug(
|
|
30
|
+
target_name text,
|
|
31
|
+
target_id uuid
|
|
32
|
+
)
|
|
33
|
+
returns text
|
|
34
|
+
language plpgsql
|
|
35
|
+
as $$
|
|
36
|
+
declare
|
|
37
|
+
reserved text[] := array[
|
|
38
|
+
'admin',
|
|
39
|
+
'api',
|
|
40
|
+
'app',
|
|
41
|
+
'assets',
|
|
42
|
+
'auth',
|
|
43
|
+
'billing',
|
|
44
|
+
'cdn',
|
|
45
|
+
'cloudflare',
|
|
46
|
+
'dev',
|
|
47
|
+
'docs',
|
|
48
|
+
'email',
|
|
49
|
+
'ftp',
|
|
50
|
+
'help',
|
|
51
|
+
'imap',
|
|
52
|
+
'internal',
|
|
53
|
+
'localhost',
|
|
54
|
+
'login',
|
|
55
|
+
'logout',
|
|
56
|
+
'mail',
|
|
57
|
+
'mx',
|
|
58
|
+
'new',
|
|
59
|
+
'ns1',
|
|
60
|
+
'ns2',
|
|
61
|
+
'payments',
|
|
62
|
+
'portal',
|
|
63
|
+
'pop',
|
|
64
|
+
'signup',
|
|
65
|
+
'smtp',
|
|
66
|
+
'sftp',
|
|
67
|
+
'ssh',
|
|
68
|
+
'staging',
|
|
69
|
+
'static',
|
|
70
|
+
'status',
|
|
71
|
+
'support',
|
|
72
|
+
'team',
|
|
73
|
+
'teams',
|
|
74
|
+
'test',
|
|
75
|
+
'vrplatform',
|
|
76
|
+
'worker',
|
|
77
|
+
'workers',
|
|
78
|
+
'www'
|
|
79
|
+
];
|
|
80
|
+
base text;
|
|
81
|
+
candidate text;
|
|
82
|
+
suffix integer := 1;
|
|
83
|
+
suffix_text text;
|
|
84
|
+
begin
|
|
85
|
+
base := public.normalize_tenant_slug(target_name);
|
|
86
|
+
if base = '' then
|
|
87
|
+
base := 'team';
|
|
88
|
+
end if;
|
|
89
|
+
if base = any(reserved) then
|
|
90
|
+
base := left(base, 58) || '-team';
|
|
91
|
+
end if;
|
|
92
|
+
|
|
93
|
+
base := left(base, 63);
|
|
94
|
+
base := trim(both '-' from base);
|
|
95
|
+
if base = '' then
|
|
96
|
+
base := 'team';
|
|
97
|
+
end if;
|
|
98
|
+
|
|
99
|
+
candidate := base;
|
|
100
|
+
while exists (
|
|
101
|
+
select 1
|
|
102
|
+
from public.tenant
|
|
103
|
+
where slug = candidate
|
|
104
|
+
and id <> target_id
|
|
105
|
+
) loop
|
|
106
|
+
suffix := suffix + 1;
|
|
107
|
+
suffix_text := '-' || suffix::text;
|
|
108
|
+
candidate := left(base, 63 - length(suffix_text)) || suffix_text;
|
|
109
|
+
end loop;
|
|
110
|
+
|
|
111
|
+
return candidate;
|
|
112
|
+
end;
|
|
113
|
+
$$;
|
|
114
|
+
`.execute(db);
|
|
115
|
+
|
|
116
|
+
await sql`
|
|
117
|
+
create or replace function public.set_tenant_slug()
|
|
118
|
+
returns trigger
|
|
119
|
+
language plpgsql
|
|
120
|
+
as $$
|
|
121
|
+
declare
|
|
122
|
+
reserved text[] := array[
|
|
123
|
+
'admin',
|
|
124
|
+
'api',
|
|
125
|
+
'app',
|
|
126
|
+
'assets',
|
|
127
|
+
'auth',
|
|
128
|
+
'billing',
|
|
129
|
+
'cdn',
|
|
130
|
+
'cloudflare',
|
|
131
|
+
'dev',
|
|
132
|
+
'docs',
|
|
133
|
+
'email',
|
|
134
|
+
'ftp',
|
|
135
|
+
'help',
|
|
136
|
+
'imap',
|
|
137
|
+
'internal',
|
|
138
|
+
'localhost',
|
|
139
|
+
'login',
|
|
140
|
+
'logout',
|
|
141
|
+
'mail',
|
|
142
|
+
'mx',
|
|
143
|
+
'new',
|
|
144
|
+
'ns1',
|
|
145
|
+
'ns2',
|
|
146
|
+
'payments',
|
|
147
|
+
'portal',
|
|
148
|
+
'pop',
|
|
149
|
+
'signup',
|
|
150
|
+
'smtp',
|
|
151
|
+
'sftp',
|
|
152
|
+
'ssh',
|
|
153
|
+
'staging',
|
|
154
|
+
'static',
|
|
155
|
+
'status',
|
|
156
|
+
'support',
|
|
157
|
+
'team',
|
|
158
|
+
'teams',
|
|
159
|
+
'test',
|
|
160
|
+
'vrplatform',
|
|
161
|
+
'worker',
|
|
162
|
+
'workers',
|
|
163
|
+
'www'
|
|
164
|
+
];
|
|
165
|
+
begin
|
|
166
|
+
if new.slug is null or btrim(new.slug) = '' then
|
|
167
|
+
new.slug := public.build_unique_tenant_slug(new.name, new.id);
|
|
168
|
+
else
|
|
169
|
+
new.slug := public.normalize_tenant_slug(new.slug);
|
|
170
|
+
|
|
171
|
+
if new.slug = '' then
|
|
172
|
+
raise exception 'Tenant slug is required' using errcode = '23514';
|
|
173
|
+
end if;
|
|
174
|
+
if new.slug !~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$' then
|
|
175
|
+
raise exception 'Tenant slug % is invalid', new.slug
|
|
176
|
+
using errcode = '23514';
|
|
177
|
+
end if;
|
|
178
|
+
if new.slug = any(reserved) then
|
|
179
|
+
raise exception 'Tenant slug % is reserved', new.slug
|
|
180
|
+
using errcode = '23514';
|
|
181
|
+
end if;
|
|
182
|
+
if exists (
|
|
183
|
+
select 1
|
|
184
|
+
from public.tenant
|
|
185
|
+
where slug = new.slug
|
|
186
|
+
and id <> new.id
|
|
187
|
+
) then
|
|
188
|
+
raise exception 'Tenant slug % is already in use', new.slug
|
|
189
|
+
using errcode = '23505';
|
|
190
|
+
end if;
|
|
191
|
+
end if;
|
|
192
|
+
|
|
193
|
+
return new;
|
|
194
|
+
end;
|
|
195
|
+
$$;
|
|
196
|
+
`.execute(db);
|
|
197
|
+
|
|
198
|
+
await sql`
|
|
199
|
+
create trigger set_public_tenant_slug
|
|
200
|
+
before insert or update of slug, name on public.tenant
|
|
201
|
+
for each row
|
|
202
|
+
execute function public.set_tenant_slug();
|
|
203
|
+
`.execute(db);
|
|
204
|
+
|
|
205
|
+
await sql`
|
|
206
|
+
do $$
|
|
207
|
+
declare
|
|
208
|
+
tenant_row record;
|
|
209
|
+
candidate text;
|
|
210
|
+
begin
|
|
211
|
+
for tenant_row in
|
|
212
|
+
select id, name
|
|
213
|
+
from public.tenant
|
|
214
|
+
where slug is null or btrim(slug) = ''
|
|
215
|
+
order by created_at asc, id asc
|
|
216
|
+
loop
|
|
217
|
+
candidate := public.build_unique_tenant_slug(
|
|
218
|
+
tenant_row.name,
|
|
219
|
+
tenant_row.id
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
update public.tenant
|
|
223
|
+
set slug = candidate
|
|
224
|
+
where id = tenant_row.id;
|
|
225
|
+
end loop;
|
|
226
|
+
end;
|
|
227
|
+
$$;
|
|
228
|
+
`.execute(db);
|
|
229
|
+
|
|
230
|
+
await sql`
|
|
231
|
+
alter table public.tenant
|
|
232
|
+
alter column slug set not null;
|
|
233
|
+
`.execute(db);
|
|
234
|
+
|
|
235
|
+
await sql`
|
|
236
|
+
alter table public.tenant
|
|
237
|
+
add constraint tenant_slug_format_check
|
|
238
|
+
check (slug ~ '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$');
|
|
239
|
+
`.execute(db);
|
|
240
|
+
|
|
241
|
+
await sql`
|
|
242
|
+
alter table public.tenant
|
|
243
|
+
add constraint tenant_slug_reserved_check
|
|
244
|
+
check (
|
|
245
|
+
slug <> all(array[
|
|
246
|
+
'admin',
|
|
247
|
+
'api',
|
|
248
|
+
'app',
|
|
249
|
+
'assets',
|
|
250
|
+
'auth',
|
|
251
|
+
'billing',
|
|
252
|
+
'cdn',
|
|
253
|
+
'cloudflare',
|
|
254
|
+
'dev',
|
|
255
|
+
'docs',
|
|
256
|
+
'email',
|
|
257
|
+
'ftp',
|
|
258
|
+
'help',
|
|
259
|
+
'imap',
|
|
260
|
+
'internal',
|
|
261
|
+
'localhost',
|
|
262
|
+
'login',
|
|
263
|
+
'logout',
|
|
264
|
+
'mail',
|
|
265
|
+
'mx',
|
|
266
|
+
'new',
|
|
267
|
+
'ns1',
|
|
268
|
+
'ns2',
|
|
269
|
+
'payments',
|
|
270
|
+
'portal',
|
|
271
|
+
'pop',
|
|
272
|
+
'signup',
|
|
273
|
+
'smtp',
|
|
274
|
+
'sftp',
|
|
275
|
+
'ssh',
|
|
276
|
+
'staging',
|
|
277
|
+
'static',
|
|
278
|
+
'status',
|
|
279
|
+
'support',
|
|
280
|
+
'team',
|
|
281
|
+
'teams',
|
|
282
|
+
'test',
|
|
283
|
+
'vrplatform',
|
|
284
|
+
'worker',
|
|
285
|
+
'workers',
|
|
286
|
+
'www'
|
|
287
|
+
])
|
|
288
|
+
);
|
|
289
|
+
`.execute(db);
|
|
290
|
+
|
|
291
|
+
await sql`
|
|
292
|
+
create unique index tenant_slug_unique_idx
|
|
293
|
+
on public.tenant (slug);
|
|
294
|
+
`.execute(db);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
298
|
+
await sql`
|
|
299
|
+
drop index if exists public.tenant_slug_unique_idx;
|
|
300
|
+
`.execute(db);
|
|
301
|
+
|
|
302
|
+
await sql`
|
|
303
|
+
alter table public.tenant
|
|
304
|
+
drop constraint if exists tenant_slug_reserved_check,
|
|
305
|
+
drop constraint if exists tenant_slug_format_check;
|
|
306
|
+
`.execute(db);
|
|
307
|
+
|
|
308
|
+
await sql`
|
|
309
|
+
drop trigger if exists set_public_tenant_slug on public.tenant;
|
|
310
|
+
`.execute(db);
|
|
311
|
+
|
|
312
|
+
await sql`
|
|
313
|
+
drop function if exists public.set_tenant_slug();
|
|
314
|
+
`.execute(db);
|
|
315
|
+
|
|
316
|
+
await sql`
|
|
317
|
+
drop function if exists public.build_unique_tenant_slug(text, uuid);
|
|
318
|
+
`.execute(db);
|
|
319
|
+
|
|
320
|
+
await sql`
|
|
321
|
+
drop function if exists public.normalize_tenant_slug(text);
|
|
322
|
+
`.execute(db);
|
|
323
|
+
|
|
324
|
+
await sql`
|
|
325
|
+
alter table public.tenant
|
|
326
|
+
drop column if exists slug;
|
|
327
|
+
`.execute(db);
|
|
328
|
+
}
|