prostgles-server 4.2.72 → 4.2.74

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 (85) hide show
  1. package/dist/DboBuilder/DboBuilder.d.ts +2 -1
  2. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  3. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  4. package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts +1 -1
  5. package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts.map +1 -1
  6. package/dist/DboBuilder/QueryBuilder/getNewQuery.js +2 -2
  7. package/dist/DboBuilder/QueryBuilder/getNewQuery.js.map +1 -1
  8. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +2 -1
  9. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  10. package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
  11. package/dist/DboBuilder/dboBuilderUtils.d.ts +2 -1
  12. package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
  13. package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
  14. package/dist/DboBuilder/getTablesForSchemaPostgresSQL.d.ts +1 -1
  15. package/dist/DboBuilder/getTablesForSchemaPostgresSQL.d.ts.map +1 -1
  16. package/dist/DboBuilder/getTablesForSchemaPostgresSQL.js +2 -1
  17. package/dist/DboBuilder/getTablesForSchemaPostgresSQL.js.map +1 -1
  18. package/dist/DboBuilder/prepareShortestJoinPaths.d.ts +1 -1
  19. package/dist/DboBuilder/prepareShortestJoinPaths.d.ts.map +1 -1
  20. package/dist/DboBuilder/prepareShortestJoinPaths.js +3 -3
  21. package/dist/DboBuilder/prepareShortestJoinPaths.js.map +1 -1
  22. package/dist/Prostgles.d.ts +12 -177
  23. package/dist/Prostgles.d.ts.map +1 -1
  24. package/dist/Prostgles.js +6 -2
  25. package/dist/Prostgles.js.map +1 -1
  26. package/dist/ProstglesTypes.d.ts +177 -0
  27. package/dist/ProstglesTypes.d.ts.map +1 -0
  28. package/dist/ProstglesTypes.js +5 -0
  29. package/dist/ProstglesTypes.js.map +1 -0
  30. package/dist/PubSubManager/PubSubManager.d.ts +2 -4
  31. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  32. package/dist/PubSubManager/PubSubManager.js +25 -17
  33. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  34. package/dist/PubSubManager/getInitQuery.d.ts.map +1 -1
  35. package/dist/PubSubManager/getInitQuery.js +5 -2
  36. package/dist/PubSubManager/getInitQuery.js.map +1 -1
  37. package/dist/PubSubManager/initPubSubManager.d.ts +1 -0
  38. package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
  39. package/dist/PubSubManager/initPubSubManager.js +31 -18
  40. package/dist/PubSubManager/initPubSubManager.js.map +1 -1
  41. package/dist/PubSubManager/notifListener.d.ts.map +1 -1
  42. package/dist/PubSubManager/notifListener.js +13 -0
  43. package/dist/PubSubManager/notifListener.js.map +1 -1
  44. package/dist/PubSubManager/orphanTriggerCheck.d.ts +3 -0
  45. package/dist/PubSubManager/orphanTriggerCheck.d.ts.map +1 -0
  46. package/dist/PubSubManager/orphanTriggerCheck.js +78 -0
  47. package/dist/PubSubManager/orphanTriggerCheck.js.map +1 -0
  48. package/dist/SchemaWatch/SchemaWatch.d.ts +4 -1
  49. package/dist/SchemaWatch/SchemaWatch.d.ts.map +1 -1
  50. package/dist/SchemaWatch/SchemaWatch.js.map +1 -1
  51. package/dist/SchemaWatch/getValidatedWatchSchemaType.d.ts +1 -1
  52. package/dist/SchemaWatch/getValidatedWatchSchemaType.d.ts.map +1 -1
  53. package/dist/SchemaWatch/getWatchSchemaTagList.d.ts +1 -1
  54. package/dist/SchemaWatch/getWatchSchemaTagList.d.ts.map +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/initProstgles.d.ts +2 -1
  59. package/dist/initProstgles.d.ts.map +1 -1
  60. package/dist/initProstgles.js +23 -2
  61. package/dist/initProstgles.js.map +1 -1
  62. package/lib/DboBuilder/DboBuilder.ts +2 -3
  63. package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +5 -6
  64. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +2 -1
  65. package/lib/DboBuilder/dboBuilderUtils.ts +1 -1
  66. package/lib/DboBuilder/getTablesForSchemaPostgresSQL.ts +4 -2
  67. package/lib/DboBuilder/prepareShortestJoinPaths.ts +1 -1
  68. package/lib/Prostgles.ts +14 -198
  69. package/lib/ProstglesTypes.ts +193 -0
  70. package/lib/PubSubManager/PubSubManager.ts +25 -19
  71. package/lib/PubSubManager/getInitQuery.ts +5 -2
  72. package/lib/PubSubManager/initPubSubManager.ts +33 -18
  73. package/lib/PubSubManager/notifListener.ts +15 -0
  74. package/lib/PubSubManager/orphanTriggerCheck.ts +79 -0
  75. package/lib/SchemaWatch/SchemaWatch.ts +2 -1
  76. package/lib/SchemaWatch/getValidatedWatchSchemaType.ts +1 -1
  77. package/lib/SchemaWatch/getWatchSchemaTagList.ts +1 -1
  78. package/lib/index.ts +2 -1
  79. package/lib/initProstgles.ts +26 -3
  80. package/package.json +2 -2
  81. package/tests/isomorphicQueries.spec.ts +4 -4
  82. package/tests/server/index.ts +1 -0
  83. package/tests/server/package-lock.json +329 -138
  84. package/tests/server/package.json +2 -2
  85. package/tests/server/testTableConfig.ts +1 -0
@@ -167,6 +167,10 @@ export class PubSubManager {
167
167
  return result;
168
168
  }
169
169
 
170
+ appInfoWasInserted = false;
171
+ get appId() {
172
+ return this.dboBuilder.prostgles.appId;
173
+ }
170
174
  get db(): DB {
171
175
  return this.dboBuilder.db;
172
176
  }
@@ -195,12 +199,6 @@ export class PubSubManager {
195
199
 
196
200
  log("Created PubSubManager");
197
201
  }
198
-
199
- /**
200
- * Used facilitate concurrent prostgles connections to the same database
201
- */
202
- appID?: string;
203
-
204
202
  appCheckFrequencyMS = 10 * 1000;
205
203
  appCheck?: ReturnType<typeof setInterval>;
206
204
 
@@ -227,8 +225,6 @@ export class PubSubManager {
227
225
  checkedListenerTableCond?: string[];
228
226
 
229
227
  initialiseEventTriggers = async () => {
230
- if (!this.appID) throw "prepareTriggers failed: this.appID missing";
231
-
232
228
  const { watchSchema } = this.dboBuilder.prostgles.opts;
233
229
  if (watchSchema && !(await getIsSuperUser(this.db))) {
234
230
  console.warn("prostgles watchSchema requires superuser db user. Will not watch using event triggers")
@@ -268,7 +264,7 @@ export class PubSubManager {
268
264
 
269
265
  DROP TABLE IF EXISTS %1$I;
270
266
  $q$,
271
- ${asValue('triggers_' + this.appID)}
267
+ ${asValue('triggers_' + this.appId)}
272
268
  );
273
269
 
274
270
  is_super_user := EXISTS (select 1 from pg_user where usename = CURRENT_USER AND usesuper IS TRUE);
@@ -402,15 +398,14 @@ export class PubSubManager {
402
398
 
403
399
  addSub = addSub.bind(this);
404
400
 
405
-
406
401
  getActiveListeners = (): { table_name: string; condition: string }[] => {
407
- const result: { table_name: string; condition: string }[] = [];
402
+ const activeListeners: { table_name: string; condition: string }[] = [];
408
403
  const upsert = (t: string, c: string) => {
409
- if (!result.find(r => r.table_name === t && r.condition === c)) {
410
- result.push({ table_name: t, condition: c });
404
+ if (!activeListeners.find(r => r.table_name === t && r.condition === c)) {
405
+ activeListeners.push({ table_name: t, condition: c });
411
406
  }
412
407
  }
413
- (this.syncs || []).map(s => {
408
+ (this.syncs ?? []).map(s => {
414
409
  upsert(s.table_name, s.condition)
415
410
  });
416
411
 
@@ -420,7 +415,7 @@ export class PubSubManager {
420
415
  });
421
416
  });
422
417
 
423
- return result;
418
+ return activeListeners;
424
419
  }
425
420
 
426
421
  /**
@@ -436,7 +431,7 @@ export class PubSubManager {
436
431
  FROM prostgles.v_triggers
437
432
  WHERE app_id = $1
438
433
  ORDER BY table_name, condition
439
- `, [this.appID]
434
+ `, [this.dboBuilder.prostgles.appId]
440
435
  );
441
436
 
442
437
  this._triggers = {};
@@ -459,7 +454,6 @@ export class PubSubManager {
459
454
  const { table_name } = { ...params }
460
455
  let { condition } = { ...params }
461
456
  if (!table_name) throw "MISSING table_name";
462
- if (!this.appID) throw "MISSING appID";
463
457
 
464
458
  if (!condition || !condition.trim().length) {
465
459
  condition = "TRUE";
@@ -479,8 +473,20 @@ export class PubSubManager {
479
473
  /* ${ PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID} */
480
474
  LOCK TABLE prostgles.app_triggers IN ACCESS EXCLUSIVE MODE;
481
475
 
482
- INSERT INTO prostgles.app_triggers (table_name, condition, app_id, related_view_name, related_view_def)
483
- VALUES (${trgVals.tbl}, ${trgVals.cond}, ${asValue(this.appID)}, ${asValue(viewOptions?.viewName ?? null)}, ${asValue(viewOptions?.definition ?? null)})
476
+ INSERT INTO prostgles.app_triggers (
477
+ table_name,
478
+ condition,
479
+ app_id,
480
+ related_view_name,
481
+ related_view_def
482
+ )
483
+ VALUES (
484
+ ${trgVals.tbl},
485
+ ${trgVals.cond},
486
+ ${asValue(this.appId)},
487
+ ${asValue(viewOptions?.viewName ?? null)},
488
+ ${asValue(viewOptions?.definition ?? null)}
489
+ )
484
490
  ON CONFLICT DO NOTHING;
485
491
 
486
492
  COMMIT WORK;
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { asValue, NOTIF_CHANNEL, NOTIF_TYPE, PubSubManager } from "./PubSubManager";
3
3
  const { version } = require("../../package.json");
4
+ import { getAppCheckQuery } from "./orphanTriggerCheck";
4
5
 
5
6
  export const DB_OBJ_NAMES = {
6
7
  trigger_add_remove_func: "prostgles.trigger_add_remove_func",
@@ -279,7 +280,6 @@ BEGIN
279
280
  err_detail = PG_EXCEPTION_DETAIL,
280
281
  err_hint = PG_EXCEPTION_HINT;
281
282
 
282
-
283
283
  END;
284
284
 
285
285
  --RAISE NOTICE 'has_errors: % ', has_errors;
@@ -307,7 +307,7 @@ BEGIN
307
307
  THEN concat_ws('; ', 'error', err_text, err_detail, err_hint, 'query: ' || query )
308
308
  ELSE COALESCE(v_trigger.cids, '')
309
309
  END
310
- ${this.dboBuilder.prostgles.opts.DEBUG_MODE? (", COALESCE(current_query(), 'current_query ??'), (select json_agg(t)::TEXT FROM (SELECT * from old_table) t), query") : ""}
310
+ ${this.dboBuilder.prostgles.opts.DEBUG_MODE? (", COALESCE(current_query(), 'current_query ??'), ' ', query") : ""}
311
311
  ), 7999/4) -- Some chars are 2bytes -> 'Ω'
312
312
  );
313
313
  END LOOP;
@@ -323,6 +323,7 @@ BEGIN
323
323
  END IF;
324
324
  END IF;
325
325
 
326
+ ${getAppCheckQuery()}
326
327
 
327
328
  RETURN NULL;
328
329
 
@@ -574,6 +575,8 @@ BEGIN
574
575
  );
575
576
  END LOOP;
576
577
 
578
+ ${getAppCheckQuery()}
579
+
577
580
  END IF;
578
581
 
579
582
  END;
@@ -1,7 +1,7 @@
1
1
  import { PostgresNotifListenManager } from "../PostgresNotifListenManager";
2
2
  import { getWatchSchemaTagList } from "../SchemaWatch/getWatchSchemaTagList";
3
3
  import { asValue, log, NOTIF_CHANNEL, PubSubManager } from "./PubSubManager";
4
- const REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers" as const;
4
+ export const REALTIME_TRIGGER_CHECK_QUERY = "prostgles-server internal query used to manage realtime triggers" as const;
5
5
  import { getInitQuery } from "./getInitQuery";
6
6
 
7
7
  export async function initPubSubManager(this: PubSubManager): Promise<PubSubManager | undefined> {
@@ -15,25 +15,37 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
15
15
  if (!this.getIsDestroyed()) return;
16
16
 
17
17
  /* Prepare App id */
18
- if (!this.appID) {
18
+ if (!this.appInfoWasInserted) {
19
+ this.appInfoWasInserted = true;
19
20
  const check_frequency_ms = this.appCheckFrequencyMS;
20
21
  const watching_schema_tag_names = this.dboBuilder.prostgles.schemaWatch?.type.watchType !== "NONE" ? getWatchSchemaTagList(this.dboBuilder.prostgles.opts.watchSchema) : null;
21
- const raw = await this.db.one(
22
- "INSERT INTO prostgles.apps (check_frequency_ms, watching_schema_tag_names, application_name) \
23
- VALUES($1, $2, current_setting('application_name')) \
22
+ await this.db.one(
23
+ "INSERT INTO prostgles.apps (id, check_frequency_ms, watching_schema_tag_names, application_name) \
24
+ VALUES($1, $2, $3, current_setting('application_name')) \
24
25
  RETURNING *; "
25
26
  , [
27
+ this.appId,
26
28
  check_frequency_ms,
27
29
  watching_schema_tag_names
28
30
  ]
29
31
  );
30
- this.appID = raw.id;
31
32
 
32
- if (!this.appCheck) {
33
+ const appRecord = await this.db.one("SELECT * FROM prostgles.apps WHERE id = $1", [this.appId]);
34
+ if (!appRecord || !appRecord.application_name?.includes(this.appId)) {
35
+ throw `initPubSubManager error: App record with application_name containing appId (${this.appId}) not found`;
36
+ }
37
+
38
+ await this.db.any(`
39
+ DELETE FROM prostgles.app_triggers
40
+ WHERE app_id = ${asValue(this.appId)}
41
+ `);
42
+
43
+ console.log("REMOVE app check disabled");
44
+ if (!this.appCheck && Math.random() < 12) {
33
45
 
34
46
  this.appCheck = setInterval(async () => {
35
47
  let checkForStaleTriggers = "";
36
- try { // drop owned by api
48
+ try {
37
49
 
38
50
  this.appChecking = true;
39
51
 
@@ -43,7 +55,7 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
43
55
  SET last_used = CASE WHEN (table_name, condition) IN (
44
56
  ${listeners.map(l => ` ( ${asValue(l.table_name)}, ${asValue(l.condition)} ) `).join(", ")}
45
57
  ) THEN NOW() ELSE last_used END
46
- WHERE app_id = ${asValue(this.appID)};
58
+ WHERE app_id = ${asValue(this.appId)};
47
59
  `;
48
60
 
49
61
  const checkedListenerTableCond = listeners.map(l => `${l.table_name}.${l.condition}`);
@@ -62,10 +74,11 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
62
74
  /* UPDATE currently used triggers */
63
75
  ${updateCurrentlyUsedTriggersQuery}
64
76
 
65
- /* DELETE stale triggers for current app. Other triggers will be deleted on app startup */
66
- DELETE FROM prostgles.app_triggers
67
- WHERE app_id = ${asValue(this.appID)}
68
- AND last_used < NOW() - 4 * ${asValue(this.appCheckFrequencyMS)} * interval '1 millisecond'; -- 10 seconds at the moment
77
+ /* DELETE stale triggers for current app. Other triggers will be deleted on app startup
78
+ DELETE FROM prostgles.app_triggers
79
+ WHERE app_id = ${asValue(this.appId)}
80
+ AND last_used < NOW() - 4 * ${asValue(this.appCheckFrequencyMS)} * interval '1 millisecond'; -- 10 seconds at the moment
81
+ */
69
82
 
70
83
  END IF;
71
84
 
@@ -94,7 +107,7 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
94
107
  /* Last check used to remove disconnected apps */
95
108
  UPDATE prostgles.apps
96
109
  SET last_check = NOW()
97
- WHERE id = ${asValue(this.appID)};
110
+ WHERE id = ${asValue(this.appId)};
98
111
 
99
112
  ${dataTriggerCheckQuery}
100
113
  END IF;
@@ -106,7 +119,7 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
106
119
  this.db.any(`
107
120
  /*
108
121
  ${queryIdentifier}
109
- ${REALTIME_TRIGGER_CHECK_QUERY}
122
+ ${REALTIME_TRIGGER_CHECK_QUERY}
110
123
  ${PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID}
111
124
  */
112
125
  DO $$
@@ -129,8 +142,10 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
129
142
 
130
143
  /** In some cases a query idles and blocks everything else. Terminate all similar queries */
131
144
  this.db.any(
132
- "SELECT state, pg_terminate_backend(pid) from pg_stat_activity WHERE query ilike ${qid} and pid <> pg_backend_pid();",
133
- { qid: "%" + REALTIME_TRIGGER_CHECK_QUERY + "%" }
145
+ "SELECT state, pg_terminate_backend(pid) from pg_stat_activity \
146
+ WHERE query ilike ${qid} \
147
+ AND pid <> pg_backend_pid();",
148
+ { qid: `%${REALTIME_TRIGGER_CHECK_QUERY}%` }
134
149
  );
135
150
 
136
151
  /** If no tries left
@@ -150,7 +165,7 @@ export async function initPubSubManager(this: PubSubManager): Promise<PubSubMana
150
165
  }
151
166
  }
152
167
 
153
- this.postgresNotifListenManager = new PostgresNotifListenManager(this.db, this.notifListener, NOTIF_CHANNEL.getFull(this.appID));
168
+ this.postgresNotifListenManager = new PostgresNotifListenManager(this.db, this.notifListener, NOTIF_CHANNEL.getFull(this.appId));
154
169
 
155
170
  await this.initialiseEventTriggers();
156
171
 
@@ -80,6 +80,21 @@ export async function notifListener(this: PubSubManager, data: { payload: string
80
80
 
81
81
  state = "ok";
82
82
  const conditions = tableTriggers.filter((c, i) => condition_ids.includes(i));
83
+ const orphanedConditions = condition_ids.filter((condId) => typeof tableTriggers.at(condId) !== "string" );
84
+ if(orphanedConditions.length){
85
+ this.db
86
+ .any(" \
87
+ DELETE FROM prostgles.app_triggers \
88
+ WHERE table_name = $1 \
89
+ AND id IN ($2:csv) \
90
+ AND app_id = $3 \
91
+ ",
92
+ [table_name, orphanedConditions, this.appId]
93
+ )
94
+ .catch(e => {
95
+ console.error("Error deleting orphaned triggers", e);
96
+ });
97
+ }
83
98
 
84
99
  conditions.map(condition => {
85
100
 
@@ -0,0 +1,79 @@
1
+ import { PubSubManager } from './PubSubManager';
2
+ import { REALTIME_TRIGGER_CHECK_QUERY } from "./initPubSubManager";
3
+
4
+ /**
5
+ * Schema and Data watch triggers (DB_OBJ_NAMES.schema_watch_func, DB_OBJ_NAMES.data_watch_func)
6
+ * survive and continue to user resources even after the client disconnects.
7
+ * We must therefore .
8
+ */
9
+
10
+ const queryIdentifier = "prostgles query used to keep track of which prgl backend clients are still connected";
11
+ const connectedApplicationNamesQuery = `
12
+ SELECT DISTINCT application_name
13
+ FROM prostgles.apps
14
+ WHERE application_name IN (
15
+ SELECT application_name
16
+ FROM pg_catalog.pg_stat_activity
17
+ WHERE pid = pg_backend_pid()
18
+ )
19
+ `;
20
+
21
+ const LAST_CHECKED_SETTING_NAME = 'prostgles.last_checked';
22
+
23
+ /** It is a function to prevent undefined EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID */
24
+ export const getAppCheckQuery = () => `
25
+ /*
26
+ ${queryIdentifier}
27
+ ${REALTIME_TRIGGER_CHECK_QUERY}
28
+ ${PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID}
29
+ */
30
+ IF
31
+ /* prostgles schema must exist */
32
+ EXISTS (
33
+ SELECT 1
34
+ FROM information_schema.tables
35
+ WHERE table_schema = 'prostgles'
36
+ AND table_name = 'apps'
37
+ )
38
+ /* Ensure we don't check too often */
39
+ AND (
40
+ NULLIF(current_setting('${LAST_CHECKED_SETTING_NAME}', true), '') IS NULL
41
+ OR current_setting('${LAST_CHECKED_SETTING_NAME}', true)::timestamp < NOW() - INTERVAL '1 minute'
42
+ )
43
+ THEN
44
+ EXECUTE format('SET LOCAL ${LAST_CHECKED_SETTING_NAME} TO %L', now());
45
+ --USED FOR DEBUG REMOVE
46
+ PERFORM pg_notify('prostgles', current_setting('${LAST_CHECKED_SETTING_NAME}', true));
47
+
48
+ IF EXISTS (
49
+ ${connectedApplicationNamesQuery}
50
+ ) THEN
51
+
52
+ /* Remove disconnected apps */
53
+ WITH deleted_apps AS (
54
+ DELETE FROM prostgles.apps a
55
+ WHERE NOT EXISTS (
56
+ SELECT 1
57
+ FROM pg_catalog.pg_stat_activity s
58
+ WHERE s.application_name = a.application_name
59
+ )
60
+ RETURNING a.id
61
+ )
62
+ DELETE FROM prostgles.app_triggers
63
+ WHERE app_id IN (
64
+ SELECT id
65
+ FROM deleted_apps
66
+ );
67
+
68
+ END IF;
69
+ END IF;
70
+ `;
71
+
72
+
73
+ // /* Ensure we don't check in paralel */
74
+ // AND NOT EXISTS (
75
+ // SELECT 1
76
+ // FROM pg_catalog.pg_stat_activity
77
+ // WHERE query ilike '%${queryIdentifier}%'
78
+ // AND state = 'active'
79
+ // )
@@ -1,6 +1,5 @@
1
1
  import type { DboBuilder } from "../DboBuilder/DboBuilder";
2
2
  import { EVENT_TRIGGER_TAGS } from "../Event_Trigger_Tags";
3
- import { OnSchemaChangeCallback } from "../Prostgles";
4
3
  import { PubSubManager, log } from "../PubSubManager/PubSubManager";
5
4
  import { ValidatedWatchSchemaType, getValidatedWatchSchemaType } from "./getValidatedWatchSchemaType";
6
5
  const COMMAND_FIRST_KEYWORDS = EVENT_TRIGGER_TAGS
@@ -11,6 +10,8 @@ const DB_FALLBACK_COMMANDS = Array.from(new Set(COMMAND_FIRST_KEYWORDS));
11
10
 
12
11
  export type VoidFunction = () => void;
13
12
 
13
+ export type OnSchemaChangeCallback = ((event: { command: string; query: string }) => void);
14
+
14
15
  export class SchemaWatch {
15
16
 
16
17
  dboBuilder: DboBuilder;
@@ -1,5 +1,5 @@
1
1
  import type { DboBuilder } from "../DboBuilder/DboBuilder";
2
- import { OnSchemaChangeCallback } from "../Prostgles";
2
+ import { OnSchemaChangeCallback } from "./SchemaWatch";
3
3
 
4
4
  export type ValidatedWatchSchemaType =
5
5
  | { watchType: "NONE" }
@@ -1,6 +1,6 @@
1
1
  import { getKeys, isObject } from "prostgles-types";
2
2
  import { EVENT_TRIGGER_TAGS } from "../Event_Trigger_Tags";
3
- import { ProstglesInitOptions } from "../Prostgles";
3
+ import { ProstglesInitOptions } from "../ProstglesTypes";
4
4
 
5
5
  export const getWatchSchemaTagList = (watchSchema: ProstglesInitOptions["watchSchema"]) => {
6
6
  if(!watchSchema) return undefined;
package/lib/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { SessionUser } from "./AuthHandler";
2
- import { Prostgles, ProstglesInitOptions } from "./Prostgles";
2
+ import { Prostgles } from "./Prostgles";
3
+ import { ProstglesInitOptions } from "./ProstglesTypes";
3
4
 
4
5
  function prostgles<S = void, SUser extends SessionUser = SessionUser>(params: ProstglesInitOptions<S, SUser>){
5
6
 
@@ -5,10 +5,11 @@ import { isEmpty, pickKeys } from "prostgles-types";
5
5
  import { AuthHandler } from "./AuthHandler";
6
6
  import { DBEventsManager } from "./DBEventsManager";
7
7
  import { DBOFullyTyped } from "./DBSchemaBuilder";
8
- import { DBHandlerServer, Prostgles, ProstglesInitOptions, getIsSuperUser } from "./Prostgles";
8
+ import { DBHandlerServer, Prostgles, getIsSuperUser } from "./Prostgles";
9
9
  import { DbTableInfo, PublishParser } from "./PublishParser/PublishParser";
10
10
  import { sleep } from "./utils";
11
11
  import { SchemaWatch } from "./SchemaWatch/SchemaWatch";
12
+ import { ProstglesInitOptions } from "./ProstglesTypes";
12
13
 
13
14
  export type DbConnection = string | pg.IConnectionParameters<pg.IClient>;
14
15
  export type DbConnectionOpts = pg.IDefaults;
@@ -58,9 +59,31 @@ export type InitResult = {
58
59
  export const initProstgles = async function(this: Prostgles, onReady: OnReadyCallbackBasic, reason: OnInitReason): Promise<InitResult> {
59
60
  this.loaded = false;
60
61
 
61
- /* 1. Connect to db */
62
62
  if (!this.db) {
63
- const { db, pgp } = getDbConnection(this.opts.dbConnection, this.opts.dbOptions, this.opts.DEBUG_MODE,
63
+ let existingAppName = "";
64
+ let connString = "";
65
+ if(typeof this.opts.dbConnection === "string"){
66
+ connString = this.opts.dbConnection;
67
+ } else if(this.opts.dbConnection.connectionString){
68
+ connString = this.opts.dbConnection.connectionString;
69
+ } else {
70
+ existingAppName = this.opts.dbConnection.application_name ?? "";
71
+ }
72
+
73
+ if(connString){
74
+ try {
75
+ const url = new URL(connString);
76
+ existingAppName = url.searchParams.get("application_name") ?? url.searchParams.get("ApplicationName") ?? "";
77
+ } catch (e) {
78
+
79
+ }
80
+ }
81
+
82
+ const conObj = typeof this.opts.dbConnection === "string" ? { connectionString: this.opts.dbConnection } : this.opts.dbConnection
83
+ const application_name = `prostgles ${this.appId} ${existingAppName}`;
84
+
85
+ /* 1. Connect to db */
86
+ const { db, pgp } = getDbConnection({ ...conObj, application_name }, this.opts.dbOptions, this.opts.DEBUG_MODE,
64
87
  notice => {
65
88
  if (this.opts.onNotice) this.opts.onNotice(notice);
66
89
  if (this.dbEventsManager) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.72",
3
+ "version": "4.2.74",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -53,10 +53,10 @@
53
53
  "@types/pg": "^8.11.5",
54
54
  "@types/pg-cursor": "^2.7.2",
55
55
  "@types/sharp": "^0.30.4",
56
- "@types/socket.io": "^3.0.2",
57
56
  "@typescript-eslint/eslint-plugin": "^5.62.0",
58
57
  "@typescript-eslint/parser": "^5.62.0",
59
58
  "eslint": "^8.51.0",
59
+ "socket.io": "^4.7.5",
60
60
  "typescript": "^5.3.3"
61
61
  }
62
62
  }
@@ -487,11 +487,11 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
487
487
  ) as { tgname: string; enabled: boolean; }[];
488
488
  }
489
489
  await sub.unsubscribe();
490
- let validTriggers = await getTableTriggers(table_name)
491
- assert.equal(validTriggers.filter(t => t.enabled).length, 3);
490
+ let validTriggers = await getTableTriggers(table_name);
491
+ assert.equal(validTriggers.filter(t => t.enabled).length, 3, '3 Triggers should be enabled');
492
492
  await db.sql?.(`DELETE FROM prostgles.app_triggers`, []); // WHERE table_name = $1
493
- validTriggers = await getTableTriggers(table_name)
494
- assert.equal(validTriggers.length, 3);
493
+ validTriggers = await getTableTriggers(table_name);
494
+ assert.equal(validTriggers.length, 3, '3 Triggers should exist but be disabled');
495
495
  assert.equal(validTriggers.filter(t => t.enabled).length, 0);
496
496
  }
497
497
 
@@ -124,6 +124,7 @@ function dd(){
124
124
  expressApp: app,
125
125
  tableName: "files",
126
126
  },
127
+ // DEBUG_MODE: true,
127
128
  restApi: {
128
129
  expressApp: app,
129
130
  routePrefix: "/api"