prostgles-server 4.2.347 → 4.2.349

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/Auth/endpoints/setOAuthRequestHandlers.d.ts.map +1 -1
  2. package/dist/Auth/endpoints/setOAuthRequestHandlers.js +3 -1
  3. package/dist/Auth/endpoints/setOAuthRequestHandlers.js.map +1 -1
  4. package/dist/DboBuilder/DboBuilder.d.ts +2 -0
  5. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  6. package/dist/DboBuilder/DboBuilder.js +5 -1
  7. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  8. package/dist/DboBuilder/DboBuilderTypes.d.ts +7 -0
  9. package/dist/DboBuilder/DboBuilderTypes.d.ts.map +1 -1
  10. package/dist/DboBuilder/DboBuilderTypes.js.map +1 -1
  11. package/dist/DboBuilder/QueryStreamer.d.ts.map +1 -1
  12. package/dist/DboBuilder/QueryStreamer.js +1 -1
  13. package/dist/DboBuilder/QueryStreamer.js.map +1 -1
  14. package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.d.ts +7 -0
  15. package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.d.ts.map +1 -0
  16. package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.js +18 -0
  17. package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.js.map +1 -0
  18. package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.d.ts +7 -0
  19. package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.d.ts.map +1 -0
  20. package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.js +18 -0
  21. package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.js.map +1 -0
  22. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.d.ts +22 -0
  23. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.d.ts.map +1 -0
  24. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.js +63 -0
  25. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.js.map +1 -0
  26. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.d.ts +15 -0
  27. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.d.ts.map +1 -0
  28. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.js +69 -0
  29. package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.js.map +1 -0
  30. package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -1
  31. package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
  32. package/dist/DboBuilder/dboBuilderUtils.js +5 -27
  33. package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
  34. package/dist/DboBuilder/getSubscribeRelatedTables.d.ts +2 -1
  35. package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
  36. package/dist/DboBuilder/getSubscribeRelatedTables.js +2 -101
  37. package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
  38. package/dist/DboBuilder/runSQL.d.ts +1 -1
  39. package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.d.ts.map +1 -1
  40. package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.js.map +1 -1
  41. package/dist/Prostgles.d.ts.map +1 -1
  42. package/dist/Prostgles.js +4 -2
  43. package/dist/Prostgles.js.map +1 -1
  44. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  45. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  46. package/dist/PublishParser/PublishParser.d.ts +1 -3
  47. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  48. package/dist/PublishParser/PublishParser.js +6 -3
  49. package/dist/PublishParser/PublishParser.js.map +1 -1
  50. package/dist/PublishParser/getTableRulesWithoutFileTable.d.ts.map +1 -1
  51. package/dist/PublishParser/getTableRulesWithoutFileTable.js +1 -1
  52. package/dist/PublishParser/getTableRulesWithoutFileTable.js.map +1 -1
  53. package/dist/WebsocketAPI/getClientSchema.js +1 -1
  54. package/dist/WebsocketAPI/getClientSchema.js.map +1 -1
  55. package/dist/WebsocketAPI/onSocketConnected.d.ts.map +1 -1
  56. package/dist/WebsocketAPI/onSocketConnected.js +2 -2
  57. package/dist/WebsocketAPI/onSocketConnected.js.map +1 -1
  58. package/dist/initProstgles.js +0 -3
  59. package/dist/initProstgles.js.map +1 -1
  60. package/dist/runClientRequest.d.ts +9 -9
  61. package/dist/runClientRequest.d.ts.map +1 -1
  62. package/dist/runClientRequest.js +34 -8
  63. package/dist/runClientRequest.js.map +1 -1
  64. package/dist/shortestPath.js +1 -1
  65. package/dist/shortestPath.js.map +1 -1
  66. package/lib/Auth/endpoints/setOAuthRequestHandlers.ts +5 -2
  67. package/lib/DboBuilder/DboBuilder.ts +6 -1
  68. package/lib/DboBuilder/DboBuilderTypes.ts +9 -0
  69. package/lib/DboBuilder/QueryStreamer.ts +3 -10
  70. package/lib/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.ts +24 -0
  71. package/lib/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.ts +99 -0
  72. package/lib/DboBuilder/ViewRelatedTables/getViewRelatedTables.ts +93 -0
  73. package/lib/DboBuilder/dboBuilderUtils.ts +6 -32
  74. package/lib/DboBuilder/getSubscribeRelatedTables.ts +6 -144
  75. package/lib/DboBuilder/schema/getTablesForSchemaPostgresSQL.ts +1 -0
  76. package/lib/Prostgles.ts +8 -3
  77. package/lib/PubSubManager/PubSubManager.ts +3 -10
  78. package/lib/PublishParser/PublishParser.ts +10 -9
  79. package/lib/PublishParser/getTableRulesWithoutFileTable.ts +3 -5
  80. package/lib/WebsocketAPI/getClientSchema.ts +1 -1
  81. package/lib/WebsocketAPI/onSocketConnected.ts +4 -3
  82. package/lib/initProstgles.ts +0 -4
  83. package/lib/runClientRequest.ts +57 -19
  84. package/lib/shortestPath.ts +1 -1
  85. package/package.json +2 -2
@@ -1,18 +1,12 @@
1
- import type {
2
- AnyObject,
3
- ParsedJoinPath,
4
- SubscribeParams} from "prostgles-types";
5
- import {
6
- asName,
7
- reverseParsedPath
8
- } from "prostgles-types";
1
+ import type { AnyObject, ParsedJoinPath, SubscribeParams } from "prostgles-types";
2
+ import { asName, reverseParsedPath } from "prostgles-types";
9
3
  import type { ParsedTableRule } from "../PublishParser/PublishParser";
10
4
  import type { ViewSubscriptionOptions } from "../PubSubManager/PubSubManager";
11
5
  import type { Filter, LocalParams } from "./DboBuilder";
12
- import { getSerializedClientErrorFromPGError } from "./DboBuilder";
13
6
  import type { NewQuery } from "./QueryBuilder/QueryBuilder";
7
+ import type { TableHandler } from "./TableHandler/TableHandler";
14
8
  import type { ViewHandler } from "./ViewHandler/ViewHandler";
15
- import { log } from "../PubSubManager/PubSubManagerUtils";
9
+ import { getViewRelatedTables } from "./ViewRelatedTables/getViewRelatedTables";
16
10
 
17
11
  type Args = {
18
12
  selectParams: Omit<SubscribeParams, "throttle">;
@@ -27,144 +21,12 @@ type Args = {
27
21
  * When subscribing to a table: identify joined tables to subscribe to them
28
22
  */
29
23
  export async function getSubscribeRelatedTables(
30
- this: ViewHandler,
24
+ this: ViewHandler | TableHandler,
31
25
  { filter, localParams, newQuery }: Args
32
26
  ) {
33
27
  let viewOptions: ViewSubscriptionOptions | undefined = undefined;
34
- const { condition } = newQuery.whereOpts;
35
28
  if (this.is_view) {
36
- /** TODO: this needs to be memoized on schema fetch */
37
- const viewName = this.name;
38
- const viewNameEscaped = this.escapedName;
39
- const { current_schema } = await this.db.one<{ current_schema: string }>(
40
- "SELECT current_schema"
41
- );
42
-
43
- /** Get list of used columns and their parent tables */
44
- let { def } = await this.db.one<{ def: string }>("SELECT pg_get_viewdef(${viewName}) as def", {
45
- viewName,
46
- });
47
- def = def.trim();
48
- if (def.endsWith(";")) {
49
- def = def.slice(0, -1);
50
- }
51
- if (!def || typeof def !== "string") {
52
- throw getSerializedClientErrorFromPGError("Could get view definition", {
53
- type: "tableMethod",
54
- localParams,
55
- view: this,
56
- });
57
- }
58
- const { fields } = await this.dboBuilder.dbo.sql!(
59
- `SELECT * FROM ( \n ${def} \n ) prostgles_subscribe_view_definition LIMIT 0`,
60
- {},
61
- { returnType: "default-with-rollback" }
62
- );
63
- const tableColumns = fields.filter((f) => f.tableName && f.columnName);
64
-
65
- /** Create exists filters for each table */
66
- const tableIds: string[] = Array.from(
67
- new Set(tableColumns.map((tc) => tc.tableID!.toString()))
68
- );
69
- viewOptions = {
70
- type: "view",
71
- viewName,
72
- definition: def,
73
- relatedTables: [],
74
- };
75
- viewOptions.relatedTables = await Promise.all(
76
- tableIds.map(async (tableID) => {
77
- const table = this.dboBuilder.USER_TABLES!.find((t) => t.relid === +tableID)!;
78
- let tableCols = tableColumns.filter((tc) => tc.tableID!.toString() === tableID);
79
-
80
- /** If table has primary keys and they are all in this view then use only primary keys */
81
- if (table.pkey_columns?.every((pkey) => tableCols.some((c) => c.columnName === pkey))) {
82
- tableCols = tableCols.filter((c) => table.pkey_columns?.includes(c.columnName!));
83
- } else {
84
- /** Exclude non comparable data types */
85
- tableCols = tableCols.filter((c) => !["json", "xml"].includes(c.udt_name));
86
- }
87
-
88
- const { relname: tableName, schemaname: tableSchema } = table;
89
-
90
- if (tableCols.length) {
91
- const tableNameEscaped =
92
- tableSchema === current_schema ?
93
- table.relname
94
- : [tableSchema, tableName].map((v) => JSON.stringify(v)).join(".");
95
-
96
- const fullCondition = `EXISTS (
97
- SELECT 1
98
- FROM ${viewNameEscaped}
99
- WHERE ${tableCols.map((c) => `${tableNameEscaped}.${JSON.stringify(c.columnName)} = ${viewNameEscaped}.${JSON.stringify(c.name)}`).join(" AND \n")}
100
- AND ${condition || "TRUE"}
101
- )`;
102
-
103
- try {
104
- const { count } = await this.db.one<{ count: number }>(`
105
- WITH ${asName(tableName)} AS (
106
- SELECT *
107
- FROM ${asName(tableName)}
108
- LIMIT 0
109
- )
110
-
111
- SELECT COUNT(*) as count
112
- FROM (
113
- ${def}
114
- ) prostgles_view_ref_table_test
115
- `);
116
-
117
- const relatedTableSubscription = {
118
- tableName: tableName,
119
- tableNameEscaped,
120
- condition: fullCondition,
121
- };
122
-
123
- if (count.toString() === "0") {
124
- return relatedTableSubscription;
125
- }
126
- } catch (e) {
127
- log(
128
- `Could not not override subscribed view (${this.name}) table (${tableName}). Will not check condition`,
129
- e
130
- );
131
- }
132
- }
133
-
134
- return {
135
- tableName,
136
- tableNameEscaped: JSON.stringify(tableName), // [table.schemaname, table.relname].map(v => JSON.stringify(v)).join("."),
137
- condition: "TRUE",
138
- };
139
- })
140
- );
141
-
142
- /** Get list of remaining used inner tables */
143
- const allUsedTables: { table_name: string; table_schema: string }[] = await this.db.any(
144
- "SELECT distinct table_name, table_schema FROM information_schema.view_column_usage WHERE view_name = ${viewName}",
145
- { viewName }
146
- );
147
-
148
- /** Remaining tables will have listeners on all records (condition = "TRUE") */
149
- const remainingInnerTables = allUsedTables.filter(
150
- (at) =>
151
- !tableColumns.some(
152
- (dc) => dc.tableName === at.table_name && dc.tableSchema === at.table_schema
153
- )
154
- );
155
- viewOptions.relatedTables = [
156
- ...viewOptions.relatedTables,
157
- ...remainingInnerTables.map((t) => ({
158
- tableName: t.table_name,
159
- tableNameEscaped: [t.table_name, t.table_schema].map((v) => JSON.stringify(v)).join("."),
160
- condition: "TRUE",
161
- })),
162
- ];
163
-
164
- if (!viewOptions.relatedTables.length) {
165
- throw "Could not subscribe to this view: no related tables found";
166
- }
167
-
29
+ viewOptions = await getViewRelatedTables(this, localParams, newQuery);
168
30
  /** Any joined table used within select or filter must also be added a trigger for this recordset */
169
31
  } else {
170
32
  viewOptions = {
@@ -227,6 +227,7 @@ export async function getTablesForSchemaPostgresSQL(
227
227
  table.parent_tables =
228
228
  getViewParentTables.data?.parent_tables.find((vr) => vr.oid === table.oid)?.table_names ??
229
229
  [];
230
+
230
231
  return table;
231
232
  });
232
233
  return { tablesAndViews };
package/lib/Prostgles.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  import type * as pgPromise from "pg-promise";
7
7
  import { AuthHandler } from "./Auth/AuthHandler";
8
8
  import { FileManager } from "./FileManager/FileManager";
9
- import type { OnInitReason} from "./initProstgles";
9
+ import type { OnInitReason } from "./initProstgles";
10
10
  import { initProstgles } from "./initProstgles";
11
11
  import type { SchemaWatch } from "./SchemaWatch/SchemaWatch";
12
12
  import { getClientSchema } from "./WebsocketAPI/getClientSchema";
@@ -148,7 +148,7 @@ export class Prostgles {
148
148
  console.error(`Unrecognised ProstglesInitOptions params: ${unknownParams.join()}`);
149
149
  }
150
150
 
151
- Object.assign(this.opts, params);
151
+ this.opts = { ...this.opts, ...params };
152
152
 
153
153
  /* set defaults */
154
154
  if (this.opts.fileTable) {
@@ -164,7 +164,12 @@ export class Prostgles {
164
164
  destroyed = false;
165
165
 
166
166
  checkDb() {
167
- if (!this.db || !(this.db as any).connect) throw "something went wrong getting a db connection";
167
+ if (
168
+ !this.db ||
169
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
170
+ !this.db.connect
171
+ )
172
+ throw "something went wrong getting a db connection";
168
173
  }
169
174
 
170
175
  getTSFileName() {
@@ -19,18 +19,11 @@ import { initPubSubManager } from "./init/initPubSubManager";
19
19
  import { initialiseEventTriggers } from "./initialiseEventTriggers";
20
20
  import { refreshTriggers } from "./refreshTriggers";
21
21
 
22
- import type {
23
- AnyObject,
24
- FieldFilter,
25
- SelectParams,
26
- WAL} from "prostgles-types";
27
- import {
28
- CHANNELS,
29
- type SubscribeOptions,
30
- } from "prostgles-types";
22
+ import type { AnyObject, FieldFilter, SelectParams, WAL } from "prostgles-types";
23
+ import { CHANNELS, type SubscribeOptions } from "prostgles-types";
31
24
 
32
25
  import { find, pickKeys } from "prostgles-types";
33
- import type { LocalFuncs} from "../DboBuilder/ViewHandler/subscribe";
26
+ import type { LocalFuncs } from "../DboBuilder/ViewHandler/subscribe";
34
27
  import { getOnDataFunc, matchesLocalFuncs } from "../DboBuilder/ViewHandler/subscribe";
35
28
  import type { EventTypes } from "../Logging";
36
29
  import type { ParsedTableRule } from "../PublishParser/PublishParser";
@@ -1,4 +1,4 @@
1
- import type { Method} from "prostgles-types";
1
+ import type { Method } from "prostgles-types";
2
2
  import { getObjectEntries, isObject } from "prostgles-types";
3
3
  import type { AuthClientRequest, AuthResultWithSID, SessionUser } from "../Auth/AuthTypes";
4
4
  import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
@@ -14,7 +14,8 @@ import type {
14
14
  DboTableCommand,
15
15
  ParsedTableRule,
16
16
  PublishMethods,
17
- PublishParams} from "./publishTypesAndUtils";
17
+ PublishParams,
18
+ } from "./publishTypesAndUtils";
18
19
  import {
19
20
  RULE_TO_METHODS,
20
21
  parsePublishTableRule,
@@ -72,18 +73,15 @@ export class PublishParser {
72
73
  return getV2Methods(publishMethods);
73
74
  }
74
75
 
75
- async getAllowedMethods(
76
- clientReq: AuthClientRequest,
77
- userData: AuthResultWithSID | undefined
78
- ): Promise<{ [key: string]: Method }> {
79
- const methods: { [key: string]: Method } = {};
76
+ async getAllowedMethods(clientReq: AuthClientRequest, userData: AuthResultWithSID | undefined) {
77
+ const methods: Map<string, Method> = new Map();
80
78
 
81
79
  const publishParams = await this.getPublishParams(clientReq, userData);
82
80
  const v2Methods = this.publishMethodsV2;
83
81
  if (v2Methods) {
84
82
  for (const [name, method] of Object.entries(v2Methods)) {
85
83
  if (await method.isAllowed(publishParams)) {
86
- methods[name] = method;
84
+ methods.set(name, method);
87
85
  }
88
86
  }
89
87
  return methods;
@@ -92,6 +90,9 @@ export class PublishParser {
92
90
  const _methods = await applyParamsIfFunc(this.publishMethods, publishParams);
93
91
  if (!_methods) return methods;
94
92
  getObjectEntries(_methods).map(([key, method]) => {
93
+ if (typeof key !== "string") {
94
+ throw `invalid publishMethods key -> ${String(key)} \n Expecting a string`;
95
+ }
95
96
  const isFuncLike = (maybeFunc: VoidFunction | Promise<void> | Promise<any>) =>
96
97
  typeof maybeFunc === "function" || typeof maybeFunc.then === "function";
97
98
  if (
@@ -99,7 +100,7 @@ export class PublishParser {
99
100
  // @ts-ignore
100
101
  (isObject(method) && isFuncLike(method.run))
101
102
  ) {
102
- methods[key] = _methods[key]!;
103
+ methods.set(key, method);
103
104
  } else {
104
105
  throw `invalid publishMethods item -> ${key} \n Expecting a function or promise`;
105
106
  }
@@ -9,11 +9,9 @@ import type {
9
9
  ParsedPublishTable,
10
10
  PublishTableRule,
11
11
  PublishViewRule,
12
- SubscribeRule} from "./publishTypesAndUtils";
13
- import {
14
- type PublishObject,
15
- RULE_TO_METHODS
12
+ SubscribeRule,
16
13
  } from "./publishTypesAndUtils";
14
+ import { type PublishObject, RULE_TO_METHODS } from "./publishTypesAndUtils";
17
15
 
18
16
  export async function getTableRulesWithoutFileTable(
19
17
  this: PublishParser,
@@ -21,7 +19,7 @@ export async function getTableRulesWithoutFileTable(
21
19
  clientInfo: AuthResultWithSID | undefined,
22
20
  overridenPublish?: PublishObject
23
21
  ): Promise<ParsedPublishTable | undefined> {
24
- if (!tableName) throw new Error("publish OR socket OR dbo OR tableName are missing");
22
+ if (!tableName) throw new Error("tableName is missing in getTableRules");
25
23
 
26
24
  const publish =
27
25
  overridenPublish ?? (clientReq && (await this.getPublishAsObject(clientReq, clientInfo)));
@@ -62,7 +62,7 @@ export async function getClientSchema(
62
62
  const methodSchema: ClientSchema["methods"] =
63
63
  !methods ?
64
64
  []
65
- : Object.entries(methods)
65
+ : Array.from(methods.entries())
66
66
  .map(([methodName, method]) => {
67
67
  if (isObject(method) && "run" in method) {
68
68
  return {
@@ -1,5 +1,5 @@
1
- import type { AnyObject} from "prostgles-types";
2
- import { CHANNELS } from "prostgles-types";
1
+ import type { AnyObject } from "prostgles-types";
2
+ import { CHANNELS, getSerialisableError, isObject } from "prostgles-types";
3
3
  import type { Prostgles, TABLE_METHODS } from "../Prostgles";
4
4
  import type { PRGLIOSocket } from "../DboBuilder/DboBuilderTypes";
5
5
  import { runClientMethod, runClientRequest } from "../runClientRequest";
@@ -151,7 +151,8 @@ export async function onSocketConnected(this: Prostgles, socket: PRGLIOSocket) {
151
151
  }
152
152
 
153
153
  export function makeSocketError(cb: (err: AnyObject) => void, err: any) {
154
- cb(getErrorAsObject(err));
154
+ const serializedError = getSerialisableError(err);
155
+ cb(isObject(serializedError) ? serializedError : { serializedError });
155
156
  }
156
157
 
157
158
  type SocketRequestParams = {
@@ -367,10 +367,6 @@ const getDbConnection = function ({
367
367
  pgp.pg.types.setTypeParser(pgp.pg.types.builtins.TIMESTAMPTZ, (v) => v); // timestamp with time zone
368
368
  pgp.pg.types.setTypeParser(pgp.pg.types.builtins.DATE, (v) => v); // date
369
369
 
370
- // if (dbOptions) {
371
- // Object.assign(pgp.pg.defaults, dbOptions);
372
- // }
373
-
374
370
  return {
375
371
  db: pgp(dbConnection),
376
372
  pgp,
@@ -1,8 +1,6 @@
1
- import type {
2
- SQLRequest,
3
- TableHandler,
4
- UserLike} from "prostgles-types";
1
+ import type { SQLRequest, TableHandler, UserLike } from "prostgles-types";
5
2
  import {
3
+ getJSONBObjectSchemaValidationError,
6
4
  getKeys,
7
5
  pickKeys,
8
6
  type AnyObject,
@@ -13,7 +11,7 @@ import type { TableHandler as TableHandlerServer } from "./DboBuilder/TableHandl
13
11
  import { parseFieldFilter } from "./DboBuilder/ViewHandler/parseFieldFilter";
14
12
  import { canRunSQL } from "./DboBuilder/runSQL";
15
13
  import type { Prostgles } from "./Prostgles";
16
- import type { ParsedTableRule} from "./PublishParser/publishTypesAndUtils";
14
+ import type { ParsedTableRule } from "./PublishParser/publishTypesAndUtils";
17
15
  import { type PermissionScope } from "./PublishParser/publishTypesAndUtils";
18
16
 
19
17
  const TABLE_METHODS = {
@@ -41,11 +39,11 @@ const SOCKET_ONLY_COMMANDS = [
41
39
  ] as const satisfies typeof TABLE_METHODS_KEYS;
42
40
 
43
41
  type Args = {
44
- tableName: string;
45
- command: string;
46
- param1: any;
47
- param2: any;
48
- param3: any;
42
+ tableName: unknown;
43
+ command: unknown;
44
+ param1: unknown;
45
+ param2: unknown;
46
+ param3: unknown;
49
47
  };
50
48
 
51
49
  type TableMethodFunctionWithRulesAndLocalParams = (
@@ -58,7 +56,7 @@ type TableMethodFunctionWithRulesAndLocalParams = (
58
56
 
59
57
  export const runClientRequest = async function (
60
58
  this: Prostgles,
61
- args: Args,
59
+ nonValidatedArgs: Args,
62
60
  clientReq: AuthClientRequest,
63
61
  scope: PermissionScope | undefined
64
62
  ) {
@@ -67,11 +65,22 @@ export const runClientRequest = async function (
67
65
  throw "socket/httpReq or authhandler missing";
68
66
  }
69
67
 
70
- const { tableName, command: nonValidatedCommand, param1, param2, param3 } = args;
71
- if (!TABLE_METHODS_KEYS.some((v) => v === nonValidatedCommand)) {
72
- throw `Invalid command: ${nonValidatedCommand}. Expecting one of: ${TABLE_METHODS_KEYS.join(", ")};`;
68
+ const validation = getJSONBObjectSchemaValidationError(
69
+ {
70
+ tableName: { type: "string" },
71
+ command: { enum: TABLE_METHODS_KEYS },
72
+ param1: { type: "any", optional: true },
73
+ param2: { type: "any", optional: true },
74
+ param3: { type: "any", optional: true },
75
+ },
76
+ nonValidatedArgs,
77
+ "tableName"
78
+ );
79
+ if (validation.error !== undefined) {
80
+ throw validation.error;
73
81
  }
74
- const command = nonValidatedCommand as keyof TableHandler;
82
+ const { tableName, command, param1, param2, param3 } = validation.data;
83
+
75
84
  if (!clientReq.socket && SOCKET_ONLY_COMMANDS.some((v) => v === command)) {
76
85
  throw (
77
86
  "The following commands cannot be completed over a non-websocket connection: " +
@@ -79,6 +88,10 @@ export const runClientRequest = async function (
79
88
  );
80
89
  }
81
90
 
91
+ if (!this.dboBuilder.dboMap.has(tableName)) {
92
+ throw `tableName ${tableName} is invalid or not allowed`;
93
+ }
94
+
82
95
  const clientInfo = await this.authHandler?.getSidAndUserFromRequest(clientReq);
83
96
  if (clientInfo === "new-session-redirect") {
84
97
  throw clientInfo;
@@ -159,7 +172,7 @@ export const clientCanRunSqlRequest = async function (
159
172
 
160
173
  export const runClientSqlRequest = async function (
161
174
  this: Prostgles,
162
- reqData: SQLRequest,
175
+ unvalidatedArgs: SQLRequest,
163
176
  clientReq: AuthClientRequest
164
177
  ) {
165
178
  const { allowed } = await clientCanRunSqlRequest.bind(this)(clientReq);
@@ -167,23 +180,48 @@ export const runClientSqlRequest = async function (
167
180
  throw "Not allowed to execute sql";
168
181
  }
169
182
  if (!this.dbo?.sql) throw "Internal error: sql handler missing";
183
+ const validation = getJSONBObjectSchemaValidationError(
184
+ {
185
+ query: { type: "string" },
186
+ params: { type: "any", optional: true },
187
+ options: { type: "any", optional: true },
188
+ },
189
+ unvalidatedArgs,
190
+ "query"
191
+ );
192
+ if (validation.error !== undefined) {
193
+ throw validation.error;
194
+ }
195
+ const reqData = validation.data;
170
196
  const { query, params, options } = reqData;
171
197
  return this.dbo.sql(query, params, options, { clientReq });
172
198
  };
173
199
 
174
200
  type ArgsMethod = {
175
- method: string;
201
+ method: unknown;
176
202
  params?: any[];
177
203
  };
178
204
  export const runClientMethod = async function (
179
205
  this: Prostgles,
180
- reqArgs: ArgsMethod,
206
+ unvalidatedArgs: ArgsMethod,
181
207
  clientReq: AuthClientRequest
182
208
  ) {
209
+ const validation = getJSONBObjectSchemaValidationError(
210
+ {
211
+ method: { type: "string" },
212
+ params: { type: "any[]", optional: true },
213
+ },
214
+ unvalidatedArgs,
215
+ "method"
216
+ );
217
+ if (validation.error !== undefined) {
218
+ throw validation.error;
219
+ }
220
+ const reqArgs = validation.data;
183
221
  const { method, params = [] } = reqArgs;
184
222
  const methods = await this.publishParser?.getAllowedMethods(clientReq, undefined);
185
223
 
186
- const methodDef = methods?.[method];
224
+ const methodDef = methods?.get(method);
187
225
  if (!methods || !methodDef) {
188
226
  throw "Disallowed/missing method " + JSON.stringify(method);
189
227
  }
@@ -25,7 +25,7 @@ export const findShortestPath = (
25
25
  // establish object for recording distances from the start node
26
26
  let distances: AnyObject = {};
27
27
  distances[endNode] = "Infinity";
28
- distances = Object.assign(distances, graph[startNode]);
28
+ distances = { ...distances, ...graph[startNode] };
29
29
 
30
30
  // track paths
31
31
  const parents: AnyObject = { endNode: null };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.347",
3
+ "version": "4.2.349",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,7 +57,7 @@
57
57
  "pg": "^8.15.6",
58
58
  "pg-cursor": "^2.14.6",
59
59
  "pg-promise": "^11.13.0",
60
- "prostgles-types": "^4.0.182"
60
+ "prostgles-types": "^4.0.183"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint/js": "^9.22.0",