@supabase/pg-delta 1.0.0-alpha.23 → 1.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/core/catalog.model.d.ts +2 -2
  2. package/dist/core/catalog.model.js +26 -21
  3. package/dist/core/integrations/supabase.js +84 -0
  4. package/dist/core/objects/aggregate/changes/aggregate.privilege.js +21 -9
  5. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.js +4 -1
  6. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.js +6 -3
  7. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.d.ts +11 -0
  8. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +11 -0
  9. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.js +4 -1
  10. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.js +6 -3
  11. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +11 -0
  12. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +11 -0
  13. package/dist/core/objects/foreign-data-wrapper/sensitive-options.d.ts +32 -0
  14. package/dist/core/objects/foreign-data-wrapper/sensitive-options.js +129 -0
  15. package/dist/core/objects/foreign-data-wrapper/server/changes/server.alter.js +4 -1
  16. package/dist/core/objects/foreign-data-wrapper/server/changes/server.create.js +6 -3
  17. package/dist/core/objects/foreign-data-wrapper/server/server.model.d.ts +10 -0
  18. package/dist/core/objects/foreign-data-wrapper/server/server.model.js +10 -0
  19. package/dist/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.js +4 -1
  20. package/dist/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.js +6 -3
  21. package/dist/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.d.ts +10 -0
  22. package/dist/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.js +10 -0
  23. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  24. package/dist/core/objects/table/table.model.js +7 -2
  25. package/dist/core/post-diff-normalization.d.ts +7 -0
  26. package/dist/core/post-diff-normalization.js +33 -4
  27. package/dist/core/sort/cycle-breakers.js +139 -17
  28. package/package.json +1 -1
  29. package/src/core/catalog.model.ts +36 -20
  30. package/src/core/integrations/supabase.test.ts +198 -0
  31. package/src/core/integrations/supabase.ts +84 -0
  32. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +79 -0
  33. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +22 -9
  34. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +34 -4
  35. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +5 -1
  36. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +34 -0
  37. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +7 -5
  38. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +11 -0
  39. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +25 -4
  40. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +5 -1
  41. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +54 -0
  42. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +7 -5
  43. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +11 -0
  44. package/src/core/objects/foreign-data-wrapper/sensitive-options.test.ts +98 -0
  45. package/src/core/objects/foreign-data-wrapper/sensitive-options.ts +133 -0
  46. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +39 -4
  47. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +5 -1
  48. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +36 -0
  49. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +7 -5
  50. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +10 -0
  51. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +39 -6
  52. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +5 -1
  53. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +38 -2
  54. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +7 -5
  55. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +10 -0
  56. package/src/core/objects/table/table.model.ts +7 -2
  57. package/src/core/plan/sql-format/format-off.test.ts +4 -4
  58. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +4 -4
  59. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +5 -4
  60. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +4 -4
  61. package/src/core/plan/sql-format/format-pretty-upper.test.ts +4 -4
  62. package/src/core/post-diff-normalization.test.ts +123 -0
  63. package/src/core/post-diff-normalization.ts +40 -4
  64. package/src/core/sort/cycle-breakers.test.ts +236 -2
  65. package/src/core/sort/cycle-breakers.ts +184 -24
  66. package/src/core/sort/sort-changes.test.ts +317 -0
@@ -0,0 +1,317 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { Catalog, createEmptyCatalog } from "../catalog.model.ts";
3
+ import type { Change } from "../change.types.ts";
4
+ import type { PgDepend } from "../depend.ts";
5
+ import { AlterPublicationDropTables } from "../objects/publication/changes/publication.alter.ts";
6
+ import { Publication } from "../objects/publication/publication.model.ts";
7
+ import { AlterTableDropConstraint } from "../objects/table/changes/table.alter.ts";
8
+ import { DropTable } from "../objects/table/changes/table.drop.ts";
9
+ import { Table } from "../objects/table/table.model.ts";
10
+ import { sortChanges } from "./sort-changes.ts";
11
+
12
+ const baseTableProps = {
13
+ schema: "public",
14
+ persistence: "p" as const,
15
+ row_security: false,
16
+ force_row_security: false,
17
+ has_indexes: false,
18
+ has_rules: false,
19
+ has_triggers: false,
20
+ has_subclasses: false,
21
+ is_populated: true,
22
+ replica_identity: "d" as const,
23
+ is_partition: false,
24
+ options: null,
25
+ partition_bound: null,
26
+ partition_by: null,
27
+ owner: "postgres",
28
+ comment: null,
29
+ parent_schema: null,
30
+ parent_name: null,
31
+ privileges: [],
32
+ };
33
+
34
+ function integerColumn(name: string, position: number) {
35
+ return {
36
+ name,
37
+ position,
38
+ data_type: "integer",
39
+ data_type_str: "integer",
40
+ is_custom_type: false,
41
+ custom_type_type: null,
42
+ custom_type_category: null,
43
+ custom_type_schema: null,
44
+ custom_type_name: null,
45
+ not_null: false,
46
+ is_identity: false,
47
+ is_identity_always: false,
48
+ is_generated: false,
49
+ collation: null,
50
+ default: null,
51
+ comment: null,
52
+ };
53
+ }
54
+
55
+ function fkConstraint(props: {
56
+ name: string;
57
+ fkColumn: string;
58
+ targetTable: string;
59
+ targetColumn?: string;
60
+ }) {
61
+ const targetColumn = props.targetColumn ?? "id";
62
+ return {
63
+ name: props.name,
64
+ constraint_type: "f" as const,
65
+ deferrable: false,
66
+ initially_deferred: false,
67
+ validated: true,
68
+ is_local: true,
69
+ no_inherit: false,
70
+ is_temporal: false,
71
+ is_partition_clone: false,
72
+ parent_constraint_schema: null,
73
+ parent_constraint_name: null,
74
+ parent_table_schema: null,
75
+ parent_table_name: null,
76
+ key_columns: [props.fkColumn],
77
+ foreign_key_columns: [targetColumn],
78
+ foreign_key_table: props.targetTable,
79
+ foreign_key_schema: "public",
80
+ foreign_key_table_is_partition: false,
81
+ foreign_key_parent_schema: null,
82
+ foreign_key_parent_table: null,
83
+ foreign_key_effective_schema: "public",
84
+ foreign_key_effective_table: props.targetTable,
85
+ on_update: "a" as const,
86
+ on_delete: "a" as const,
87
+ match_type: "s" as const,
88
+ check_expression: null,
89
+ owner: "postgres",
90
+ definition: `FOREIGN KEY (${props.fkColumn}) REFERENCES public.${props.targetTable}(${targetColumn})`,
91
+ comment: null,
92
+ };
93
+ }
94
+
95
+ function uniqueConstraint(name: string, column: string) {
96
+ return {
97
+ name,
98
+ constraint_type: "u" as const,
99
+ deferrable: false,
100
+ initially_deferred: false,
101
+ validated: true,
102
+ is_local: true,
103
+ no_inherit: false,
104
+ is_temporal: false,
105
+ is_partition_clone: false,
106
+ parent_constraint_schema: null,
107
+ parent_constraint_name: null,
108
+ parent_table_schema: null,
109
+ parent_table_name: null,
110
+ key_columns: [column],
111
+ foreign_key_columns: null,
112
+ foreign_key_table: null,
113
+ foreign_key_schema: null,
114
+ foreign_key_table_is_partition: null,
115
+ foreign_key_parent_schema: null,
116
+ foreign_key_parent_table: null,
117
+ foreign_key_effective_schema: null,
118
+ foreign_key_effective_table: null,
119
+ on_update: null,
120
+ on_delete: null,
121
+ match_type: null,
122
+ check_expression: null,
123
+ owner: "postgres",
124
+ definition: `UNIQUE (${column})`,
125
+ comment: null,
126
+ };
127
+ }
128
+
129
+ function table(
130
+ name: string,
131
+ constraints: ConstructorParameters<typeof Table>[0]["constraints"] = [],
132
+ ) {
133
+ return new Table({
134
+ ...baseTableProps,
135
+ name,
136
+ columns: [
137
+ { ...integerColumn("id", 1), not_null: true },
138
+ integerColumn("post_id", 2),
139
+ integerColumn("lab_id", 3),
140
+ ],
141
+ constraints,
142
+ });
143
+ }
144
+
145
+ async function catalogWithDepends(depends: PgDepend[]) {
146
+ const base = await createEmptyCatalog(170000, "postgres");
147
+ return new Catalog({ ...base, depends });
148
+ }
149
+
150
+ function changeLabel(change: Change) {
151
+ if (change instanceof AlterTableDropConstraint) {
152
+ return `${change.constructor.name}:${change.table.name}.${change.constraint.name}`;
153
+ }
154
+ if (change instanceof DropTable) {
155
+ return `${change.constructor.name}:${change.table.name}`;
156
+ }
157
+ return change.constructor.name;
158
+ }
159
+
160
+ describe("sortChanges", () => {
161
+ test("breaks publication FK-chain constraint-drop cycle with one dropped table", async () => {
162
+ const labs = table("labs", [uniqueConstraint("unique_lab_id", "id")]);
163
+ const posts = table("posts", [
164
+ fkConstraint({
165
+ name: "posts_lab_id_fkey",
166
+ fkColumn: "lab_id",
167
+ targetTable: "labs",
168
+ }),
169
+ ]);
170
+ const publication = new Publication({
171
+ name: "supabase_realtime",
172
+ owner: "postgres",
173
+ comment: null,
174
+ all_tables: false,
175
+ publish_insert: true,
176
+ publish_update: true,
177
+ publish_delete: true,
178
+ publish_truncate: true,
179
+ publish_via_partition_root: false,
180
+ tables: [
181
+ {
182
+ schema: "public",
183
+ name: "labs",
184
+ columns: null,
185
+ row_filter: null,
186
+ },
187
+ {
188
+ schema: "public",
189
+ name: "posts",
190
+ columns: null,
191
+ row_filter: null,
192
+ },
193
+ ],
194
+ schemas: [],
195
+ });
196
+ const changes: Change[] = [
197
+ new AlterPublicationDropTables({
198
+ publication,
199
+ tables: publication.tables,
200
+ }),
201
+ new DropTable({ table: posts }),
202
+ new AlterTableDropConstraint({
203
+ table: labs,
204
+ constraint: labs.constraints[0],
205
+ }),
206
+ ];
207
+ const mainCatalog = await catalogWithDepends([
208
+ {
209
+ dependent_stable_id: "publication:supabase_realtime",
210
+ referenced_stable_id: "table:public.posts",
211
+ deptype: "n",
212
+ },
213
+ {
214
+ dependent_stable_id: "constraint:public.posts.posts_lab_id_fkey",
215
+ referenced_stable_id: "constraint:public.labs.unique_lab_id",
216
+ deptype: "n",
217
+ },
218
+ ]);
219
+ const branchCatalog = await catalogWithDepends([]);
220
+
221
+ const sorted = sortChanges({ mainCatalog, branchCatalog }, changes);
222
+
223
+ expect(sorted.map(changeLabel)).toContain(
224
+ "AlterTableDropConstraint:posts.posts_lab_id_fkey",
225
+ );
226
+ });
227
+
228
+ test("breaks publication FK-chain constraint-drop cycle in the drop phase", async () => {
229
+ const labs = table("labs", [uniqueConstraint("unique_lab_id", "id")]);
230
+ const posts = table("posts", [
231
+ fkConstraint({
232
+ name: "posts_lab_id_fkey",
233
+ fkColumn: "lab_id",
234
+ targetTable: "labs",
235
+ }),
236
+ ]);
237
+ const postAttachments = table("post_attachments", [
238
+ fkConstraint({
239
+ name: "post_attachments_post_id_fkey",
240
+ fkColumn: "post_id",
241
+ targetTable: "posts",
242
+ }),
243
+ ]);
244
+ const publication = new Publication({
245
+ name: "supabase_realtime",
246
+ owner: "postgres",
247
+ comment: null,
248
+ all_tables: false,
249
+ publish_insert: true,
250
+ publish_update: true,
251
+ publish_delete: true,
252
+ publish_truncate: true,
253
+ publish_via_partition_root: false,
254
+ tables: [
255
+ {
256
+ schema: "public",
257
+ name: "labs",
258
+ columns: null,
259
+ row_filter: null,
260
+ },
261
+ {
262
+ schema: "public",
263
+ name: "post_attachments",
264
+ columns: null,
265
+ row_filter: null,
266
+ },
267
+ {
268
+ schema: "public",
269
+ name: "posts",
270
+ columns: null,
271
+ row_filter: null,
272
+ },
273
+ ],
274
+ schemas: [],
275
+ });
276
+ const changes: Change[] = [
277
+ new AlterPublicationDropTables({
278
+ publication,
279
+ tables: publication.tables,
280
+ }),
281
+ new DropTable({ table: postAttachments }),
282
+ new DropTable({ table: posts }),
283
+ new AlterTableDropConstraint({
284
+ table: labs,
285
+ constraint: labs.constraints[0],
286
+ }),
287
+ ];
288
+ const mainCatalog = await catalogWithDepends([
289
+ {
290
+ dependent_stable_id: "publication:supabase_realtime",
291
+ referenced_stable_id: "table:public.post_attachments",
292
+ deptype: "n",
293
+ },
294
+ {
295
+ dependent_stable_id:
296
+ "constraint:public.post_attachments.post_attachments_post_id_fkey",
297
+ referenced_stable_id: "column:public.posts.id",
298
+ deptype: "n",
299
+ },
300
+ {
301
+ dependent_stable_id: "constraint:public.posts.posts_lab_id_fkey",
302
+ referenced_stable_id: "constraint:public.labs.unique_lab_id",
303
+ deptype: "n",
304
+ },
305
+ ]);
306
+ const branchCatalog = await catalogWithDepends([]);
307
+
308
+ const sorted = sortChanges({ mainCatalog, branchCatalog }, changes);
309
+
310
+ expect(sorted.map(changeLabel)).toContain(
311
+ "AlterTableDropConstraint:post_attachments.post_attachments_post_id_fkey",
312
+ );
313
+ expect(sorted.map(changeLabel)).toContain(
314
+ "AlterTableDropConstraint:posts.posts_lab_id_fkey",
315
+ );
316
+ });
317
+ });