prostgles-server 4.2.602 → 4.2.604

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 (121) 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/DboBuilder/prepareShortestJoinPaths.d.ts.map +1 -1
  43. package/dist/DboBuilder/prepareShortestJoinPaths.js +9 -0
  44. package/dist/DboBuilder/prepareShortestJoinPaths.js.map +1 -1
  45. package/dist/DboBuilder/prepareShortestJoinPaths.spec.d.ts +2 -0
  46. package/dist/DboBuilder/prepareShortestJoinPaths.spec.d.ts.map +1 -0
  47. package/dist/DboBuilder/prepareShortestJoinPaths.spec.js +30 -0
  48. package/dist/DboBuilder/prepareShortestJoinPaths.spec.js.map +1 -0
  49. package/dist/Prostgles.d.ts +1 -0
  50. package/dist/Prostgles.d.ts.map +1 -1
  51. package/dist/Prostgles.js +1 -0
  52. package/dist/Prostgles.js.map +1 -1
  53. package/dist/PubSubManager/PubSubManager.d.ts +5 -2
  54. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  55. package/dist/PubSubManager/PubSubManager.js +2 -4
  56. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  57. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts +3 -3
  58. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.d.ts.map +1 -1
  59. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js +2 -2
  60. package/dist/PubSubManager/SyncReplication/fetchSyncServerData.js.map +1 -1
  61. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts +3 -2
  62. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.d.ts.map +1 -1
  63. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js +8 -8
  64. package/dist/PubSubManager/SyncReplication/getSyncUtilFunctions.js.map +1 -1
  65. package/dist/PubSubManager/SyncReplication/syncData.js +1 -0
  66. package/dist/PubSubManager/SyncReplication/syncData.js.map +1 -1
  67. package/dist/PubSubManager/addSub.d.ts.map +1 -1
  68. package/dist/PubSubManager/addSub.js +2 -1
  69. package/dist/PubSubManager/addSub.js.map +1 -1
  70. package/dist/PubSubManager/addSync.d.ts.map +1 -1
  71. package/dist/PubSubManager/addSync.js +2 -0
  72. package/dist/PubSubManager/addSync.js.map +1 -1
  73. package/dist/PubSubManager/init/getPubSubManagerInitQuery.js +4 -4
  74. package/dist/StorageClient/getFileTableConfig.d.ts.map +1 -1
  75. package/dist/StorageClient/getFileTableConfig.js +1 -0
  76. package/dist/StorageClient/getFileTableConfig.js.map +1 -1
  77. package/dist/StorageClient/getFileTableConfig.spec.d.ts +2 -0
  78. package/dist/StorageClient/getFileTableConfig.spec.d.ts.map +1 -0
  79. package/dist/StorageClient/getFileTableConfig.spec.js +23 -0
  80. package/dist/StorageClient/getFileTableConfig.spec.js.map +1 -0
  81. package/dist/TableConfig/getTableConfigSchemaQueries.js +2 -2
  82. package/dist/TableConfig/getTableConfigSchemaQueries.js.map +1 -1
  83. package/dist/TableConfig/initTableConfig.js +6 -6
  84. package/dist/TableConfig/initTableConfig.js.map +1 -1
  85. package/dist/initProstgles.d.ts.map +1 -1
  86. package/dist/initProstgles.js +9 -2
  87. package/dist/initProstgles.js.map +1 -1
  88. package/dist/runClientRequest.d.ts.map +1 -1
  89. package/dist/runClientRequest.js +2 -7
  90. package/dist/runClientRequest.js.map +1 -1
  91. package/lib/Auth/utils/getSessionUser.spec.ts +41 -0
  92. package/lib/Auth/utils/getSessionUser.ts +19 -0
  93. package/lib/DBSchemaBuilder/getColumnTypescriptDefinition.ts +2 -2
  94. package/lib/DboBuilder/TableHandler/TableHandler.ts +9 -1
  95. package/lib/DboBuilder/TableHandler/delete.ts +8 -1
  96. package/lib/DboBuilder/TableHandler/insert/insert.ts +1 -1
  97. package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +1 -1
  98. package/lib/DboBuilder/TableHandler/update.ts +1 -1
  99. package/lib/DboBuilder/TableHandler/updateBatch.ts +4 -1
  100. package/lib/DboBuilder/ViewHandler/count.ts +5 -1
  101. package/lib/DboBuilder/ViewHandler/find.ts +5 -1
  102. package/lib/DboBuilder/ViewHandler/size.ts +5 -1
  103. package/lib/DboBuilder/ViewHandler/subscribe.ts +1 -0
  104. package/lib/DboBuilder/dboBuilderUtils.ts +11 -2
  105. package/lib/DboBuilder/prepareShortestJoinPaths.spec.ts +29 -0
  106. package/lib/DboBuilder/prepareShortestJoinPaths.ts +13 -0
  107. package/lib/Prostgles.ts +1 -0
  108. package/lib/PubSubManager/PubSubManager.ts +20 -5
  109. package/lib/PubSubManager/SyncReplication/fetchSyncServerData.ts +4 -4
  110. package/lib/PubSubManager/SyncReplication/getSyncUtilFunctions.ts +16 -8
  111. package/lib/PubSubManager/SyncReplication/syncData.ts +1 -1
  112. package/lib/PubSubManager/addSub.ts +2 -0
  113. package/lib/PubSubManager/addSync.ts +2 -0
  114. package/lib/PubSubManager/init/getPubSubManagerInitQuery.ts +4 -4
  115. package/lib/StorageClient/getFileTableConfig.spec.ts +19 -0
  116. package/lib/StorageClient/getFileTableConfig.ts +1 -0
  117. package/lib/TableConfig/getTableConfigSchemaQueries.ts +2 -2
  118. package/lib/TableConfig/initTableConfig.ts +6 -6
  119. package/lib/initProstgles.ts +8 -2
  120. package/lib/runClientRequest.ts +3 -15
  121. package/package.json +1 -1
@@ -125,7 +125,11 @@ export async function _delete(
125
125
  // }
126
126
  // }
127
127
 
128
- const queryWithRLS = withUserRLS(localParams, queryWithoutRLS);
128
+ const queryWithRLS = withUserRLS(
129
+ localParams,
130
+ queryWithoutRLS,
131
+ !!this.getTransaction(localParams),
132
+ );
129
133
 
130
134
  const queryToReturn = await getReturnTypeQuery({
131
135
  handler: this,
@@ -155,6 +159,9 @@ export async function _delete(
155
159
  "onInsteadOfDelete requires a transaction. Please wrap the delete call in a transaction.",
156
160
  );
157
161
  }
162
+ if (localParams?.isRemoteRequest) {
163
+ await transaction.t.none(withUserRLS(localParams, ""));
164
+ }
158
165
  const result = await onInsteadOfDelete({
159
166
  context: this.dboBuilder.prostgles.context,
160
167
  queryType,
@@ -164,7 +164,7 @@ export async function insert(
164
164
  }
165
165
 
166
166
  const queryWithoutUserRLS = query;
167
- const queryWithRLS = withUserRLS(localParams, query);
167
+ const queryWithRLS = withUserRLS(localParams, query, !!this.getTransaction(localParams));
168
168
 
169
169
  const queryToReturn = await getReturnTypeQuery({
170
170
  handler: this,
@@ -65,7 +65,7 @@ export const runInsertUpdateQuery = async (args: RunInsertUpdateQueryArgs) => {
65
65
  checkCondition = `NOT (${checkCond.where})`;
66
66
  }
67
67
  const hasReturning = !!returningSelectItems.length;
68
- const userRLS = withUserRLS(localParams, "");
68
+ const userRLS = withUserRLS(localParams, "", !!tableHandler.getTransaction(localParams));
69
69
  const CHECK_CONDITION_ALIAS = "prostgles_check_condition";
70
70
  const RETURNING_ALIAS_PREFIX = "prostgles_returning_";
71
71
  const returningSelectKeyRemap = new Map<string, string>();
@@ -166,7 +166,7 @@ export async function update(
166
166
  ).getQuery();
167
167
  query += "\n" + updateFilter.where;
168
168
  const queryWithoutUserRLS = query;
169
- query = withUserRLS(localParams, query);
169
+ query = withUserRLS(localParams, query, !!this.getTransaction(localParams));
170
170
 
171
171
  const queryToReturn = await getReturnTypeQuery({
172
172
  handler: this,
@@ -37,7 +37,10 @@ export async function updateBatch(
37
37
  return query;
38
38
  }),
39
39
  );
40
- const queries = [withUserRLS(localParams, ""), ...updateQueries];
40
+ const queries = [
41
+ withUserRLS(localParams, "", !!this.getTransaction(localParams)),
42
+ ...updateQueries,
43
+ ];
41
44
 
42
45
  const queryToReturn = await getReturnTypeQuery({
43
46
  handler: this,
@@ -41,7 +41,11 @@ export async function count(
41
41
  ${findQuery}
42
42
  ) t
43
43
  `;
44
- const queryWithRLS = withUserRLS(localParams, queryWithoutUserRLS);
44
+ const queryWithRLS = withUserRLS(
45
+ localParams,
46
+ queryWithoutUserRLS,
47
+ !!this.getTransaction(localParams),
48
+ );
45
49
 
46
50
  const queryToReturn = await getReturnTypeQuery({
47
51
  handler: this,
@@ -113,7 +113,11 @@ export const find = async function (
113
113
  !!selectParamsLimitCheck.groupBy,
114
114
  );
115
115
 
116
- const queryWithRLS = withUserRLS(localParams, queryWithoutRLS);
116
+ const queryWithRLS = withUserRLS(
117
+ localParams,
118
+ queryWithoutRLS,
119
+ !!this.getTransaction(localParams),
120
+ );
117
121
 
118
122
  const queryToReturn = await getReturnTypeQuery({
119
123
  handler: this,
@@ -44,7 +44,11 @@ export async function size(
44
44
  ${selectQueryWithoutRLS}
45
45
  ) prgl_size_query
46
46
  `;
47
- const queryWithRLS = withUserRLS(localParams, queryWithoutUserRLS);
47
+ const queryWithRLS = withUserRLS(
48
+ localParams,
49
+ queryWithoutUserRLS,
50
+ !!this.getTransaction(localParams),
51
+ );
48
52
 
49
53
  const queryToReturn = await getReturnTypeQuery({
50
54
  handler: this,
@@ -92,6 +92,7 @@ async function subscribe(
92
92
  { actions, skipFirst, throttle, throttleOpts, skipChangedColumnsCheck },
93
93
  table_rules?.select,
94
94
  ),
95
+ localParams,
95
96
  lastPushed: 0,
96
97
  tracked_columns: !firstField ? undefined : [firstField, ...otherFields],
97
98
  pushRequestedVersion: 0,
@@ -178,13 +178,22 @@ export const getCanExecute = async (db: DB) => {
178
178
 
179
179
  export const QUERY_ID_PREFIX = "-- prostgles query id: ";
180
180
 
181
- export const withUserRLS = (localParams: LocalParams | undefined, query: string) => {
181
+ export const withUserRLS = (
182
+ localParams: LocalParams | undefined,
183
+ query: string,
184
+ inTransaction = false,
185
+ ) => {
182
186
  const user = localParams?.isRemoteRequest?.user;
183
- const queryPrefix = `SET SESSION "prostgles.user" \nTO`;
187
+ const queryPrefix = `SET LOCAL "prostgles.user" \nTO`;
184
188
  let firstQuery = `${queryPrefix} '';`;
185
189
  if (user) {
186
190
  firstQuery = pgp.as.format(`${queryPrefix} \${user};`, { user });
187
191
  }
192
+ // Local calls through a transaction's dbx must preserve its request context.
193
+ // Anonymous remote requests still explicitly clear the user.
194
+ if (inTransaction && !localParams?.isRemoteRequest) {
195
+ firstQuery = "";
196
+ }
188
197
 
189
198
  const queryId = crypto.randomUUID();
190
199
  return [QUERY_ID_PREFIX + queryId, firstQuery, query].filter(Boolean).join("\n");
@@ -0,0 +1,29 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import type { DboBuilder } from "./DboBuilder";
4
+ import { prepareShortestJoinPaths } from "./prepareShortestJoinPaths";
5
+
6
+ void test("configured joins are deferred only during table configuration", async () => {
7
+ const builder = {
8
+ prostgles: { preparingTableConfig: true, opts: { joins: [
9
+ { tables: ["conditions", "members"], on: [{ project_id: "project_id" }], type: "many-many" },
10
+ ] } },
11
+ tablesOrViews: [],
12
+ } as unknown as DboBuilder;
13
+ assert.deepEqual((await prepareShortestJoinPaths(builder)).joins, []);
14
+ builder.prostgles.preparingTableConfig = false;
15
+ await assert.rejects(prepareShortestJoinPaths(builder), (error: unknown) =>
16
+ typeof error === "string" && error.includes("Table not found: conditions")
17
+ );
18
+ });
19
+
20
+ void test("existing configured joins remain available during table configuration", async () => {
21
+ const join = { tables: ["conditions", "members"], on: [{ project_id: "project_id" }], type: "many-many" };
22
+ const builder = {
23
+ prostgles: { preparingTableConfig: true, opts: { joins: [join] } },
24
+ tablesOrViews: ["conditions", "members"].map((name) => ({ name, columns: [{ name: "project_id" }] })),
25
+ } as unknown as DboBuilder;
26
+ assert.deepEqual((await prepareShortestJoinPaths(builder)).joins, [join]);
27
+ builder.prostgles.preparingTableConfig = false;
28
+ assert.deepEqual((await prepareShortestJoinPaths(builder)).joins, [join]);
29
+ });
@@ -18,6 +18,19 @@ export async function prepareShortestJoinPaths(dboBuilder: DboBuilder): Promise<
18
18
  throw new Error("Could not create join config. this.tablesOrViews missing");
19
19
  }
20
20
 
21
+ // The initial DBO is needed by tableConfig before its tables/columns exist.
22
+ // Defer only joins that cannot be resolved yet; the final rebuild validates all.
23
+ if (Array.isArray(joinConfig) && dboBuilder.prostgles.preparingTableConfig) {
24
+ const tables = dboBuilder.tablesOrViews;
25
+ joinConfig = joinConfig.filter((join) => join.tables.every((name, index) => {
26
+ const table = tables.find((candidate) => candidate.name === name);
27
+ return table && join.on.every((on) =>
28
+ (index === 0 ? Object.keys(on) : Object.values(on)).every((column) =>
29
+ table.columns.some((candidate) => candidate.name === column)
30
+ )
31
+ );
32
+ }));
33
+ }
21
34
  const inferredJoins = await getInferredJoins2(dboBuilder.tablesOrViews);
22
35
  if (joinConfig === "inferred") {
23
36
  joinConfig = inferredJoins;
package/lib/Prostgles.ts CHANGED
@@ -106,6 +106,7 @@ export class Prostgles {
106
106
 
107
107
  keywords = DEFAULT_KEYWORDS;
108
108
  loaded = false;
109
+ preparingTableConfig = false;
109
110
 
110
111
  dbEventsManager?: DBEventsManager;
111
112
  schemaAge = "0";
@@ -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 (
@@ -0,0 +1,19 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import type { Prostgles } from "../Prostgles";
4
+ import { getFileTableConfig } from "./getFileTableConfig";
5
+
6
+ void test("managed files preserve hooks on other tables and append file hooks", () => {
7
+ const guard = { afterEach: [{ commands: { insert: 1 }, validate: async () => {} }] };
8
+ const fileGuard = { beforeEach: [{ commands: { insert: 1 }, validate: async () => {} }] };
9
+ const prostgles = {
10
+ opts: {
11
+ fileTable: { tableName: "files", storageClient: {}, expressApp: {} },
12
+ tableHooks: { documents: guard, files: fileGuard },
13
+ },
14
+ } as unknown as Prostgles;
15
+ const result = getFileTableConfig(prostgles);
16
+ assert.equal(result.tableHooks?.documents, guard);
17
+ assert.equal(result.tableHooks.files?.beforeEach?.length, 2);
18
+ assert.equal(result.tableHooks.files.beforeEach[1], fileGuard.beforeEach[0]);
19
+ });
@@ -103,6 +103,7 @@ export const getFileTableConfig = (
103
103
 
104
104
  const userFileTableHooks = tableHooks?.[fileTableName];
105
105
  const mergedTableHooks: TableHooks<void, any> = {
106
+ ...tableHooks,
106
107
  [fileTableName]: {
107
108
  ...userFileTableHooks,
108
109
  beforeEach: [
@@ -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,
@@ -162,7 +162,7 @@ export const initTableConfig = async function (this: TableConfigurator) {
162
162
  const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
163
163
 
164
164
  /* isLookupTable table has already been created */
165
- const coldef =
165
+ const tableColumnDefinition =
166
166
  "isLookupTable" in tableConf ? undefined : (
167
167
  await getTableColumnQueries({
168
168
  db: this.db,
@@ -172,8 +172,8 @@ export const initTableConfig = async function (this: TableConfigurator) {
172
172
  })
173
173
  );
174
174
 
175
- if (coldef) {
176
- queries.push(coldef.fullQuery);
175
+ if (tableColumnDefinition) {
176
+ queries.push(tableColumnDefinition.fullQuery);
177
177
  }
178
178
 
179
179
  /** CONSTRAINTS */
@@ -181,13 +181,13 @@ export const initTableConfig = async function (this: TableConfigurator) {
181
181
  tableName,
182
182
  tableConf,
183
183
  });
184
- if (coldef?.isCreate) {
184
+ if (tableColumnDefinition?.isCreate) {
185
185
  queries.push(...(constraintDefs?.map((c) => c.alterQuery) ?? []));
186
- } else if (coldef) {
186
+ } else if (tableColumnDefinition) {
187
187
  const fullSchema = await getFutureTableSchema({
188
188
  db: this.db,
189
189
  tableName,
190
- columnDefs: coldef.columnDefs,
190
+ columnDefs: tableColumnDefinition.columnDefs,
191
191
  constraintDefs,
192
192
  });
193
193
  const futureCons = fullSchema.constraints.map((nc) => ({
@@ -223,8 +223,14 @@ export const initProstgles = async function (
223
223
 
224
224
  /* 2. Execute any SQL file if provided */
225
225
  await runSQLFile(this);
226
- await this.rebuildDBO();
227
- await this.initTableConfig(reason);
226
+ this.preparingTableConfig = true;
227
+ try {
228
+ await this.rebuildDBO();
229
+ await this.initTableConfig(reason);
230
+ } finally {
231
+ this.preparingTableConfig = false;
232
+ }
233
+ // Validate all configured joins against the completed schema before publishing.
228
234
  await this.rebuildDBO();
229
235
  await this.createContext(reason);
230
236
  this.initRestApi();
@@ -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.602",
3
+ "version": "4.2.604",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",