neon 8.4.4 → 8.5.0

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 (75) hide show
  1. package/README.md +11 -11
  2. package/dist/_chunks/{env-4WGRW2nw.js → env-BNm69Qh8.js} +2 -5
  3. package/dist/commands/config.js +11 -28
  4. package/dist/commands/dev.js +3 -3
  5. package/dist/commands/env.js +2 -3
  6. package/dist/commands/index.js +0 -2
  7. package/dist/commands/init.js +1 -2
  8. package/dist/commands/manifest.js +2 -10
  9. package/dist/commands/realtime.js +2 -1
  10. package/dist/commands/subscribe.js +24 -43
  11. package/dist/credential_io.js +1 -2
  12. package/dist/dev/env.js +1 -2
  13. package/dist/index.js +2 -2
  14. package/dist/init/run.js +1 -2
  15. package/dist/plugins/run.js +2 -1
  16. package/dist/psql/command/cmd_io.js +1 -2
  17. package/dist/psql/command/cmd_pipeline.js +1 -2
  18. package/dist/psql/core/common.js +1 -2
  19. package/dist/psql/core/startup.js +1 -2
  20. package/dist/psql/index.js +1 -2
  21. package/dist/psql/types/index.js +1 -2
  22. package/dist/skills/catalog.js +5 -0
  23. package/dist/utils/hooks.js +0 -2
  24. package/dist/utils/staging.js +1 -14
  25. package/{LICENSE → dist/vendor/postgres-meta/LICENSE} +0 -1
  26. package/dist/vendor/postgres-meta/constants.js +14 -0
  27. package/dist/vendor/postgres-meta/lib/PostgresMeta.js +49 -0
  28. package/dist/vendor/postgres-meta/lib/PostgresMetaColumnPrivileges.js +85 -0
  29. package/dist/vendor/postgres-meta/lib/PostgresMetaColumns.js +235 -0
  30. package/dist/vendor/postgres-meta/lib/PostgresMetaConfig.js +16 -0
  31. package/dist/vendor/postgres-meta/lib/PostgresMetaExtensions.js +79 -0
  32. package/dist/vendor/postgres-meta/lib/PostgresMetaForeignTables.js +81 -0
  33. package/dist/vendor/postgres-meta/lib/PostgresMetaFunctions.js +173 -0
  34. package/dist/vendor/postgres-meta/lib/PostgresMetaIndexes.js +42 -0
  35. package/dist/vendor/postgres-meta/lib/PostgresMetaMaterializedViews.js +84 -0
  36. package/dist/vendor/postgres-meta/lib/PostgresMetaPolicies.js +120 -0
  37. package/dist/vendor/postgres-meta/lib/PostgresMetaPublications.js +193 -0
  38. package/dist/vendor/postgres-meta/lib/PostgresMetaRelationships.js +87 -0
  39. package/dist/vendor/postgres-meta/lib/PostgresMetaRoles.js +203 -0
  40. package/dist/vendor/postgres-meta/lib/PostgresMetaSchemas.js +105 -0
  41. package/dist/vendor/postgres-meta/lib/PostgresMetaTablePrivileges.js +91 -0
  42. package/dist/vendor/postgres-meta/lib/PostgresMetaTables.js +183 -0
  43. package/dist/vendor/postgres-meta/lib/PostgresMetaTriggers.js +156 -0
  44. package/dist/vendor/postgres-meta/lib/PostgresMetaTypes.js +22 -0
  45. package/dist/vendor/postgres-meta/lib/PostgresMetaVersion.js +20 -0
  46. package/dist/vendor/postgres-meta/lib/PostgresMetaViews.js +83 -0
  47. package/dist/vendor/postgres-meta/lib/constants.js +8 -0
  48. package/dist/vendor/postgres-meta/lib/db.js +147 -0
  49. package/dist/vendor/postgres-meta/lib/generators.js +106 -0
  50. package/dist/vendor/postgres-meta/lib/helpers.js +26 -0
  51. package/dist/vendor/postgres-meta/lib/index.js +1 -0
  52. package/dist/vendor/postgres-meta/lib/sql/column_privileges.sql.js +154 -0
  53. package/dist/vendor/postgres-meta/lib/sql/columns.sql.js +123 -0
  54. package/dist/vendor/postgres-meta/lib/sql/common.js +1 -0
  55. package/dist/vendor/postgres-meta/lib/sql/config.sql.js +32 -0
  56. package/dist/vendor/postgres-meta/lib/sql/extensions.sql.js +20 -0
  57. package/dist/vendor/postgres-meta/lib/sql/foreign_tables.sql.js +20 -0
  58. package/dist/vendor/postgres-meta/lib/sql/functions.sql.js +141 -0
  59. package/dist/vendor/postgres-meta/lib/sql/indexes.sql.js +51 -0
  60. package/dist/vendor/postgres-meta/lib/sql/materialized_views.sql.js +21 -0
  61. package/dist/vendor/postgres-meta/lib/sql/policies.sql.js +53 -0
  62. package/dist/vendor/postgres-meta/lib/sql/publications.sql.js +46 -0
  63. package/dist/vendor/postgres-meta/lib/sql/roles.sql.js +40 -0
  64. package/dist/vendor/postgres-meta/lib/sql/schemas.sql.js +26 -0
  65. package/dist/vendor/postgres-meta/lib/sql/table.sql.js +109 -0
  66. package/dist/vendor/postgres-meta/lib/sql/table_privileges.sql.js +85 -0
  67. package/dist/vendor/postgres-meta/lib/sql/table_relationships.sql.js +52 -0
  68. package/dist/vendor/postgres-meta/lib/sql/triggers.sql.js +64 -0
  69. package/dist/vendor/postgres-meta/lib/sql/types.sql.js +65 -0
  70. package/dist/vendor/postgres-meta/lib/sql/version.sql.js +15 -0
  71. package/dist/vendor/postgres-meta/lib/sql/views.sql.js +22 -0
  72. package/dist/vendor/postgres-meta/lib/sql/views_key_dependencies.sql.js +198 -0
  73. package/dist/vendor/postgres-meta/lib/types.js +1 -0
  74. package/dist/vendor/postgres-meta/templates/typescript.js +608 -0
  75. package/package.json +16 -8
@@ -0,0 +1,173 @@
1
+ import { DEFAULT_SYSTEM_SCHEMAS } from "./constants.js";
2
+ import { filterByList, filterByValue } from "./helpers.js";
3
+ import { FUNCTIONS_SQL } from "./sql/functions.sql.js";
4
+ import { ident, literal } from "pg-format";
5
+ //#region src/vendor/postgres-meta/lib/PostgresMetaFunctions.ts
6
+ var PostgresMetaFunctions = class {
7
+ constructor(query) {
8
+ this.query = query;
9
+ }
10
+ async list({ includeSystemSchemas = false, includedSchemas, excludedSchemas, limit, offset } = {}) {
11
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : void 0);
12
+ const sql = FUNCTIONS_SQL({
13
+ schemaFilter,
14
+ limit,
15
+ offset
16
+ });
17
+ return await this.query(sql);
18
+ }
19
+ async retrieve({ id, name, schema = "public", args = [] }) {
20
+ const schemaFilter = schema ? filterByList([schema], []) : void 0;
21
+ if (id) {
22
+ const idsFilter = filterByValue([id]);
23
+ const sql = FUNCTIONS_SQL({ idsFilter });
24
+ const { data, error } = await this.query(sql);
25
+ if (error) return {
26
+ data,
27
+ error
28
+ };
29
+ else if (data.length === 0) return {
30
+ data: null,
31
+ error: { message: `Cannot find a function with ID ${id}` }
32
+ };
33
+ else return {
34
+ data: data[0],
35
+ error
36
+ };
37
+ } else if (name && schema && args) {
38
+ const nameFilter = filterByValue([name]);
39
+ const sql = FUNCTIONS_SQL({
40
+ schemaFilter,
41
+ nameFilter,
42
+ args: args.map(literal)
43
+ });
44
+ const { data, error } = await this.query(sql);
45
+ if (error) return {
46
+ data,
47
+ error
48
+ };
49
+ else if (data.length === 0) return {
50
+ data: null,
51
+ error: { message: `Cannot find function "${schema}"."${name}"(${args.join(", ")})` }
52
+ };
53
+ else return {
54
+ data: data[0],
55
+ error
56
+ };
57
+ } else return {
58
+ data: null,
59
+ error: { message: "Invalid parameters on function retrieve" }
60
+ };
61
+ }
62
+ async create({ name, schema = "public", args = [], definition, return_type = "void", language = "sql", behavior = "VOLATILE", security_definer = false, config_params = {} }) {
63
+ const sql = this.generateCreateFunctionSql({
64
+ name,
65
+ schema,
66
+ args,
67
+ definition,
68
+ return_type,
69
+ language,
70
+ behavior,
71
+ security_definer,
72
+ config_params
73
+ });
74
+ const { error } = await this.query(sql);
75
+ if (error) return {
76
+ data: null,
77
+ error
78
+ };
79
+ return await this.retrieve({
80
+ name,
81
+ schema,
82
+ args
83
+ });
84
+ }
85
+ async update(id, { name, schema, definition }) {
86
+ const { data: currentFunc, error } = await this.retrieve({ id });
87
+ if (error) return {
88
+ data: null,
89
+ error
90
+ };
91
+ const args = currentFunc.argument_types.split(", ");
92
+ const identityArgs = currentFunc.identity_argument_types;
93
+ const updateDefinitionSql = typeof definition === "string" ? this.generateCreateFunctionSql({
94
+ ...currentFunc,
95
+ definition,
96
+ args,
97
+ config_params: currentFunc.config_params ?? {}
98
+ }, { replace: true }) : "";
99
+ const updateNameSql = name && name !== currentFunc.name ? `ALTER FUNCTION ${ident(currentFunc.schema)}.${ident(currentFunc.name)}(${identityArgs}) RENAME TO ${ident(name)};` : "";
100
+ const updateSchemaSql = schema && schema !== currentFunc.schema ? `ALTER FUNCTION ${ident(currentFunc.schema)}.${ident(name || currentFunc.name)}(${identityArgs}) SET SCHEMA ${ident(schema)};` : "";
101
+ const currentSchemaFilter = currentFunc.schema ? filterByList([currentFunc.schema], []) : void 0;
102
+ const currentNameFilter = currentFunc.name ? filterByValue([currentFunc.name]) : void 0;
103
+ const sql = `
104
+ DO LANGUAGE plpgsql $$
105
+ BEGIN
106
+ IF ${typeof definition === "string" ? "TRUE" : "FALSE"} THEN
107
+ ${updateDefinitionSql}
108
+
109
+ IF (
110
+ SELECT id
111
+ FROM (${FUNCTIONS_SQL({
112
+ schemaFilter: currentSchemaFilter,
113
+ nameFilter: currentNameFilter
114
+ })}) AS f
115
+ WHERE f.schema = ${literal(currentFunc.schema)}
116
+ AND f.name = ${literal(currentFunc.name)}
117
+ AND f.identity_argument_types = ${literal(identityArgs)}
118
+ ) != ${id} THEN
119
+ RAISE EXCEPTION 'Cannot find function "${currentFunc.schema}"."${currentFunc.name}"(${identityArgs})';
120
+ END IF;
121
+ END IF;
122
+
123
+ ${updateNameSql}
124
+
125
+ ${updateSchemaSql}
126
+ END;
127
+ $$;
128
+ `;
129
+ {
130
+ const { error } = await this.query(sql);
131
+ if (error) return {
132
+ data: null,
133
+ error
134
+ };
135
+ }
136
+ return await this.retrieve({ id });
137
+ }
138
+ async remove(id, { cascade = false } = {}) {
139
+ const { data: func, error } = await this.retrieve({ id });
140
+ if (error) return {
141
+ data: null,
142
+ error
143
+ };
144
+ const sql = `DROP FUNCTION ${ident(func.schema)}.${ident(func.name)}
145
+ (${func.identity_argument_types})
146
+ ${cascade ? "CASCADE" : "RESTRICT"};`;
147
+ {
148
+ const { error } = await this.query(sql);
149
+ if (error) return {
150
+ data: null,
151
+ error
152
+ };
153
+ }
154
+ return {
155
+ data: func,
156
+ error: null
157
+ };
158
+ }
159
+ generateCreateFunctionSql({ name, schema, args, definition, return_type, language, behavior, security_definer, config_params }, { replace = false } = {}) {
160
+ return `
161
+ CREATE ${replace ? "OR REPLACE" : ""} FUNCTION ${ident(schema)}.${ident(name)}(${args?.join(", ") || ""})
162
+ RETURNS ${return_type}
163
+ AS ${literal(definition)}
164
+ LANGUAGE ${language}
165
+ ${behavior}
166
+ CALLED ON NULL INPUT
167
+ ${security_definer ? "SECURITY DEFINER" : "SECURITY INVOKER"}
168
+ ${config_params ? Object.entries(config_params).map(([param, value]) => `SET ${param} ${value[0] === "FROM CURRENT" ? "FROM CURRENT" : "TO " + value}`).join("\n") : ""};
169
+ `;
170
+ }
171
+ };
172
+ //#endregion
173
+ export { PostgresMetaFunctions as default };
@@ -0,0 +1,42 @@
1
+ import { DEFAULT_SYSTEM_SCHEMAS } from "./constants.js";
2
+ import { filterByList, filterByValue } from "./helpers.js";
3
+ import { INDEXES_SQL } from "./sql/indexes.sql.js";
4
+ //#region src/vendor/postgres-meta/lib/PostgresMetaIndexes.ts
5
+ var PostgresMetaIndexes = class {
6
+ constructor(query) {
7
+ this.query = query;
8
+ }
9
+ async list({ includeSystemSchemas = false, includedSchemas, excludedSchemas, limit, offset } = {}) {
10
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : void 0);
11
+ const sql = INDEXES_SQL({
12
+ schemaFilter,
13
+ limit,
14
+ offset
15
+ });
16
+ return await this.query(sql);
17
+ }
18
+ async retrieve({ id }) {
19
+ if (id) {
20
+ const idsFilter = filterByValue([id]);
21
+ const sql = INDEXES_SQL({ idsFilter });
22
+ const { data, error } = await this.query(sql);
23
+ if (error) return {
24
+ data,
25
+ error
26
+ };
27
+ else if (data.length === 0) return {
28
+ data: null,
29
+ error: { message: `Cannot find a index with ID ${id}` }
30
+ };
31
+ else return {
32
+ data: data[0],
33
+ error
34
+ };
35
+ } else return {
36
+ data: null,
37
+ error: { message: "Invalid parameters on function retrieve" }
38
+ };
39
+ }
40
+ };
41
+ //#endregion
42
+ export { PostgresMetaIndexes as default };
@@ -0,0 +1,84 @@
1
+ import { coalesceRowsToArray, filterByList, filterByValue } from "./helpers.js";
2
+ import { COLUMNS_SQL } from "./sql/columns.sql.js";
3
+ import { MATERIALIZED_VIEWS_SQL } from "./sql/materialized_views.sql.js";
4
+ //#region src/vendor/postgres-meta/lib/PostgresMetaMaterializedViews.ts
5
+ var PostgresMetaMaterializedViews = class {
6
+ constructor(query) {
7
+ this.query = query;
8
+ }
9
+ async list({ includedSchemas, excludedSchemas, limit, offset, includeColumns = false } = {}) {
10
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, void 0);
11
+ let sql = generateEnrichedMaterializedViewsSql({
12
+ includeColumns,
13
+ schemaFilter,
14
+ limit,
15
+ offset
16
+ });
17
+ return await this.query(sql);
18
+ }
19
+ async retrieve({ id, name, schema = "public" }) {
20
+ if (id) {
21
+ const idsFilter = filterByValue([id]);
22
+ const sql = generateEnrichedMaterializedViewsSql({
23
+ includeColumns: true,
24
+ idsFilter
25
+ });
26
+ const { data, error } = await this.query(sql);
27
+ if (error) return {
28
+ data,
29
+ error
30
+ };
31
+ else if (data.length === 0) return {
32
+ data: null,
33
+ error: { message: `Cannot find a materialized view with ID ${id}` }
34
+ };
35
+ else return {
36
+ data: data[0],
37
+ error
38
+ };
39
+ } else if (name) {
40
+ const materializedViewIdentifierFilter = filterByValue([`${schema}.${name}`]);
41
+ const sql = generateEnrichedMaterializedViewsSql({
42
+ includeColumns: true,
43
+ materializedViewIdentifierFilter
44
+ });
45
+ const { data, error } = await this.query(sql);
46
+ if (error) return {
47
+ data,
48
+ error
49
+ };
50
+ else if (data.length === 0) return {
51
+ data: null,
52
+ error: { message: `Cannot find a materialized view named ${name} in schema ${schema}` }
53
+ };
54
+ else return {
55
+ data: data[0],
56
+ error
57
+ };
58
+ } else return {
59
+ data: null,
60
+ error: { message: "Invalid parameters on materialized view retrieve" }
61
+ };
62
+ }
63
+ };
64
+ const generateEnrichedMaterializedViewsSql = ({ includeColumns, schemaFilter, materializedViewIdentifierFilter, idsFilter, limit, offset }) => `
65
+ with materialized_views as (${MATERIALIZED_VIEWS_SQL({
66
+ schemaFilter,
67
+ limit,
68
+ offset,
69
+ materializedViewIdentifierFilter,
70
+ idsFilter
71
+ })})
72
+ ${includeColumns ? `, columns as (${COLUMNS_SQL({
73
+ schemaFilter,
74
+ limit,
75
+ offset,
76
+ tableIdentifierFilter: materializedViewIdentifierFilter,
77
+ tableIdFilter: idsFilter
78
+ })})` : ""}
79
+ select
80
+ *
81
+ ${includeColumns ? `, ${coalesceRowsToArray("columns", "columns.table_id = materialized_views.id")}` : ""}
82
+ from materialized_views`;
83
+ //#endregion
84
+ export { PostgresMetaMaterializedViews as default };
@@ -0,0 +1,120 @@
1
+ import { DEFAULT_SYSTEM_SCHEMAS } from "./constants.js";
2
+ import { filterByList, filterByValue } from "./helpers.js";
3
+ import { POLICIES_SQL } from "./sql/policies.sql.js";
4
+ import { ident } from "pg-format";
5
+ //#region src/vendor/postgres-meta/lib/PostgresMetaPolicies.ts
6
+ var PostgresMetaPolicies = class {
7
+ constructor(query) {
8
+ this.query = query;
9
+ }
10
+ async list({ includeSystemSchemas = false, includedSchemas, excludedSchemas, limit, offset } = {}) {
11
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : void 0);
12
+ let sql = POLICIES_SQL({
13
+ schemaFilter,
14
+ limit,
15
+ offset
16
+ });
17
+ return await this.query(sql);
18
+ }
19
+ async retrieve({ id, name, table, schema = "public" }) {
20
+ const schemaFilter = schema ? filterByList([schema], []) : void 0;
21
+ if (id) {
22
+ const idsFilter = filterByValue([`${id}`]);
23
+ const sql = POLICIES_SQL({ idsFilter });
24
+ const { data, error } = await this.query(sql);
25
+ if (error) return {
26
+ data,
27
+ error
28
+ };
29
+ else if (data.length === 0) return {
30
+ data: null,
31
+ error: { message: `Cannot find a policy with ID ${id}` }
32
+ };
33
+ else return {
34
+ data: data[0],
35
+ error
36
+ };
37
+ } else if (name && table) {
38
+ const functionNameIdentifierFilter = filterByValue([`${table}.${name}`]);
39
+ const sql = POLICIES_SQL({
40
+ schemaFilter,
41
+ functionNameIdentifierFilter
42
+ });
43
+ const { data, error } = await this.query(sql);
44
+ if (error) return {
45
+ data,
46
+ error
47
+ };
48
+ else if (data.length === 0) return {
49
+ data: null,
50
+ error: { message: `Cannot find a policy named ${name} for table ${schema}.${table}` }
51
+ };
52
+ else return {
53
+ data: data[0],
54
+ error
55
+ };
56
+ } else return {
57
+ data: null,
58
+ error: { message: "Invalid parameters on policy retrieve" }
59
+ };
60
+ }
61
+ async create({ name, table, schema = "public", definition, check, action = "PERMISSIVE", command = "ALL", roles = ["public"] }) {
62
+ const definitionClause = definition === void 0 ? "" : `USING (${definition})`;
63
+ const checkClause = check === void 0 ? "" : `WITH CHECK (${check})`;
64
+ const sql = `
65
+ CREATE POLICY ${ident(name)} ON ${ident(schema)}.${ident(table)}
66
+ AS ${action}
67
+ FOR ${command}
68
+ TO ${roles.map(ident).join(",")}
69
+ ${definitionClause} ${checkClause};`;
70
+ const { error } = await this.query(sql);
71
+ if (error) return {
72
+ data: null,
73
+ error
74
+ };
75
+ return await this.retrieve({
76
+ name,
77
+ table,
78
+ schema
79
+ });
80
+ }
81
+ async update(id, { name, definition, check, roles }) {
82
+ const { data: old, error } = await this.retrieve({ id });
83
+ if (error) return {
84
+ data: null,
85
+ error
86
+ };
87
+ const alter = `ALTER POLICY ${ident(old.name)} ON ${ident(old.schema)}.${ident(old.table)}`;
88
+ const nameSql = name === void 0 ? "" : `${alter} RENAME TO ${ident(name)};`;
89
+ const sql = `BEGIN; ${definition === void 0 ? "" : `${alter} USING (${definition});`} ${check === void 0 ? "" : `${alter} WITH CHECK (${check});`} ${roles === void 0 ? "" : `${alter} TO ${roles.map(ident).join(",")};`} ${nameSql} COMMIT;`;
90
+ {
91
+ const { error } = await this.query(sql);
92
+ if (error) return {
93
+ data: null,
94
+ error
95
+ };
96
+ }
97
+ return await this.retrieve({ id });
98
+ }
99
+ async remove(id) {
100
+ const { data: policy, error } = await this.retrieve({ id });
101
+ if (error) return {
102
+ data: null,
103
+ error
104
+ };
105
+ const sql = `DROP POLICY ${ident(policy.name)} ON ${ident(policy.schema)}.${ident(policy.table)};`;
106
+ {
107
+ const { error } = await this.query(sql);
108
+ if (error) return {
109
+ data: null,
110
+ error
111
+ };
112
+ }
113
+ return {
114
+ data: policy,
115
+ error: null
116
+ };
117
+ }
118
+ };
119
+ //#endregion
120
+ export { PostgresMetaPolicies as default };
@@ -0,0 +1,193 @@
1
+ import { filterByValue } from "./helpers.js";
2
+ import { PUBLICATIONS_SQL } from "./sql/publications.sql.js";
3
+ import { ident, literal } from "pg-format";
4
+ //#region src/vendor/postgres-meta/lib/PostgresMetaPublications.ts
5
+ var PostgresMetaPublications = class {
6
+ constructor(query) {
7
+ this.query = query;
8
+ }
9
+ async list({ limit, offset }) {
10
+ let sql = PUBLICATIONS_SQL({
11
+ limit,
12
+ offset
13
+ });
14
+ return await this.query(sql);
15
+ }
16
+ async retrieve({ id, name }) {
17
+ if (id) {
18
+ const idsFilter = filterByValue([id]);
19
+ const sql = PUBLICATIONS_SQL({ idsFilter });
20
+ const { data, error } = await this.query(sql);
21
+ if (error) return {
22
+ data,
23
+ error
24
+ };
25
+ else if (data.length === 0) return {
26
+ data: null,
27
+ error: { message: `Cannot find a publication with ID ${id}` }
28
+ };
29
+ else return {
30
+ data: data[0],
31
+ error
32
+ };
33
+ } else if (name) {
34
+ const nameFilter = filterByValue([name]);
35
+ const sql = PUBLICATIONS_SQL({ nameFilter });
36
+ const { data, error } = await this.query(sql);
37
+ if (error) return {
38
+ data,
39
+ error
40
+ };
41
+ else if (data.length === 0) return {
42
+ data: null,
43
+ error: { message: `Cannot find a publication named ${name}` }
44
+ };
45
+ else return {
46
+ data: data[0],
47
+ error
48
+ };
49
+ } else return {
50
+ data: null,
51
+ error: { message: "Invalid parameters on publication retrieve" }
52
+ };
53
+ }
54
+ async create({ name, publish_insert = false, publish_update = false, publish_delete = false, publish_truncate = false, tables = null }) {
55
+ let tableClause;
56
+ if (tables === void 0 || tables === null) tableClause = "FOR ALL TABLES";
57
+ else if (tables.length === 0) tableClause = "";
58
+ else tableClause = `FOR TABLE ${tables.map((t) => {
59
+ if (!t.includes(".")) return ident(t);
60
+ const [schema, ...rest] = t.split(".");
61
+ const table = rest.join(".");
62
+ return `${ident(schema)}.${ident(table)}`;
63
+ }).join(",")}`;
64
+ let publishOps = [];
65
+ if (publish_insert) publishOps.push("insert");
66
+ if (publish_update) publishOps.push("update");
67
+ if (publish_delete) publishOps.push("delete");
68
+ if (publish_truncate) publishOps.push("truncate");
69
+ const sql = `
70
+ CREATE PUBLICATION ${ident(name)} ${tableClause}
71
+ WITH (publish = '${publishOps.join(",")}');`;
72
+ const { error } = await this.query(sql);
73
+ if (error) return {
74
+ data: null,
75
+ error
76
+ };
77
+ return await this.retrieve({ name });
78
+ }
79
+ async update(id, { name, owner, publish_insert, publish_update, publish_delete, publish_truncate, tables }) {
80
+ const sql = `
81
+ do $$
82
+ declare
83
+ id oid := ${literal(id)};
84
+ old record;
85
+ new_name text := ${name === void 0 ? null : literal(name)};
86
+ new_owner text := ${owner === void 0 ? null : literal(owner)};
87
+ new_publish_insert bool := ${publish_insert ?? null};
88
+ new_publish_update bool := ${publish_update ?? null};
89
+ new_publish_delete bool := ${publish_delete ?? null};
90
+ new_publish_truncate bool := ${publish_truncate ?? null};
91
+ new_tables text := ${tables === void 0 ? null : literal(tables === null ? "all tables" : tables.map((t) => {
92
+ if (!t.includes(".")) return ident(t);
93
+ const [schema, ...rest] = t.split(".");
94
+ const table = rest.join(".");
95
+ return `${ident(schema)}.${ident(table)}`;
96
+ }).join(","))};
97
+ begin
98
+ select * into old from pg_publication where oid = id;
99
+ if old is null then
100
+ raise exception 'Cannot find publication with id %', id;
101
+ end if;
102
+
103
+ if new_tables is null then
104
+ null;
105
+ elsif new_tables = 'all tables' then
106
+ if old.puballtables then
107
+ null;
108
+ else
109
+ -- Need to recreate because going from list of tables <-> all tables with alter is not possible.
110
+ execute(format('drop publication %1$I; create publication %1$I for all tables;', old.pubname));
111
+ end if;
112
+ else
113
+ if old.puballtables then
114
+ -- Need to recreate because going from list of tables <-> all tables with alter is not possible.
115
+ execute(format('drop publication %1$I; create publication %1$I;', old.pubname));
116
+ elsif exists(select from pg_publication_rel where prpubid = id) then
117
+ execute(
118
+ format(
119
+ 'alter publication %I drop table %s',
120
+ old.pubname,
121
+ (select string_agg(prrelid::regclass::text, ', ') from pg_publication_rel where prpubid = id)
122
+ )
123
+ );
124
+ end if;
125
+
126
+ -- At this point the publication must have no tables.
127
+
128
+ if new_tables != '' then
129
+ execute(format('alter publication %I add table %s', old.pubname, new_tables));
130
+ end if;
131
+ end if;
132
+
133
+ execute(
134
+ format(
135
+ 'alter publication %I set (publish = %L);',
136
+ old.pubname,
137
+ concat_ws(
138
+ ', ',
139
+ case when coalesce(new_publish_insert, old.pubinsert) then 'insert' end,
140
+ case when coalesce(new_publish_update, old.pubupdate) then 'update' end,
141
+ case when coalesce(new_publish_delete, old.pubdelete) then 'delete' end,
142
+ case when coalesce(new_publish_truncate, old.pubtruncate) then 'truncate' end
143
+ )
144
+ )
145
+ );
146
+
147
+ execute(format('alter publication %I owner to %I;', old.pubname, coalesce(new_owner, old.pubowner::regrole::name)));
148
+
149
+ -- Using the same name in the rename clause gives an error, so only do it if the new name is different.
150
+ if new_name is not null and new_name != old.pubname then
151
+ execute(format('alter publication %I rename to %I;', old.pubname, coalesce(new_name, old.pubname)));
152
+ end if;
153
+
154
+ -- We need to retrieve the publication later, so we need a way to uniquely identify which publication this is.
155
+ -- We can't rely on id because it gets changed if it got recreated.
156
+ -- We use a temp table to store the unique name - DO blocks can't return a value.
157
+ create temp table pg_meta_publication_tmp (name) on commit drop as values (coalesce(new_name, old.pubname));
158
+ end $$;
159
+
160
+ with publications as (${PUBLICATIONS_SQL({})}) select * from publications where name = (select name from pg_meta_publication_tmp);
161
+ `;
162
+ const { data, error } = await this.query(sql);
163
+ if (error) return {
164
+ data: null,
165
+ error
166
+ };
167
+ return {
168
+ data: data[0],
169
+ error
170
+ };
171
+ }
172
+ async remove(id) {
173
+ const { data: publication, error } = await this.retrieve({ id });
174
+ if (error) return {
175
+ data: null,
176
+ error
177
+ };
178
+ const sql = `DROP PUBLICATION IF EXISTS ${ident(publication.name)};`;
179
+ {
180
+ const { error } = await this.query(sql);
181
+ if (error) return {
182
+ data: null,
183
+ error
184
+ };
185
+ }
186
+ return {
187
+ data: publication,
188
+ error: null
189
+ };
190
+ }
191
+ };
192
+ //#endregion
193
+ export { PostgresMetaPublications as default };
@@ -0,0 +1,87 @@
1
+ import { DEFAULT_SYSTEM_SCHEMAS } from "./constants.js";
2
+ import { filterByList } from "./helpers.js";
3
+ import { TABLE_RELATIONSHIPS_SQL } from "./sql/table_relationships.sql.js";
4
+ import { VIEWS_KEY_DEPENDENCIES_SQL } from "./sql/views_key_dependencies.sql.js";
5
+ //#region src/vendor/postgres-meta/lib/PostgresMetaRelationships.ts
6
+ var PostgresMetaRelationships = class {
7
+ constructor(query) {
8
+ this.query = query;
9
+ }
10
+ async list({ includeSystemSchemas = false, includedSchemas, excludedSchemas } = {}) {
11
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : void 0);
12
+ let allTableM2oAndO2oRelationships;
13
+ {
14
+ const sql = TABLE_RELATIONSHIPS_SQL({ schemaFilter });
15
+ const { data, error } = await this.query(sql);
16
+ if (error) return {
17
+ data: null,
18
+ error
19
+ };
20
+ allTableM2oAndO2oRelationships = data;
21
+ }
22
+ let allViewM2oAndO2oRelationships;
23
+ {
24
+ const viewsKeyDependenciesSql = VIEWS_KEY_DEPENDENCIES_SQL({ schemaFilter });
25
+ const { data: viewsKeyDependencies, error } = await this.query(viewsKeyDependenciesSql);
26
+ if (error) return {
27
+ data: null,
28
+ error
29
+ };
30
+ allViewM2oAndO2oRelationships = allTableM2oAndO2oRelationships.flatMap((r) => {
31
+ const expandKeyDepCols = (colDeps) => {
32
+ const tableColumns = colDeps.map(({ table_column }) => table_column);
33
+ const cartesianProduct = (allEntries) => {
34
+ return allEntries.reduce((results, entries) => results.map((result) => entries.map((entry) => result.concat(entry))).reduce((subResults, result) => subResults.concat(result), []), [[]]);
35
+ };
36
+ return cartesianProduct(colDeps.map((cd) => cd.view_columns)).map((viewColumns) => ({
37
+ tableColumns,
38
+ viewColumns
39
+ }));
40
+ };
41
+ const viewToTableKeyDeps = viewsKeyDependencies.filter((vkd) => vkd.table_schema === r.schema && vkd.table_name === r.relation && vkd.constraint_name === r.foreign_key_name && vkd.constraint_type === "f");
42
+ const tableToViewKeyDeps = viewsKeyDependencies.filter((vkd) => vkd.table_schema === r.referenced_schema && vkd.table_name === r.referenced_relation && vkd.constraint_name === r.foreign_key_name && vkd.constraint_type === "f_ref");
43
+ const viewToTableRelationships = viewToTableKeyDeps.flatMap((vtkd) => expandKeyDepCols(vtkd.column_dependencies).map(({ viewColumns }) => ({
44
+ foreign_key_name: r.foreign_key_name,
45
+ schema: vtkd.view_schema,
46
+ relation: vtkd.view_name,
47
+ columns: viewColumns,
48
+ is_one_to_one: r.is_one_to_one,
49
+ referenced_schema: r.referenced_schema,
50
+ referenced_relation: r.referenced_relation,
51
+ referenced_columns: r.referenced_columns
52
+ })));
53
+ const tableToViewRelationships = tableToViewKeyDeps.flatMap((tvkd) => expandKeyDepCols(tvkd.column_dependencies).map(({ viewColumns }) => ({
54
+ foreign_key_name: r.foreign_key_name,
55
+ schema: r.schema,
56
+ relation: r.relation,
57
+ columns: r.columns,
58
+ is_one_to_one: r.is_one_to_one,
59
+ referenced_schema: tvkd.view_schema,
60
+ referenced_relation: tvkd.view_name,
61
+ referenced_columns: viewColumns
62
+ })));
63
+ const viewToViewRelationships = viewToTableKeyDeps.flatMap((vtkd) => expandKeyDepCols(vtkd.column_dependencies).flatMap(({ viewColumns }) => tableToViewKeyDeps.flatMap((tvkd) => expandKeyDepCols(tvkd.column_dependencies).map(({ viewColumns: referencedViewColumns }) => ({
64
+ foreign_key_name: r.foreign_key_name,
65
+ schema: vtkd.view_schema,
66
+ relation: vtkd.view_name,
67
+ columns: viewColumns,
68
+ is_one_to_one: r.is_one_to_one,
69
+ referenced_schema: tvkd.view_schema,
70
+ referenced_relation: tvkd.view_name,
71
+ referenced_columns: referencedViewColumns
72
+ })))));
73
+ return [
74
+ ...viewToTableRelationships,
75
+ ...tableToViewRelationships,
76
+ ...viewToViewRelationships
77
+ ];
78
+ });
79
+ }
80
+ return {
81
+ data: allTableM2oAndO2oRelationships.concat(allViewM2oAndO2oRelationships),
82
+ error: null
83
+ };
84
+ }
85
+ };
86
+ //#endregion
87
+ export { PostgresMetaRelationships as default };