prostgles-server 3.0.70 → 3.0.72

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.
@@ -8,7 +8,7 @@ async function initPubSubManager() {
8
8
  if (!this.canContinue())
9
9
  return undefined;
10
10
  try {
11
- const schema_version = 6;
11
+ const schema_version = 10;
12
12
  const initQuery = `
13
13
  BEGIN; -- ISOLATION LEVEL SERIALIZABLE;-- TRANSACTION ISOLATION LEVEL SERIALIZABLE;
14
14
 
@@ -149,49 +149,65 @@ async function initPubSubManager() {
149
149
  DECLARE err_text TEXT;
150
150
  DECLARE err_detail TEXT;
151
151
  DECLARE err_hint TEXT;
152
-
152
+
153
+ DECLARE view_def_query TEXT := '';
154
+
153
155
  BEGIN
154
156
 
155
157
  -- PERFORM pg_notify('debug', concat_ws(' ', 'TABLE', TG_TABLE_NAME, TG_OP));
156
158
 
157
159
  SELECT string_agg(
158
- concat_ws(
159
- E' UNION \n ',
160
- CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN (p1 || ' old_table ' || p2) END,
161
- CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN (p1 || ' new_table ' || p2) END
160
+ format(
161
+ $c$
162
+ SELECT CASE WHEN EXISTS(
163
+ SELECT 1 FROM %I WHERE %s
164
+ ) THEN %s::text END AS t_ids
165
+ $c$,
166
+ table_name,
167
+ condition,
168
+ id
162
169
  ),
163
- E' UNION \n '::text
164
- )
170
+ E' UNION \n '
171
+ )
165
172
  INTO unions
166
- FROM (
167
- SELECT
168
- CASE WHEN related_view_name IS NOT NULL
169
- /* E' is used to ensure line breaks are not escaped */
170
- THEN format(E'WITH %I AS (\n %s \n) ', related_view_name, related_view_def)
171
- ELSE
172
- ''
173
- END ||
174
- $z$
175
- SELECT CASE WHEN EXISTS( SELECT 1 FROM
176
- $z$ AS p1,
177
- format(
178
- $c$
179
- as %I WHERE %s ) THEN %s::text END AS t_ids
180
- $c$,
181
- table_name, condition, id
182
- ) AS p2
183
- FROM prostgles.v_triggers
184
- WHERE table_name = TG_TABLE_NAME
185
- ) t;
173
+ FROM prostgles.v_triggers
174
+ WHERE table_name = TG_TABLE_NAME;
175
+
186
176
 
177
+ /* unions = 'old_table union new_table' or any one of the tables */
187
178
  IF unions IS NOT NULL THEN
188
- query = format(
189
- $s$
190
- SELECT ARRAY_AGG(DISTINCT t.t_ids)
191
- FROM ( %s ) t
192
- $s$,
193
- unions
194
- );
179
+
180
+ SELECT
181
+ format(
182
+ E'WITH %I AS (\n %s \n) ',
183
+ TG_TABLE_NAME,
184
+ concat_ws(
185
+ E' UNION ALL \n ',
186
+ CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN ' SELECT * FROM old_table ' END,
187
+ CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN ' SELECT * FROM new_table ' END
188
+ )
189
+ )
190
+ ||
191
+ COALESCE((
192
+ SELECT ', ' || string_agg(format(E' %I AS ( \n %s \n ) ', related_view_name, related_view_def), ', ')
193
+ FROM (
194
+ SELECT DISTINCT related_view_name, related_view_def
195
+ FROM prostgles.v_triggers
196
+ WHERE table_name = TG_TABLE_NAME
197
+ AND related_view_name IS NOT NULL
198
+ AND related_view_def IS NOT NULL
199
+ ) t
200
+ ), '')
201
+ ||
202
+ format(
203
+ $c$
204
+ SELECT ARRAY_AGG(DISTINCT t.t_ids)
205
+ FROM (
206
+ %s
207
+ ) t
208
+ $c$, unions
209
+ )
210
+ INTO query;
195
211
 
196
212
  BEGIN
197
213
  EXECUTE query INTO t_ids;
@@ -232,7 +248,7 @@ async function initPubSubManager() {
232
248
  COALESCE(TG_TABLE_NAME, 'MISSING'),
233
249
  COALESCE(TG_OP, 'MISSING'),
234
250
  CASE WHEN has_errors
235
- THEN concat_ws('; ', 'error', err_text, err_detail, err_hint )
251
+ THEN concat_ws('; ', 'error', err_text, err_detail, err_hint, 'query: ' || query )
236
252
  ELSE COALESCE(nrw.cids, '')
237
253
  END
238
254
  ${this.dboBuilder.prostgles.opts.DEBUG_MODE ? (", (select json_agg(t)::TEXT FROM (SELECT * from old_table) t), query") : ""}
@@ -1,12 +1,12 @@
1
1
  import { PostgresNotifListenManager } from "../PostgresNotifListenManager";
2
2
  import { asValue, log, PubSubManager } from "./PubSubManager";
3
- const REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers" as const;
3
+ const REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers" as const;
4
4
 
5
5
  export async function initPubSubManager(this: PubSubManager): Promise<PubSubManager | undefined> {
6
6
  if (!this.canContinue()) return undefined;
7
7
 
8
8
  try {
9
- const schema_version = 6;
9
+ const schema_version = 10;
10
10
 
11
11
  const initQuery = `
12
12
  BEGIN; -- ISOLATION LEVEL SERIALIZABLE;-- TRANSACTION ISOLATION LEVEL SERIALIZABLE;
@@ -148,49 +148,65 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
148
148
  DECLARE err_text TEXT;
149
149
  DECLARE err_detail TEXT;
150
150
  DECLARE err_hint TEXT;
151
-
151
+
152
+ DECLARE view_def_query TEXT := '';
153
+
152
154
  BEGIN
153
155
 
154
156
  -- PERFORM pg_notify('debug', concat_ws(' ', 'TABLE', TG_TABLE_NAME, TG_OP));
155
157
 
156
158
  SELECT string_agg(
157
- concat_ws(
158
- E' UNION \n ',
159
- CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN (p1 || ' old_table ' || p2) END,
160
- CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN (p1 || ' new_table ' || p2) END
159
+ format(
160
+ $c$
161
+ SELECT CASE WHEN EXISTS(
162
+ SELECT 1 FROM %I WHERE %s
163
+ ) THEN %s::text END AS t_ids
164
+ $c$,
165
+ table_name,
166
+ condition,
167
+ id
161
168
  ),
162
- E' UNION \n '::text
163
- )
169
+ E' UNION \n '
170
+ )
164
171
  INTO unions
165
- FROM (
166
- SELECT
167
- CASE WHEN related_view_name IS NOT NULL
168
- /* E' is used to ensure line breaks are not escaped */
169
- THEN format(E'WITH %I AS (\n %s \n) ', related_view_name, related_view_def)
170
- ELSE
171
- ''
172
- END ||
173
- $z$
174
- SELECT CASE WHEN EXISTS( SELECT 1 FROM
175
- $z$ AS p1,
176
- format(
177
- $c$
178
- as %I WHERE %s ) THEN %s::text END AS t_ids
179
- $c$,
180
- table_name, condition, id
181
- ) AS p2
182
- FROM prostgles.v_triggers
183
- WHERE table_name = TG_TABLE_NAME
184
- ) t;
172
+ FROM prostgles.v_triggers
173
+ WHERE table_name = TG_TABLE_NAME;
174
+
185
175
 
176
+ /* unions = 'old_table union new_table' or any one of the tables */
186
177
  IF unions IS NOT NULL THEN
187
- query = format(
188
- $s$
189
- SELECT ARRAY_AGG(DISTINCT t.t_ids)
190
- FROM ( %s ) t
191
- $s$,
192
- unions
193
- );
178
+
179
+ SELECT
180
+ format(
181
+ E'WITH %I AS (\n %s \n) ',
182
+ TG_TABLE_NAME,
183
+ concat_ws(
184
+ E' UNION ALL \n ',
185
+ CASE WHEN (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') THEN ' SELECT * FROM old_table ' END,
186
+ CASE WHEN (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN ' SELECT * FROM new_table ' END
187
+ )
188
+ )
189
+ ||
190
+ COALESCE((
191
+ SELECT ', ' || string_agg(format(E' %I AS ( \n %s \n ) ', related_view_name, related_view_def), ', ')
192
+ FROM (
193
+ SELECT DISTINCT related_view_name, related_view_def
194
+ FROM prostgles.v_triggers
195
+ WHERE table_name = TG_TABLE_NAME
196
+ AND related_view_name IS NOT NULL
197
+ AND related_view_def IS NOT NULL
198
+ ) t
199
+ ), '')
200
+ ||
201
+ format(
202
+ $c$
203
+ SELECT ARRAY_AGG(DISTINCT t.t_ids)
204
+ FROM (
205
+ %s
206
+ ) t
207
+ $c$, unions
208
+ )
209
+ INTO query;
194
210
 
195
211
  BEGIN
196
212
  EXECUTE query INTO t_ids;
@@ -231,7 +247,7 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
231
247
  COALESCE(TG_TABLE_NAME, 'MISSING'),
232
248
  COALESCE(TG_OP, 'MISSING'),
233
249
  CASE WHEN has_errors
234
- THEN concat_ws('; ', 'error', err_text, err_detail, err_hint )
250
+ THEN concat_ws('; ', 'error', err_text, err_detail, err_hint, 'query: ' || query )
235
251
  ELSE COALESCE(nrw.cids, '')
236
252
  END
237
253
  ${this.dboBuilder.prostgles.opts.DEBUG_MODE? (", (select json_agg(t)::TEXT FROM (SELECT * from old_table) t), query") : ""}
@@ -80,6 +80,12 @@ const RULE_TO_METHODS = [
80
80
  ];
81
81
  const PubSubManager_1 = require("./PubSubManager/PubSubManager");
82
82
  class PublishParser {
83
+ publish;
84
+ publishMethods;
85
+ publishRawSQL;
86
+ dbo;
87
+ db;
88
+ prostgles;
83
89
  constructor(publish, publishMethods, publishRawSQL, dbo, db, prostgles) {
84
90
  this.publish = publish;
85
91
  this.publishMethods = publishMethods;
@@ -289,7 +295,6 @@ class PublishParser {
289
295
  MY_RULES.map(r => {
290
296
  /** THIS IS A MESS -> some methods cannot be dissallowed (unsync, unsubscribe...) */
291
297
  r.methods.forEach(method => {
292
- var _a;
293
298
  const isAllowed = tableRules[r.rule] && tableRules[method] === undefined;
294
299
  if (isAllowed) {
295
300
  if (method === "updateBatch" && !tableRules.update) {
@@ -297,7 +302,7 @@ class PublishParser {
297
302
  else if (method === "upsert" && (!tableRules.update || !tableRules.insert)) {
298
303
  }
299
304
  else {
300
- (_a = res)[method] ?? (_a[method] = true);
305
+ res[method] ??= true;
301
306
  }
302
307
  }
303
308
  });
@@ -4,8 +4,9 @@ exports.SchemaWatch = void 0;
4
4
  const prostgles_types_1 = require("prostgles-types");
5
5
  const DboBuilder_1 = require("./DboBuilder");
6
6
  class SchemaWatch {
7
+ schema_checkIntervalMillis;
8
+ loaded = false;
7
9
  constructor({ watchSchema, watchSchemaType, tsGeneratedTypesDir, currDbuilder, onSchemaChanged }) {
8
- this.loaded = false;
9
10
  if (!watchSchema)
10
11
  return;
11
12
  if (watchSchema === "hotReloadMode" && !tsGeneratedTypesDir) {
@@ -23,97 +23,7 @@ exports.parseI18N = parseI18N;
23
23
  * Will be run between initSQL and fileTable
24
24
  */
25
25
  class TableConfigurator {
26
- constructor(prostgles) {
27
- this.getColumnConfig = (tableName, colName) => {
28
- const tconf = this.config?.[tableName];
29
- if (tconf && "columns" in tconf) {
30
- return tconf.columns?.[colName];
31
- }
32
- return undefined;
33
- };
34
- this.getTableInfo = (params) => {
35
- const tconf = this.config?.[params.tableName];
36
- return {
37
- label: (0, exports.parseI18N)({ config: tconf?.info?.label, lang: params.lang, defaultLang: "en", defaultValue: params.tableName })
38
- };
39
- };
40
- this.getColInfo = (params) => {
41
- const colConf = this.getColumnConfig(params.table, params.col);
42
- let result = undefined;
43
- if (colConf) {
44
- if ((0, prostgles_types_1.isObject)(colConf)) {
45
- result = {
46
- ...(result ?? {}),
47
- ...("info" in colConf && colConf?.info),
48
- ...("jsonbSchema" in colConf && colConf.jsonbSchema && { jsonSchema: (0, validation_1.getJSONBSchemaAsJSONSchema)(params.table, params.col, colConf) })
49
- };
50
- /**
51
- * Get labels from TableConfig if specified
52
- */
53
- if (colConf.label) {
54
- const { lang } = params;
55
- const lbl = colConf?.label;
56
- if (["string", "object"].includes(typeof lbl)) {
57
- if (typeof lbl === "string") {
58
- result ?? (result = {});
59
- result.label = lbl;
60
- }
61
- else if (lang && (lbl?.[lang] || lbl?.en)) {
62
- result ?? (result = {});
63
- result.label = (lbl?.[lang]) || lbl?.en;
64
- }
65
- }
66
- }
67
- }
68
- }
69
- return result;
70
- };
71
- this.checkColVal = (params) => {
72
- const conf = this.getColInfo(params);
73
- if (conf) {
74
- const { value } = params;
75
- const { min, max } = conf;
76
- if (min !== undefined && value !== undefined && value < min)
77
- throw `${params.col} must be less than ${min}`;
78
- if (max !== undefined && value !== undefined && value > max)
79
- throw `${params.col} must be greater than ${max}`;
80
- }
81
- };
82
- this.getJoinInfo = (sourceTable, targetTable) => {
83
- if (this.config &&
84
- sourceTable in this.config &&
85
- this.config[sourceTable] &&
86
- "columns" in this.config[sourceTable]) {
87
- const td = this.config[sourceTable];
88
- if ("columns" in td && td.columns?.[targetTable]) {
89
- const cd = td.columns[targetTable];
90
- if ((0, prostgles_types_1.isObject)(cd) && "joinDef" in cd) {
91
- if (!cd.joinDef)
92
- throw "cd.joinDef missing";
93
- const { joinDef } = cd;
94
- const res = {
95
- expectOne: false,
96
- paths: joinDef.map(({ sourceTable, targetTable: table, on }) => ({
97
- source: sourceTable,
98
- target: targetTable,
99
- table,
100
- on
101
- })),
102
- };
103
- return res;
104
- }
105
- }
106
- }
107
- return undefined;
108
- };
109
- this.log = (...args) => {
110
- if (this.prostgles.opts.DEBUG_MODE) {
111
- console.log("TableConfig: \n", ...args);
112
- }
113
- };
114
- this.config = prostgles.opts.tableConfig;
115
- this.prostgles = prostgles;
116
- }
26
+ config;
117
27
  get dbo() {
118
28
  if (!this.prostgles.dbo)
119
29
  throw "this.prostgles.dbo missing";
@@ -126,6 +36,94 @@ class TableConfigurator {
126
36
  return this.prostgles.db;
127
37
  }
128
38
  ;
39
+ // sidKeyName: string;
40
+ prostgles;
41
+ constructor(prostgles) {
42
+ this.config = prostgles.opts.tableConfig;
43
+ this.prostgles = prostgles;
44
+ }
45
+ getColumnConfig = (tableName, colName) => {
46
+ const tconf = this.config?.[tableName];
47
+ if (tconf && "columns" in tconf) {
48
+ return tconf.columns?.[colName];
49
+ }
50
+ return undefined;
51
+ };
52
+ getTableInfo = (params) => {
53
+ const tconf = this.config?.[params.tableName];
54
+ return {
55
+ label: (0, exports.parseI18N)({ config: tconf?.info?.label, lang: params.lang, defaultLang: "en", defaultValue: params.tableName })
56
+ };
57
+ };
58
+ getColInfo = (params) => {
59
+ const colConf = this.getColumnConfig(params.table, params.col);
60
+ let result = undefined;
61
+ if (colConf) {
62
+ if ((0, prostgles_types_1.isObject)(colConf)) {
63
+ result = {
64
+ ...(result ?? {}),
65
+ ...("info" in colConf && colConf?.info),
66
+ ...("jsonbSchema" in colConf && colConf.jsonbSchema && { jsonSchema: (0, validation_1.getJSONBSchemaAsJSONSchema)(params.table, params.col, colConf) })
67
+ };
68
+ /**
69
+ * Get labels from TableConfig if specified
70
+ */
71
+ if (colConf.label) {
72
+ const { lang } = params;
73
+ const lbl = colConf?.label;
74
+ if (["string", "object"].includes(typeof lbl)) {
75
+ if (typeof lbl === "string") {
76
+ result ??= {};
77
+ result.label = lbl;
78
+ }
79
+ else if (lang && (lbl?.[lang] || lbl?.en)) {
80
+ result ??= {};
81
+ result.label = (lbl?.[lang]) || lbl?.en;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return result;
88
+ };
89
+ checkColVal = (params) => {
90
+ const conf = this.getColInfo(params);
91
+ if (conf) {
92
+ const { value } = params;
93
+ const { min, max } = conf;
94
+ if (min !== undefined && value !== undefined && value < min)
95
+ throw `${params.col} must be less than ${min}`;
96
+ if (max !== undefined && value !== undefined && value > max)
97
+ throw `${params.col} must be greater than ${max}`;
98
+ }
99
+ };
100
+ getJoinInfo = (sourceTable, targetTable) => {
101
+ if (this.config &&
102
+ sourceTable in this.config &&
103
+ this.config[sourceTable] &&
104
+ "columns" in this.config[sourceTable]) {
105
+ const td = this.config[sourceTable];
106
+ if ("columns" in td && td.columns?.[targetTable]) {
107
+ const cd = td.columns[targetTable];
108
+ if ((0, prostgles_types_1.isObject)(cd) && "joinDef" in cd) {
109
+ if (!cd.joinDef)
110
+ throw "cd.joinDef missing";
111
+ const { joinDef } = cd;
112
+ const res = {
113
+ expectOne: false,
114
+ paths: joinDef.map(({ sourceTable, targetTable: table, on }) => ({
115
+ source: sourceTable,
116
+ target: targetTable,
117
+ table,
118
+ on
119
+ })),
120
+ };
121
+ return res;
122
+ }
123
+ }
124
+ }
125
+ return undefined;
126
+ };
129
127
  async init() {
130
128
  let queries = [];
131
129
  if (!this.config || !this.prostgles.pgp)
@@ -372,6 +370,11 @@ class TableConfigurator {
372
370
  });
373
371
  }
374
372
  }
373
+ log = (...args) => {
374
+ if (this.prostgles.opts.DEBUG_MODE) {
375
+ console.log("TableConfig: \n", ...args);
376
+ }
377
+ };
375
378
  }
376
379
  exports.default = TableConfigurator;
377
380
  async function columnExists(args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "3.0.70",
3
+ "version": "3.0.72",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "file-type": "^17.1.4",
40
40
  "g": "^2.0.1",
41
41
  "pg-promise": "^10.11.1",
42
- "prostgles-types": "^3.0.17",
42
+ "prostgles-types": "^3.0.18",
43
43
  "sharp": "^0.31.0",
44
44
  "typescript": "^4.9.5"
45
45
  },
@@ -1 +1 @@
1
- 174896
1
+ 263626
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "files": ["./index.ts"],
3
3
  "compilerOptions": {
4
- "target": "es2020",
5
- "lib": [ "es2020", "DOM" ],
4
+ "target": "es2022",
5
+ "lib": [ "es2022", "DOM" ],
6
6
  // "outDir": "dist",
7
7
  "esModuleInterop" : true,
8
8
  "module": "commonjs",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "../..": {
23
23
  "name": "prostgles-server",
24
- "version": "3.0.69",
24
+ "version": "3.0.71",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
27
  "@aws-sdk/client-s3": "^3.121.0",
@@ -32,7 +32,7 @@
32
32
  "file-type": "^17.1.4",
33
33
  "g": "^2.0.1",
34
34
  "pg-promise": "^10.11.1",
35
- "prostgles-types": "^3.0.17",
35
+ "prostgles-types": "^3.0.18",
36
36
  "sharp": "^0.31.0",
37
37
  "typescript": "^4.9.5"
38
38
  },
@@ -1512,7 +1512,7 @@
1512
1512
  "file-type": "^17.1.4",
1513
1513
  "g": "^2.0.1",
1514
1514
  "pg-promise": "^10.11.1",
1515
- "prostgles-types": "^3.0.17",
1515
+ "prostgles-types": "^3.0.18",
1516
1516
  "sharp": "^0.31.0",
1517
1517
  "typescript": "^4.9.5"
1518
1518
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "files": ["./index.ts"],
3
3
  "compilerOptions": {
4
- "target": "es2020",
5
- "lib": [ "es2020" ],
4
+ "target": "es2022",
5
+ "lib": [ "es2022" ],
6
6
  "esModuleInterop" : true,
7
7
  "allowSyntheticDefaultImports": true,
8
8
  "resolveJsonModule": true,