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.
- package/dist/Auth/endpoints/setOAuthRequestHandlers.d.ts.map +1 -1
- package/dist/Auth/endpoints/setOAuthRequestHandlers.js +3 -1
- package/dist/Auth/endpoints/setOAuthRequestHandlers.js.map +1 -1
- package/dist/DboBuilder/DboBuilder.d.ts +2 -0
- package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/DboBuilder.js +5 -1
- package/dist/DboBuilder/DboBuilder.js.map +1 -1
- package/dist/DboBuilder/DboBuilderTypes.d.ts +7 -0
- package/dist/DboBuilder/DboBuilderTypes.d.ts.map +1 -1
- package/dist/DboBuilder/DboBuilderTypes.js.map +1 -1
- package/dist/DboBuilder/QueryStreamer.d.ts.map +1 -1
- package/dist/DboBuilder/QueryStreamer.js +1 -1
- package/dist/DboBuilder/QueryStreamer.js.map +1 -1
- package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.d.ts +7 -0
- package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.d.ts.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.js +18 -0
- package/dist/DboBuilder/ViewRelatedTables/fetchAllViewRelatedTables.js.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.d.ts +7 -0
- package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.d.ts.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.js +18 -0
- package/dist/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.js.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.d.ts +22 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.d.ts.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.js +63 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.js.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.d.ts +15 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.d.ts.map +1 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.js +69 -0
- package/dist/DboBuilder/ViewRelatedTables/getViewRelatedTables.js.map +1 -0
- package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -1
- package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
- package/dist/DboBuilder/dboBuilderUtils.js +5 -27
- package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.d.ts +2 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.js +2 -101
- package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
- package/dist/DboBuilder/runSQL.d.ts +1 -1
- package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.d.ts.map +1 -1
- package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +4 -2
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PublishParser/PublishParser.d.ts +1 -3
- package/dist/PublishParser/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser/PublishParser.js +6 -3
- package/dist/PublishParser/PublishParser.js.map +1 -1
- package/dist/PublishParser/getTableRulesWithoutFileTable.d.ts.map +1 -1
- package/dist/PublishParser/getTableRulesWithoutFileTable.js +1 -1
- package/dist/PublishParser/getTableRulesWithoutFileTable.js.map +1 -1
- package/dist/WebsocketAPI/getClientSchema.js +1 -1
- package/dist/WebsocketAPI/getClientSchema.js.map +1 -1
- package/dist/WebsocketAPI/onSocketConnected.d.ts.map +1 -1
- package/dist/WebsocketAPI/onSocketConnected.js +2 -2
- package/dist/WebsocketAPI/onSocketConnected.js.map +1 -1
- package/dist/initProstgles.js +0 -3
- package/dist/initProstgles.js.map +1 -1
- package/dist/runClientRequest.d.ts +9 -9
- package/dist/runClientRequest.d.ts.map +1 -1
- package/dist/runClientRequest.js +34 -8
- package/dist/runClientRequest.js.map +1 -1
- package/dist/shortestPath.js +1 -1
- package/dist/shortestPath.js.map +1 -1
- package/lib/Auth/endpoints/setOAuthRequestHandlers.ts +5 -2
- package/lib/DboBuilder/DboBuilder.ts +6 -1
- package/lib/DboBuilder/DboBuilderTypes.ts +9 -0
- package/lib/DboBuilder/QueryStreamer.ts +3 -10
- package/lib/DboBuilder/ViewRelatedTables/getAllViewRelatedTables.ts +24 -0
- package/lib/DboBuilder/ViewRelatedTables/getViewRelatedTableJoinCondition.ts +99 -0
- package/lib/DboBuilder/ViewRelatedTables/getViewRelatedTables.ts +93 -0
- package/lib/DboBuilder/dboBuilderUtils.ts +6 -32
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +6 -144
- package/lib/DboBuilder/schema/getTablesForSchemaPostgresSQL.ts +1 -0
- package/lib/Prostgles.ts +8 -3
- package/lib/PubSubManager/PubSubManager.ts +3 -10
- package/lib/PublishParser/PublishParser.ts +10 -9
- package/lib/PublishParser/getTableRulesWithoutFileTable.ts +3 -5
- package/lib/WebsocketAPI/getClientSchema.ts +1 -1
- package/lib/WebsocketAPI/onSocketConnected.ts +4 -3
- package/lib/initProstgles.ts +0 -4
- package/lib/runClientRequest.ts +57 -19
- package/lib/shortestPath.ts +1 -1
- package/package.json +2 -2
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
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 {
|
|
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
|
-
|
|
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 = {
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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("
|
|
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
|
-
:
|
|
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
|
-
|
|
154
|
+
const serializedError = getSerialisableError(err);
|
|
155
|
+
cb(isObject(serializedError) ? serializedError : { serializedError });
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
type SocketRequestParams = {
|
package/lib/initProstgles.ts
CHANGED
|
@@ -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,
|
package/lib/runClientRequest.ts
CHANGED
|
@@ -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:
|
|
45
|
-
command:
|
|
46
|
-
param1:
|
|
47
|
-
param2:
|
|
48
|
-
param3:
|
|
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
|
-
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
201
|
+
method: unknown;
|
|
176
202
|
params?: any[];
|
|
177
203
|
};
|
|
178
204
|
export const runClientMethod = async function (
|
|
179
205
|
this: Prostgles,
|
|
180
|
-
|
|
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?.
|
|
224
|
+
const methodDef = methods?.get(method);
|
|
187
225
|
if (!methods || !methodDef) {
|
|
188
226
|
throw "Disallowed/missing method " + JSON.stringify(method);
|
|
189
227
|
}
|
package/lib/shortestPath.ts
CHANGED
|
@@ -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 =
|
|
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.
|
|
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.
|
|
60
|
+
"prostgles-types": "^4.0.183"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@eslint/js": "^9.22.0",
|