prostgles-server 4.2.603 → 4.2.605

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 (105) hide show
  1. package/dist/Auth/utils/getSessionUser.d.ts +4 -0
  2. package/dist/Auth/utils/getSessionUser.d.ts.map +1 -0
  3. package/dist/Auth/utils/getSessionUser.js +17 -0
  4. package/dist/Auth/utils/getSessionUser.js.map +1 -0
  5. package/dist/Auth/utils/getSessionUser.spec.d.ts +2 -0
  6. package/dist/Auth/utils/getSessionUser.spec.d.ts.map +1 -0
  7. package/dist/Auth/utils/getSessionUser.spec.js +42 -0
  8. package/dist/Auth/utils/getSessionUser.spec.js.map +1 -0
  9. package/dist/DBSchemaBuilder/getColumnTypescriptDefinition.js +2 -2
  10. package/dist/DBSchemaBuilder/getColumnTypescriptDefinition.js.map +1 -1
  11. package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
  12. package/dist/DboBuilder/TableHandler/TableHandler.js +4 -0
  13. package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
  14. package/dist/DboBuilder/TableHandler/delete.d.ts.map +1 -1
  15. package/dist/DboBuilder/TableHandler/delete.js +4 -1
  16. package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
  17. package/dist/DboBuilder/TableHandler/insert/insert.js +1 -1
  18. package/dist/DboBuilder/TableHandler/insert/insert.js.map +1 -1
  19. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +1 -1
  20. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js.map +1 -1
  21. package/dist/DboBuilder/TableHandler/update.js +1 -1
  22. package/dist/DboBuilder/TableHandler/update.js.map +1 -1
  23. package/dist/DboBuilder/TableHandler/updateBatch.d.ts.map +1 -1
  24. package/dist/DboBuilder/TableHandler/updateBatch.js +4 -1
  25. package/dist/DboBuilder/TableHandler/updateBatch.js.map +1 -1
  26. package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
  27. package/dist/DboBuilder/ViewHandler/count.js +1 -1
  28. package/dist/DboBuilder/ViewHandler/count.js.map +1 -1
  29. package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
  30. package/dist/DboBuilder/ViewHandler/find.js +1 -1
  31. package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
  32. package/dist/DboBuilder/ViewHandler/size.d.ts.map +1 -1
  33. package/dist/DboBuilder/ViewHandler/size.js +1 -1
  34. package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
  35. package/dist/DboBuilder/ViewHandler/subscribe.d.ts.map +1 -1
  36. package/dist/DboBuilder/ViewHandler/subscribe.js +1 -0
  37. package/dist/DboBuilder/ViewHandler/subscribe.js.map +1 -1
  38. package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -1
  39. package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
  40. package/dist/DboBuilder/dboBuilderUtils.js +7 -2
  41. package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
  42. package/dist/PubSubManager/PubSubManager.d.ts +5 -2
  43. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  44. package/dist/PubSubManager/PubSubManager.js +2 -4
  45. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  46. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts +3 -3
  47. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts.map +1 -1
  48. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js +2 -2
  49. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js.map +1 -1
  50. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts +3 -2
  51. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts.map +1 -1
  52. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js +8 -8
  53. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js.map +1 -1
  54. package/dist/PubSubManager/SyncReplication/syncData.js +1 -0
  55. package/dist/PubSubManager/SyncReplication/syncData.js.map +1 -1
  56. package/dist/PubSubManager/addSub.d.ts.map +1 -1
  57. package/dist/PubSubManager/addSub.js +2 -1
  58. package/dist/PubSubManager/addSub.js.map +1 -1
  59. package/dist/PubSubManager/addSync.d.ts.map +1 -1
  60. package/dist/PubSubManager/addSync.js +2 -0
  61. package/dist/PubSubManager/addSync.js.map +1 -1
  62. package/dist/PubSubManager/init/getPubSubManagerInitQuery.js +4 -4
  63. package/dist/TableConfig/getTableConfigSchemaQueries.js +2 -2
  64. package/dist/TableConfig/getTableConfigSchemaQueries.js.map +1 -1
  65. package/dist/TableConfig/getTableTriggerQueries.d.ts +5 -0
  66. package/dist/TableConfig/getTableTriggerQueries.d.ts.map +1 -0
  67. package/dist/TableConfig/getTableTriggerQueries.js +61 -0
  68. package/dist/TableConfig/getTableTriggerQueries.js.map +1 -0
  69. package/dist/TableConfig/getTableTriggerQueries.spec.d.ts +2 -0
  70. package/dist/TableConfig/getTableTriggerQueries.spec.d.ts.map +1 -0
  71. package/dist/TableConfig/getTableTriggerQueries.spec.js +56 -0
  72. package/dist/TableConfig/getTableTriggerQueries.spec.js.map +1 -0
  73. package/dist/TableConfig/initTableConfig.d.ts.map +1 -1
  74. package/dist/TableConfig/initTableConfig.js +8 -63
  75. package/dist/TableConfig/initTableConfig.js.map +1 -1
  76. package/dist/runClientRequest.d.ts.map +1 -1
  77. package/dist/runClientRequest.js +2 -7
  78. package/dist/runClientRequest.js.map +1 -1
  79. package/lib/Auth/utils/getSessionUser.spec.ts +41 -0
  80. package/lib/Auth/utils/getSessionUser.ts +19 -0
  81. package/lib/DBSchemaBuilder/getColumnTypescriptDefinition.ts +2 -2
  82. package/lib/DboBuilder/TableHandler/TableHandler.ts +9 -1
  83. package/lib/DboBuilder/TableHandler/delete.ts +8 -1
  84. package/lib/DboBuilder/TableHandler/insert/insert.ts +1 -1
  85. package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +1 -1
  86. package/lib/DboBuilder/TableHandler/update.ts +1 -1
  87. package/lib/DboBuilder/TableHandler/updateBatch.ts +4 -1
  88. package/lib/DboBuilder/ViewHandler/count.ts +5 -1
  89. package/lib/DboBuilder/ViewHandler/find.ts +5 -1
  90. package/lib/DboBuilder/ViewHandler/size.ts +5 -1
  91. package/lib/DboBuilder/ViewHandler/subscribe.ts +1 -0
  92. package/lib/DboBuilder/dboBuilderUtils.ts +11 -2
  93. package/lib/PubSubManager/PubSubManager.ts +20 -5
  94. package/lib/PubSubManager/SyncReplication/fetchSyncServerData.ts +4 -4
  95. package/lib/PubSubManager/SyncReplication/getSyncUtilFunctions.ts +16 -8
  96. package/lib/PubSubManager/SyncReplication/syncData.ts +1 -1
  97. package/lib/PubSubManager/addSub.ts +2 -0
  98. package/lib/PubSubManager/addSync.ts +2 -0
  99. package/lib/PubSubManager/init/getPubSubManagerInitQuery.ts +4 -4
  100. package/lib/TableConfig/getTableConfigSchemaQueries.ts +2 -2
  101. package/lib/TableConfig/getTableTriggerQueries.spec.ts +77 -0
  102. package/lib/TableConfig/getTableTriggerQueries.ts +74 -0
  103. package/lib/TableConfig/initTableConfig.ts +8 -73
  104. package/lib/runClientRequest.ts +3 -15
  105. package/package.json +1 -1
@@ -3,7 +3,12 @@
3
3
  * Licensed under the MIT License. See LICENSE in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
 
6
- import type { DBHandlerServer, DboBuilder, PRGLIOSocket } from "../DboBuilder/DboBuilder";
6
+ import type {
7
+ DBHandlerServer,
8
+ DboBuilder,
9
+ LocalParams,
10
+ PRGLIOSocket,
11
+ } from "../DboBuilder/DboBuilder";
7
12
  import type { PostgresNotifListenManager } from "../PostgresNotifListenManager";
8
13
  import type { DB } from "../Prostgles";
9
14
  import { addSync } from "./addSync";
@@ -56,6 +61,7 @@ export type SyncParams = {
56
61
  lr?: AnyObject;
57
62
  is_syncing: boolean;
58
63
  handlers: ReturnType<(typeof ReplicationProtocol)["getServerHandlers"]>;
64
+ localParams: LocalParams;
59
65
  };
60
66
 
61
67
  export type AddSyncParams = SyncTableInfo & {
@@ -74,6 +80,7 @@ export type AddSyncParams = SyncTableInfo & {
74
80
  };
75
81
  condition: string;
76
82
  throttle?: number;
83
+ localParams: LocalParams;
77
84
  };
78
85
 
79
86
  export type ViewSubscriptionOptions = (
@@ -114,6 +121,7 @@ export type SubscriptionParams = {
114
121
 
115
122
  onData?: OnData;
116
123
  socket: PRGLIOSocket | undefined;
124
+ localParams?: LocalParams;
117
125
 
118
126
  lastPushed: number;
119
127
  /**
@@ -143,6 +151,7 @@ export type Subscription = Pick<
143
151
  | "table_info"
144
152
  | "filter"
145
153
  | "table_rules"
154
+ | "localParams"
146
155
  > & {
147
156
  triggers: [AddTriggerParams, ...AddTriggerParams[]];
148
157
  };
@@ -321,7 +330,15 @@ export class PubSubManager {
321
330
  };
322
331
 
323
332
  getSubData = async (sub: Subscription) => {
324
- const { table_info, filter, selectParams: params, table_rules, socket, onData } = sub; //, subOne = false
333
+ const {
334
+ table_info,
335
+ filter,
336
+ selectParams: params,
337
+ table_rules,
338
+ localParams,
339
+ socket,
340
+ onData,
341
+ } = sub; //, subOne = false
325
342
  const { name: table_name } = table_info;
326
343
  const tableHandler = this.dbo[table_name];
327
344
  if (!onData && !socket) {
@@ -337,9 +354,7 @@ export class PubSubManager {
337
354
  params,
338
355
  undefined,
339
356
  table_rules,
340
- socket && {
341
- clientReq: { socket },
342
- },
357
+ localParams,
343
358
  )) as AnyObject[];
344
359
  return { data };
345
360
  } catch (err) {
@@ -1,5 +1,5 @@
1
1
  import type { AnyObject } from "prostgles-types";
2
- import type { PRGLIOSocket } from "../../DboBuilder/DboBuilder";
2
+ import type { LocalParams } from "../../DboBuilder/DboBuilder";
3
3
  import type { TableHandler } from "../../DboBuilder/TableHandler/TableHandler";
4
4
  import type { SyncParams } from "../PubSubManager";
5
5
  import { getSyncOrderByAndFields } from "./getSyncOrderByAndFields";
@@ -8,12 +8,12 @@ import { getSyncBatchOptions } from "./getSyncBatchOptions";
8
8
  export const fetchSyncServerData = async (
9
9
  {
10
10
  tableHandler,
11
- socket,
11
+ localParams,
12
12
  from_synced,
13
13
  offset,
14
14
  }: {
15
15
  tableHandler: TableHandler;
16
- socket: PRGLIOSocket;
16
+ localParams: LocalParams;
17
17
  from_synced: number | undefined;
18
18
  offset: number | undefined;
19
19
  },
@@ -48,7 +48,7 @@ export const fetchSyncServerData = async (
48
48
  },
49
49
  undefined,
50
50
  table_rules,
51
- { clientReq: { socket } },
51
+ localParams,
52
52
  );
53
53
 
54
54
  return batchRows as AnyObject[];
@@ -6,7 +6,7 @@ import {
6
6
  type AnyObject,
7
7
  type SyncBatchParams,
8
8
  } from "prostgles-types";
9
- import type { PRGLIOSocket } from "../../DboBuilder/DboBuilder";
9
+ import type { LocalParams, PRGLIOSocket } from "../../DboBuilder/DboBuilder";
10
10
  import type { TableHandler } from "../../DboBuilder/TableHandler/TableHandler";
11
11
  import { getSyncOrderByAndFields } from "./getSyncOrderByAndFields";
12
12
  import type { PubSubManager, SyncParams } from "../PubSubManager";
@@ -26,6 +26,7 @@ type Args = {
26
26
  sync: SyncParams;
27
27
  pubSubManager: PubSubManager;
28
28
  logSyncData: (state: Extract<EventTypes.Sync, { command: "syncData" }>["state"]) => void;
29
+ localParams: LocalParams;
29
30
  };
30
31
 
31
32
  export const getSyncUtilFunctions = ({
@@ -34,6 +35,7 @@ export const getSyncUtilFunctions = ({
34
35
  sync,
35
36
  pubSubManager,
36
37
  logSyncData,
38
+ localParams,
37
39
  }: Args) => {
38
40
  const {
39
41
  synced_field,
@@ -71,12 +73,18 @@ export const getSyncUtilFunctions = ({
71
73
  { orderBy: orderByAsc, select: sync_fields, limit, offset },
72
74
  undefined,
73
75
  table_rules,
74
- { clientReq: { socket } },
76
+ localParams,
75
77
  )) as AnyObject[];
76
78
 
77
79
  const last_rows = first_rows.slice(-1); // Why not logic below?
78
80
  // const last_rows = await _this?.dbo[table_name]?.find?.(_filter, { orderBy: (orderByDesc as OrderBy), select: sync_fields, limit: 1, offset: -offset || 0 }, null, table_rules);
79
- const count = await tableHandler.count(batchFilter, undefined, undefined, table_rules);
81
+ const count = await tableHandler.count(
82
+ batchFilter,
83
+ undefined,
84
+ undefined,
85
+ table_rules,
86
+ localParams,
87
+ );
80
88
 
81
89
  return {
82
90
  s_fr: first_rows[0],
@@ -128,7 +136,7 @@ export const getSyncUtilFunctions = ({
128
136
  },
129
137
  getServerData = async (from_synced: number | undefined, offset = 0): Promise<AnyObject[]> => {
130
138
  return fetchSyncServerData(
131
- { tableHandler, socket, from_synced, offset },
139
+ { tableHandler, localParams, from_synced, offset },
132
140
  { filter, id_fields, params, synced_field, batch_size, table_rules },
133
141
  );
134
142
  },
@@ -173,7 +181,7 @@ export const getSyncUtilFunctions = ({
173
181
  },
174
182
  undefined,
175
183
  table_rules,
176
- { clientReq: { socket } },
184
+ localParams,
177
185
  )) as AnyObject[];
178
186
  let rowsToInsert = data.filter(
179
187
  (incomingRow) =>
@@ -201,7 +209,7 @@ export const getSyncUtilFunctions = ({
201
209
  { removeDisallowedFields: true },
202
210
  undefined,
203
211
  table_rules,
204
- { clientReq: { socket } },
212
+ localParams,
205
213
  );
206
214
  } else {
207
215
  rowsToUpdate = [];
@@ -213,7 +221,7 @@ export const getSyncUtilFunctions = ({
213
221
  { removeDisallowedFields: true },
214
222
  undefined,
215
223
  table_rules,
216
- { clientReq: { socket } },
224
+ localParams,
217
225
  );
218
226
  } else {
219
227
  rowsToInsert = [];
@@ -355,7 +363,7 @@ export const getSyncUtilFunctions = ({
355
363
  { select: sync_fields, limit: 1 },
356
364
  undefined,
357
365
  table_rules,
358
- { clientReq: { socket } },
366
+ localParams,
359
367
  );
360
368
  }
361
369
 
@@ -82,7 +82,6 @@ export async function syncData(
82
82
  if (!tableHandler?.find) {
83
83
  throw `dbo.${table_name}.find missing or not allowed`;
84
84
  }
85
-
86
85
  const {
87
86
  upsertData,
88
87
  updateSyncLR,
@@ -98,6 +97,7 @@ export async function syncData(
98
97
  sync,
99
98
  pubSubManager: this,
100
99
  logSyncData,
100
+ localParams: sync.localParams,
101
101
  });
102
102
 
103
103
  /* Used to throttle and merge incoming updates */
@@ -34,6 +34,7 @@ export async function addSub(
34
34
  table_info,
35
35
  subscribeOptions,
36
36
  tracked_columns,
37
+ localParams,
37
38
  } = subscriptionParams;
38
39
  const table_name = table_info.name;
39
40
 
@@ -65,6 +66,7 @@ export async function addSub(
65
66
  is_throttling: false,
66
67
  socket_id: socket?.id,
67
68
  table_rules,
69
+ localParams,
68
70
  triggers: [mainTrigger],
69
71
  };
70
72
 
@@ -20,6 +20,7 @@ export async function addSync(
20
20
  const res = await tryCatchV2(async () => {
21
21
  const { socket, rawSelect, table_info, table_rules, filter, params, condition, initialData } =
22
22
  syncParams;
23
+ const { localParams } = syncParams;
23
24
  const conditionParsed = parseCondition(condition);
24
25
 
25
26
  const { name: table_name } = table_info;
@@ -84,6 +85,7 @@ export async function addSync(
84
85
  socket,
85
86
  params,
86
87
  handlers,
88
+ localParams,
87
89
  };
88
90
  const unsyncChn = channelName + "unsync";
89
91
  socket.removeAllListeners(unsyncChn);
@@ -162,11 +162,11 @@ BEGIN
162
162
  END IF;
163
163
 
164
164
  IF length(key) > 0 THEN
165
- RETURN jsonb_extract_path(user_jsonb, key);
165
+ RETURN jsonb_extract_path_text(user_jsonb, key);
166
166
  END IF;
167
167
  RETURN user_jsonb;
168
168
  END;
169
- $$ LANGUAGE plpgsql;
169
+ $$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
170
170
  COMMENT ON FUNCTION prostgles."user" IS 'Used for row level security';
171
171
 
172
172
  CREATE OR REPLACE FUNCTION prostgles.user_id()
@@ -174,7 +174,7 @@ BEGIN
174
174
  BEGIN
175
175
  RETURN prostgles.user('id')::UUID;
176
176
  END;
177
- $$ LANGUAGE plpgsql;
177
+ $$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
178
178
  COMMENT ON FUNCTION prostgles.user_id IS 'Session user id';
179
179
 
180
180
  CREATE OR REPLACE FUNCTION prostgles.user_type()
@@ -182,7 +182,7 @@ BEGIN
182
182
  BEGIN
183
183
  RETURN prostgles.user('type')::TEXT;
184
184
  END;
185
- $$ LANGUAGE plpgsql;
185
+ $$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
186
186
  COMMENT ON FUNCTION prostgles.user_type IS 'Session user type';
187
187
 
188
188
  CREATE TABLE IF NOT EXISTS prostgles.apps (
@@ -115,7 +115,7 @@ const getTableQueries = async (
115
115
  `);`,
116
116
  ].join("\n");
117
117
 
118
- const dataQuerys = rows.map((row) => {
118
+ const insertQueries = rows.map((row) => {
119
119
  const values = allColumns.map((key) => row[key]);
120
120
  return as.format(
121
121
  `INSERT INTO ${tableName} (${allColumns.map((t) => asName(t)).join(", ")}) ` +
@@ -123,7 +123,7 @@ const getTableQueries = async (
123
123
  { values },
124
124
  );
125
125
  });
126
- const queries = [createQuery, ...dataQuerys];
126
+ const queries = [createQuery, ...insertQueries];
127
127
  return {
128
128
  queries,
129
129
  colDefs,
@@ -0,0 +1,77 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { asName } from "prostgles-types";
4
+ import type { DB } from "../initProstgles";
5
+ import { getTableTriggerQueries } from "./getTableTriggerQueries";
6
+
7
+ void test("trigger configuration quotes names and bodies and preserves unmanaged triggers", async () => {
8
+ const db = {
9
+ any: () =>
10
+ Promise.resolve([
11
+ { name: "manual", comment: null },
12
+ { name: "old_insert", comment: "prostgles.tableConfig:old" },
13
+ ]),
14
+ } as unknown as DB;
15
+ const queries = await getTableTriggerQueries(
16
+ db,
17
+ "Odd ' table",
18
+ {
19
+ triggers: {
20
+ audit: {
21
+ type: "after",
22
+ actions: ["insert"],
23
+ forEach: "row",
24
+ query: "BEGIN RAISE NOTICE '$$'; RETURN NULL; END;",
25
+ },
26
+ },
27
+ },
28
+ asName,
29
+ );
30
+ assert.ok(queries.some((query) => query.includes('ON "Odd \' table"')));
31
+ assert.ok(
32
+ queries.some((query) =>
33
+ query.includes("AS 'BEGIN RAISE NOTICE ''$$''; RETURN NULL; END;';"),
34
+ ),
35
+ );
36
+ assert.ok(
37
+ queries.some((query) => query.includes('DROP TRIGGER "old_insert"')),
38
+ );
39
+ assert.ok(!queries.some((query) => query.includes('DROP TRIGGER "manual"')));
40
+ });
41
+
42
+ void test("unchanged triggers do not produce DDL; changed bodies replace them", async () => {
43
+ const trigger = {
44
+ type: "after",
45
+ actions: ["update"],
46
+ forEach: "row",
47
+ query: "BEGIN RETURN NULL; END;" as string,
48
+ } as const;
49
+ const config = {
50
+ triggers: { audit: { ...trigger, actions: [...trigger.actions] } },
51
+ };
52
+ const first = await getTableTriggerQueries(
53
+ { any: () => Promise.resolve([]) } as unknown as DB,
54
+ "records",
55
+ config,
56
+ asName,
57
+ );
58
+ const commentQuery = first.find((query) => query.startsWith("COMMENT ON"))!;
59
+ const comment = commentQuery.split(" IS '")[1]!.slice(0, -2);
60
+ const db = {
61
+ any: () => Promise.resolve([{ name: "audit_update", comment }]),
62
+ } as unknown as DB;
63
+ assert.deepEqual(
64
+ await getTableTriggerQueries(db, "records", config, asName),
65
+ [],
66
+ );
67
+ config.triggers.audit.query =
68
+ "BEGIN RAISE NOTICE 'changed'; RETURN NULL; END;";
69
+ assert.ok(
70
+ (await getTableTriggerQueries(db, "records", config, asName)).some(
71
+ (query) => query.startsWith("CREATE OR REPLACE FUNCTION"),
72
+ ),
73
+ );
74
+ assert.deepEqual(await getTableTriggerQueries(db, "records", {}, asName), [
75
+ 'DROP TRIGGER "audit_update" ON "records";',
76
+ ]);
77
+ });
@@ -0,0 +1,74 @@
1
+ import { as } from "pg-promise";
2
+ import { md5 } from "prostgles-types/dist/md5";
3
+ import type { DB } from "../initProstgles";
4
+ import type { TableConfig } from "./TableConfigTypes";
5
+
6
+ const MANAGED_TRIGGER_PREFIX = "prostgles.tableConfig:";
7
+
8
+ /** Reconcile only triggers owned by tableConfig; preserve manually created triggers. */
9
+ export const getTableTriggerQueries = async (
10
+ db: DB,
11
+ tableName: string,
12
+ tableConfig: TableConfig[string],
13
+ asName: (name: string) => string,
14
+ ): Promise<string[]> => {
15
+ const tableIdent = asName(tableName);
16
+ const existing = await db.any<{ name: string; comment: string | null }>(
17
+ `
18
+ SELECT t.tgname AS name, obj_description(t.oid, 'pg_trigger') AS comment
19
+ FROM pg_trigger t
20
+ WHERE t.tgrelid = to_regclass($1) AND NOT t.tgisinternal
21
+ `,
22
+ [tableIdent],
23
+ );
24
+ const queries: string[] = [];
25
+ const desired = new Set<string>();
26
+ const isDropped = tableConfig.dropIfExists || tableConfig.dropIfExistsCascade;
27
+ for (const [functionName, trigger] of Object.entries(
28
+ tableConfig.triggers ?? {},
29
+ )) {
30
+ const functionIdent = asName(functionName);
31
+ let functionAdded = false;
32
+ for (const action of trigger.actions) {
33
+ const name = `${functionName}_${action}`;
34
+ desired.add(name);
35
+ const triggerIdent = asName(name);
36
+ const transitionTables =
37
+ trigger.forEach === "row"
38
+ ? ""
39
+ : [
40
+ "REFERENCING",
41
+ action !== "delete" ? "NEW TABLE AS new_table" : "",
42
+ action !== "insert" ? "OLD TABLE AS old_table" : "",
43
+ ].join(" ");
44
+ const definition = `CREATE TRIGGER ${triggerIdent}
45
+ ${trigger.type} ${action} ON ${tableIdent}
46
+ ${transitionTables} FOR EACH ${trigger.forEach}
47
+ EXECUTE FUNCTION ${functionIdent}();`;
48
+ const comment = MANAGED_TRIGGER_PREFIX + md5(definition + trigger.query);
49
+ const previous = existing.find((entry) => entry.name === name);
50
+ if (!isDropped && previous?.comment === comment) continue;
51
+ if (!functionAdded) {
52
+ queries.push(`CREATE OR REPLACE FUNCTION ${functionIdent}()
53
+ RETURNS trigger LANGUAGE plpgsql AS ${as.text(trigger.query)};`);
54
+ functionAdded = true;
55
+ }
56
+ queries.push(`DROP TRIGGER IF EXISTS ${triggerIdent} ON ${tableIdent};`);
57
+ queries.push(definition);
58
+ queries.push(
59
+ `COMMENT ON TRIGGER ${triggerIdent} ON ${tableIdent} IS ${as.text(comment)};`,
60
+ );
61
+ }
62
+ }
63
+ if (!isDropped) {
64
+ for (const trigger of existing) {
65
+ if (
66
+ trigger.comment?.startsWith(MANAGED_TRIGGER_PREFIX) &&
67
+ !desired.has(trigger.name)
68
+ ) {
69
+ queries.push(`DROP TRIGGER ${asName(trigger.name)} ON ${tableIdent};`);
70
+ }
71
+ }
72
+ }
73
+ return queries;
74
+ };
@@ -9,6 +9,7 @@ import { fetchTableConstraints } from "./fetchTableConstraints";
9
9
  import { getConstraintDefinitionQueries } from "./getConstraintDefinitionQueries";
10
10
  import { getFutureTableSchema } from "./getFutureTableSchema";
11
11
  import { getTableColumnQueries } from "./getTableColumnQueries";
12
+ import { getTableTriggerQueries } from "./getTableTriggerQueries";
12
13
  import { getIndexesQueries } from "./indexes/getIndexesQueries";
13
14
  import { runMigrations } from "./runMigrations";
14
15
  import type { TableConfigurator } from "./TableConfigurator";
@@ -162,7 +163,7 @@ export const initTableConfig = async function (this: TableConfigurator) {
162
163
  const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
163
164
 
164
165
  /* isLookupTable table has already been created */
165
- const coldef =
166
+ const tableColumnDefinition =
166
167
  "isLookupTable" in tableConf ? undefined : (
167
168
  await getTableColumnQueries({
168
169
  db: this.db,
@@ -172,8 +173,8 @@ export const initTableConfig = async function (this: TableConfigurator) {
172
173
  })
173
174
  );
174
175
 
175
- if (coldef) {
176
- queries.push(coldef.fullQuery);
176
+ if (tableColumnDefinition) {
177
+ queries.push(tableColumnDefinition.fullQuery);
177
178
  }
178
179
 
179
180
  /** CONSTRAINTS */
@@ -181,13 +182,13 @@ export const initTableConfig = async function (this: TableConfigurator) {
181
182
  tableName,
182
183
  tableConf,
183
184
  });
184
- if (coldef?.isCreate) {
185
+ if (tableColumnDefinition?.isCreate) {
185
186
  queries.push(...(constraintDefs?.map((c) => c.alterQuery) ?? []));
186
- } else if (coldef) {
187
+ } else if (tableColumnDefinition) {
187
188
  const fullSchema = await getFutureTableSchema({
188
189
  db: this.db,
189
190
  tableName,
190
- columnDefs: coldef.columnDefs,
191
+ columnDefs: tableColumnDefinition.columnDefs,
191
192
  constraintDefs,
192
193
  });
193
194
  const futureCons = fullSchema.constraints.map((nc) => ({
@@ -234,73 +235,7 @@ export const initTableConfig = async function (this: TableConfigurator) {
234
235
  const indexQueries = await getIndexesQueries(this.db, tableName, tableConf);
235
236
  queries.push(...indexQueries);
236
237
 
237
- const { triggers, dropIfExists, dropIfExistsCascade } = tableConf;
238
- if (triggers) {
239
- const isDropped = dropIfExists || dropIfExistsCascade;
240
-
241
- const existingTriggers = await this.db.any<{ trigger_name: string }>(
242
- `
243
- SELECT event_object_table
244
- ,trigger_name
245
- FROM information_schema.triggers
246
- WHERE event_object_table = \${tableName}
247
- ORDER BY event_object_table
248
- `,
249
- { tableName },
250
- );
251
-
252
- // const existingTriggerFuncs = await this.dbo.sql!(`
253
- // SELECT p.oid,proname,prosrc,u.usename
254
- // FROM pg_proc p
255
- // JOIN pg_user u ON u.usesysid = p.proowner
256
- // WHERE prorettype = 2279;
257
- // `, {}, { returnType: "rows" }) as { proname: string }[];
258
-
259
- Object.entries(triggers).forEach(([triggerFuncName, trigger]) => {
260
- const funcNameParsed = asName(triggerFuncName);
261
-
262
- let addedFunc = false;
263
- const addFuncDef = () => {
264
- if (addedFunc) return;
265
- addedFunc = true;
266
- queries.push(`
267
- CREATE OR REPLACE FUNCTION ${funcNameParsed}()
268
- RETURNS trigger
269
- LANGUAGE plpgsql
270
- AS
271
- $$
272
-
273
- ${trigger.query}
274
-
275
- $$;
276
- `);
277
- };
278
-
279
- trigger.actions.forEach((action) => {
280
- const triggerActionName = triggerFuncName + "_" + action;
281
-
282
- const triggerActionNameParsed = asName(triggerActionName);
283
- if (isDropped) {
284
- queries.push(`DROP TRIGGER IF EXISTS ${triggerActionNameParsed} ON ${tableName};`);
285
- }
286
-
287
- if (isDropped || !existingTriggers.some((t) => t.trigger_name === triggerActionName)) {
288
- addFuncDef();
289
- const newTableName = action !== "delete" ? "NEW TABLE AS new_table" : "";
290
- const oldTableName = action !== "insert" ? "OLD TABLE AS old_table" : "";
291
- const transitionTables =
292
- trigger.forEach === "row" ? "" : `REFERENCING ${newTableName} ${oldTableName}`;
293
- queries.push(`
294
- CREATE TRIGGER ${triggerActionNameParsed}
295
- ${trigger.type} ${action} ON ${tableName}
296
- ${transitionTables}
297
- FOR EACH ${trigger.forEach}
298
- EXECUTE PROCEDURE ${funcNameParsed}();
299
- `);
300
- }
301
- });
302
- });
303
- }
238
+ queries.push(...(await getTableTriggerQueries(this.db, tableName, tableConf, asName)));
304
239
  }
305
240
 
306
241
  if (queries.length) {
@@ -1,16 +1,15 @@
1
- import type { SQLRequest, TableHandler, UserLike } from "prostgles-types";
1
+ import type { SQLRequest, TableHandler } from "prostgles-types";
2
2
  import {
3
3
  ABORTABLE_METHODS,
4
4
  getJSONBObjectSchemaValidationError,
5
5
  getJSONBSchemaValidationErrorAsync,
6
6
  getKeys,
7
- pickKeys,
8
7
  type AnyObject,
9
8
  } from "prostgles-types";
10
9
  import type { AuthClientRequest } from "./Auth/AuthTypes";
10
+ import { getSessionUser } from "./Auth/utils/getSessionUser";
11
11
  import type { LocalParams } from "./DboBuilder/DboBuilder";
12
12
  import type { TableHandler as TableHandlerServer } from "./DboBuilder/TableHandler/TableHandler";
13
- import { parseFieldFilter } from "./DboBuilder/ViewHandler/parseFieldFilter";
14
13
  import { canRunSQL } from "./DboBuilder/runSql/runSQL";
15
14
  import type { Prostgles } from "./Prostgles";
16
15
  import type { ParsedTableRule } from "./PublishParser/publishTypesAndUtils";
@@ -118,18 +117,7 @@ export const runClientRequest = async function (
118
117
  scope,
119
118
  );
120
119
 
121
- const sessionUser: UserLike | undefined =
122
- !clientInfo.user ? undefined : (
123
- {
124
- ...parseFieldFilter(
125
- //@ts-ignore
126
- clientInfo.sessionFields ?? [],
127
- false,
128
- getKeys(clientInfo.user),
129
- ),
130
- ...(pickKeys(clientInfo.user, ["id", "type"]) as UserLike),
131
- }
132
- );
120
+ const sessionUser = getSessionUser(clientInfo);
133
121
  const localParams: LocalParams = {
134
122
  clientReq,
135
123
  isRemoteRequest: { user: sessionUser, clientInfo },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.603",
3
+ "version": "4.2.605",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",