prostgles-server 4.2.46 → 4.2.47
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/AuthHandler.d.ts.map +1 -1
- package/dist/AuthHandler.js +2 -0
- package/dist/AuthHandler.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts +1 -0
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js +9 -2
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/prepareHaving.d.ts +11 -0
- package/dist/DboBuilder/QueryBuilder/prepareHaving.d.ts.map +1 -0
- package/dist/DboBuilder/QueryBuilder/prepareHaving.js +20 -0
- package/dist/DboBuilder/QueryBuilder/prepareHaving.js.map +1 -0
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js +2 -28
- package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
- package/dist/DboBuilder/TableHandler/upsert.d.ts +6 -0
- package/dist/DboBuilder/TableHandler/upsert.d.ts.map +1 -0
- package/dist/DboBuilder/TableHandler/upsert.js +34 -0
- package/dist/DboBuilder/TableHandler/upsert.js.map +1 -0
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +11 -15
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/find.d.ts.map +1 -1
- package/dist/DboBuilder/find.js +18 -11
- package/dist/DboBuilder/find.js.map +1 -1
- package/dist/DboBuilder/getCondition.d.ts.map +1 -1
- package/dist/DboBuilder/getCondition.js +8 -4
- package/dist/DboBuilder/getCondition.js.map +1 -1
- package/dist/Filtering.d.ts +3 -3
- package/dist/Filtering.d.ts.map +1 -1
- package/dist/Filtering.js +22 -14
- package/dist/Filtering.js.map +1 -1
- package/examples/server/typescript/index.ts +0 -2
- package/lib/AuthHandler.ts +1 -0
- package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +9 -2
- package/lib/DboBuilder/QueryBuilder/prepareHaving.ts +23 -0
- package/lib/DboBuilder/TableHandler/TableHandler.ts +2 -26
- package/lib/DboBuilder/TableHandler/upsert.ts +32 -0
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +11 -15
- package/lib/DboBuilder/find.ts +20 -9
- package/lib/DboBuilder/getCondition.ts +8 -4
- package/lib/Filtering.ts +27 -13
- package/package.json +9 -9
- package/tests/client/package-lock.json +8 -8
- package/tests/client/package.json +1 -1
- package/tests/clientRestApi.spec.ts +30 -29
- package/tests/isomorphicQueries.spec.ts +22 -10
- package/tests/server/package-lock.json +17 -17
- package/examples/server/typescript/DBoGenerated.d.ts +0 -168
- package/examples/server/typescript/DBoGenerated.d.ts.map +0 -1
- package/examples/server/typescript/DBoGenerated.js +0 -5
- package/examples/server/typescript/DBoGenerated.js.map +0 -1
- package/examples/server/typescript/DBoGenerated.ts +0 -125
package/lib/DboBuilder/find.ts
CHANGED
|
@@ -13,7 +13,11 @@ export const find = async function(this: ViewHandler, filter?: Filter, selectPar
|
|
|
13
13
|
try {
|
|
14
14
|
await this._log({ command: "find", localParams, data: { filter, selectParams } });
|
|
15
15
|
filter = filter || {};
|
|
16
|
-
const allowedReturnTypes = Object.keys({
|
|
16
|
+
const allowedReturnTypes = Object.keys({
|
|
17
|
+
row: 1, statement: 1, value: 1, values: 1,
|
|
18
|
+
"statement-no-rls": 1, "statement-where": 1,
|
|
19
|
+
} satisfies Record<Required<SelectParams>["returnType"], 1>);
|
|
20
|
+
|
|
17
21
|
const { returnType } = selectParams || {};
|
|
18
22
|
if (returnType && !allowedReturnTypes.includes(returnType)) {
|
|
19
23
|
throw `returnType (${returnType}) can only be ${allowedReturnTypes.join(" OR ")}`
|
|
@@ -23,12 +27,13 @@ export const find = async function(this: ViewHandler, filter?: Filter, selectPar
|
|
|
23
27
|
|
|
24
28
|
if (testRule) return [];
|
|
25
29
|
if (selectParams) {
|
|
26
|
-
const
|
|
27
|
-
"select": 1, "orderBy": 1, "offset": 1, "limit": 1,
|
|
30
|
+
const validParamNames = Object.keys({
|
|
31
|
+
"select": 1, "orderBy": 1, "offset": 1, "limit": 1,
|
|
32
|
+
"returnType": 1, "groupBy": 1, "having": 1
|
|
28
33
|
} satisfies Record<keyof SelectParams, 1>);
|
|
29
34
|
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
35
|
+
const invalidParams = Object.keys(selectParams).filter(k => !validParamNames.includes(k as any));
|
|
36
|
+
if (invalidParams && invalidParams.length) throw "Invalid params: " + invalidParams.join(", ") + " \n Expecting: " + validParamNames.join(", ");
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
/* Validate publish */
|
|
@@ -38,9 +43,15 @@ export const find = async function(this: ViewHandler, filter?: Filter, selectPar
|
|
|
38
43
|
const fields = tableRules.select.fields;
|
|
39
44
|
const maxLimit = tableRules.select.maxLimit;
|
|
40
45
|
|
|
41
|
-
if (<any>tableRules.select !== "*" && typeof tableRules.select !== "boolean" && !isObject(tableRules.select))
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
if (<any>tableRules.select !== "*" && typeof tableRules.select !== "boolean" && !isObject(tableRules.select)) {
|
|
47
|
+
throw `\nInvalid publish.${this.name}.select\nExpecting any of: "*" | { fields: "*" } | true | false`;
|
|
48
|
+
}
|
|
49
|
+
if (!fields) {
|
|
50
|
+
throw ` invalid ${this.name}.select rule -> fields (required) setting missing.\nExpecting any of: "*" | { col_name: false } | { col1: true, col2: true }`;
|
|
51
|
+
}
|
|
52
|
+
if (maxLimit && !Number.isInteger(maxLimit)) {
|
|
53
|
+
throw ` invalid publish.${this.name}.select.maxLimit -> expecting integer but got ` + maxLimit;
|
|
54
|
+
}
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
const _selectParams = selectParams ?? {}
|
|
@@ -68,7 +79,7 @@ export const find = async function(this: ViewHandler, filter?: Filter, selectPar
|
|
|
68
79
|
return [];
|
|
69
80
|
} catch (e) {
|
|
70
81
|
console.error(e);
|
|
71
|
-
throw `
|
|
82
|
+
throw `Internal error: publish config is not valid for publish.${this.name}.select `
|
|
72
83
|
}
|
|
73
84
|
}
|
|
74
85
|
|
|
@@ -57,7 +57,7 @@ export async function getCondition(
|
|
|
57
57
|
existsCond = (await Promise.all(existsConfigs.map(async existsConfig => await getExistsCondition.bind(this)(existsConfig, localParams)))).join(" AND ");
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
/* Computed field queries */
|
|
60
|
+
/* Computed field queries ($rowhash) */
|
|
61
61
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
62
62
|
const computedFields = p.allColumns.filter(c => c.type === "computed");
|
|
63
63
|
const computedColConditions: string[] = [];
|
|
@@ -85,8 +85,8 @@ export async function getCondition(
|
|
|
85
85
|
if (select) {
|
|
86
86
|
/* Allow filtering by selected fields/funcs */
|
|
87
87
|
allowedSelect = select.filter(s => {
|
|
88
|
-
/* */
|
|
89
88
|
if (["function", "computed", "column"].includes(s.type)) {
|
|
89
|
+
/* */
|
|
90
90
|
if (s.type !== "column" || allowed_colnames.includes(s.alias)) {
|
|
91
91
|
return true;
|
|
92
92
|
}
|
|
@@ -202,6 +202,10 @@ export async function getCondition(
|
|
|
202
202
|
));
|
|
203
203
|
|
|
204
204
|
if (invalidColumn) {
|
|
205
|
+
const selItem = select?.find(s => s.alias === invalidColumn);
|
|
206
|
+
if(selItem?.type === "aggregation"){
|
|
207
|
+
throw new Error(`Filtering by ${invalidColumn} is not allowed. Aggregations cannot be filtered. Use HAVING clause instead.`);
|
|
208
|
+
}
|
|
205
209
|
const allowedCols = allowedSelect.map(s => s.type === "column" ? s.getQuery() : s.alias).join(", ");
|
|
206
210
|
const errMessage = `Table: ${this.name} -> disallowed/inexistent columns in filter: ${invalidColumn} \n Expecting one of: ${allowedCols}`;
|
|
207
211
|
throw errMessage;
|
|
@@ -214,8 +218,8 @@ export async function getCondition(
|
|
|
214
218
|
const q = parseFilterItem({
|
|
215
219
|
filter: f,
|
|
216
220
|
tableAlias,
|
|
217
|
-
|
|
218
|
-
|
|
221
|
+
select: allowedSelect,
|
|
222
|
+
allowedColumnNames: !tableRules? this.column_names.slice(0) : this.parseFieldFilter(tableRules.select?.filterFields ?? tableRules.select?.fields),
|
|
219
223
|
});
|
|
220
224
|
|
|
221
225
|
let templates: string[] = [q].filter(q => q);
|
package/lib/Filtering.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
CompareFilterKeys,
|
|
5
5
|
CompareInFilterKeys,
|
|
6
|
-
|
|
6
|
+
FilterDataType,
|
|
7
7
|
FullFilter,
|
|
8
8
|
GeomFilterKeys, GeomFilter_Funcs,
|
|
9
9
|
JsonbFilterKeys,
|
|
@@ -14,14 +14,21 @@ import {
|
|
|
14
14
|
isObject
|
|
15
15
|
} from "prostgles-types";
|
|
16
16
|
import { SelectItem } from "./DboBuilder/QueryBuilder/QueryBuilder";
|
|
17
|
+
import { pgp } from "./DboBuilder/DboBuilderTypes";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Parse a single filter
|
|
20
21
|
* Ensure only single key objects reach this point
|
|
21
22
|
*/
|
|
22
|
-
type ParseFilterItemArgs = {
|
|
23
|
+
type ParseFilterItemArgs = {
|
|
24
|
+
filter: FullFilter<void, void>;
|
|
25
|
+
select: SelectItem[] | undefined;
|
|
26
|
+
tableAlias: string | undefined;
|
|
27
|
+
allowedColumnNames: string[];
|
|
28
|
+
};
|
|
29
|
+
|
|
23
30
|
export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
24
|
-
const { filter: _f, select, tableAlias,
|
|
31
|
+
const { filter: _f, select, tableAlias, allowedColumnNames } = args;
|
|
25
32
|
|
|
26
33
|
if(!_f || isEmpty(_f)) return "";
|
|
27
34
|
|
|
@@ -42,7 +49,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
42
49
|
filter: { [fk]: _f[fk] },
|
|
43
50
|
select,
|
|
44
51
|
tableAlias,
|
|
45
|
-
|
|
52
|
+
allowedColumnNames,
|
|
46
53
|
}))
|
|
47
54
|
.sort() /* sorted to ensure duplicate subscription channels are not created due to different condition order */
|
|
48
55
|
.join(" AND ")
|
|
@@ -50,17 +57,24 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
50
57
|
|
|
51
58
|
const fKey: string = fKeys[0]!;
|
|
52
59
|
|
|
53
|
-
/* Exists filter */
|
|
54
|
-
if(EXISTS_KEYS.find(k => k in _f)){
|
|
55
|
-
// parseExistsFilter()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
60
|
let selItem: SelectItem | undefined;
|
|
59
|
-
if(select)
|
|
61
|
+
if(select) {
|
|
62
|
+
selItem = select.find(s => fKey === s.alias);
|
|
63
|
+
}
|
|
60
64
|
let rightF: FilterDataType<any> = (_f as any)[fKey];
|
|
61
65
|
|
|
66
|
+
const validateSelectedItemFilter = (selectedItem: SelectItem | undefined) => {
|
|
67
|
+
const fields = selectedItem?.getFields();
|
|
68
|
+
if(Array.isArray(fields) && fields.length > 1) {
|
|
69
|
+
const dissallowedFields = fields.filter(fname => !allowedColumnNames.includes(fname));
|
|
70
|
+
if(dissallowedFields.length){
|
|
71
|
+
throw new Error(`Invalid/disallowed columns found in filter: ${dissallowedFields}`)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
62
75
|
const getLeftQ = (selItm: SelectItem) => {
|
|
63
|
-
|
|
76
|
+
validateSelectedItemFilter(selItem);
|
|
77
|
+
if(selItm.type === "function" || selItm.type === "aggregation") return selItm.getQuery();
|
|
64
78
|
return selItm.getQuery(tableAlias);
|
|
65
79
|
}
|
|
66
80
|
|
|
@@ -81,6 +95,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
81
95
|
selItem = select.find(s =>
|
|
82
96
|
dot_notation_delims.find(delimiter => fKey.startsWith(s.alias + delimiter))
|
|
83
97
|
);
|
|
98
|
+
validateSelectedItemFilter(selItem);
|
|
84
99
|
}
|
|
85
100
|
if(!selItem) {
|
|
86
101
|
return mErr("Bad filter. Could not match to a column or alias or dot notation: ");
|
|
@@ -135,7 +150,6 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
135
150
|
nextSep = undefined;
|
|
136
151
|
}
|
|
137
152
|
|
|
138
|
-
// console.log({ currSep, nextSep })
|
|
139
153
|
leftQ += currSep.sep + asValue(remainingStr.slice(currSep.idx + currSep.sep.length, nextIdx));
|
|
140
154
|
currSep = nextSep;
|
|
141
155
|
}
|
|
@@ -175,7 +189,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
175
189
|
|
|
176
190
|
rightF = res;
|
|
177
191
|
} else {
|
|
178
|
-
console.trace(141, select, selItem, remainingStr)
|
|
192
|
+
// console.trace(141, select, selItem, remainingStr)
|
|
179
193
|
mErr("Bad filter. Could not find the valid col name or alias or col json path")
|
|
180
194
|
}
|
|
181
195
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prostgles-server",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.47",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,23 +35,23 @@
|
|
|
35
35
|
],
|
|
36
36
|
"homepage": "https://prostgles.com",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@types/express": "^4.17.13",
|
|
39
|
-
"@types/json-schema": "^7.0.11",
|
|
40
|
-
"@types/pg": "^8.10.9",
|
|
41
38
|
"bluebird": "^3.7.2",
|
|
42
39
|
"body-parser": "^1.20.2",
|
|
43
|
-
"check-disk-space": "^3.
|
|
40
|
+
"check-disk-space": "^3.4.0",
|
|
44
41
|
"file-type": "^18.5.0",
|
|
45
|
-
"pg": "^8.11.
|
|
46
|
-
"pg-cursor": "^2.10.
|
|
47
|
-
"pg-promise": "^11.
|
|
42
|
+
"pg": "^8.11.5",
|
|
43
|
+
"pg-cursor": "^2.10.5",
|
|
44
|
+
"pg-promise": "^11.6.0",
|
|
48
45
|
"prostgles-client": "^4.0.53",
|
|
49
|
-
"prostgles-types": "^4.0.
|
|
46
|
+
"prostgles-types": "^4.0.75"
|
|
50
47
|
},
|
|
51
48
|
"devDependencies": {
|
|
52
49
|
"@types/bluebird": "^3.5.36",
|
|
50
|
+
"@types/express": "^4.17.21",
|
|
53
51
|
"@types/file-type": "^10.9.1",
|
|
52
|
+
"@types/json-schema": "^7.0.15",
|
|
54
53
|
"@types/node": "^18.0.3",
|
|
54
|
+
"@types/pg": "^8.11.5",
|
|
55
55
|
"@types/pg-cursor": "^2.7.2",
|
|
56
56
|
"@types/sharp": "^0.30.4",
|
|
57
57
|
"@types/socket.io": "^3.0.2",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/node": "^20.9.2",
|
|
13
|
-
"prostgles-client": "^4.0.
|
|
13
|
+
"prostgles-client": "^4.0.117",
|
|
14
14
|
"prostgles-types": "^4.0.51",
|
|
15
15
|
"socket.io-client": "^4.7.5"
|
|
16
16
|
},
|
|
@@ -351,11 +351,11 @@
|
|
|
351
351
|
}
|
|
352
352
|
},
|
|
353
353
|
"node_modules/prostgles-client": {
|
|
354
|
-
"version": "4.0.
|
|
355
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.
|
|
356
|
-
"integrity": "sha512-
|
|
354
|
+
"version": "4.0.117",
|
|
355
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.117.tgz",
|
|
356
|
+
"integrity": "sha512-bhA/o84sWPrlqiYFpitNRqcn1bDgNN5yOuPGSaS805t4Gm6vooKI1K392qlrskK92j6qH7VnPsKxeF4Ul7vn/g==",
|
|
357
357
|
"dependencies": {
|
|
358
|
-
"prostgles-types": "^4.0.
|
|
358
|
+
"prostgles-types": "^4.0.75"
|
|
359
359
|
},
|
|
360
360
|
"peerDependencies": {
|
|
361
361
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
@@ -371,9 +371,9 @@
|
|
|
371
371
|
}
|
|
372
372
|
},
|
|
373
373
|
"node_modules/prostgles-types": {
|
|
374
|
-
"version": "4.0.
|
|
375
|
-
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.
|
|
376
|
-
"integrity": "sha512-
|
|
374
|
+
"version": "4.0.75",
|
|
375
|
+
"resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-4.0.75.tgz",
|
|
376
|
+
"integrity": "sha512-s0v0NbLO2/w9kzsjxlC48ZyMtnUJ/5dhuH5eucAnGv41wwuJ+HjA2zsvVqBiStdEVA6AhwrWefmrO8GTkuiKhA==",
|
|
377
377
|
"dependencies": {
|
|
378
378
|
"json-schema": "^0.4.0"
|
|
379
379
|
}
|
|
@@ -7,36 +7,11 @@ export const clientRestApi = async(db: DBHandlerClient, auth: Auth, log: (...arg
|
|
|
7
7
|
|
|
8
8
|
await describe("clientRestApi", async () => {
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const headers = new Headers({
|
|
12
|
-
'Authorization': `Bearer ${Buffer.from(noAuth? "noAuth" : token, "utf-8").toString("base64")}`,
|
|
13
|
-
'Accept': 'application/json',
|
|
14
|
-
'Content-Type': 'application/json'
|
|
15
|
-
});
|
|
16
|
-
const res = await fetch(`http://127.0.0.1:3001/api/${path}`, {
|
|
17
|
-
method: "POST",
|
|
18
|
-
headers,
|
|
19
|
-
body: !params?.length? undefined : JSON.stringify(params)
|
|
20
|
-
});
|
|
21
|
-
const resBodyJson = await res.text()
|
|
22
|
-
.then(text => {
|
|
23
|
-
try {
|
|
24
|
-
return JSON.parse(text);
|
|
25
|
-
} catch {
|
|
26
|
-
return text;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
if(res.status !== 200){
|
|
31
|
-
return Promise.reject(resBodyJson);
|
|
32
|
-
}
|
|
33
|
-
return resBodyJson;
|
|
34
|
-
}
|
|
35
|
-
const rest = async ({ tableName, command, noAuth }: { tableName: string; command: string; noAuth?: boolean; }, ...params: any[]) => post({ path: `db/${tableName}/${command}`, noAuth }, ...(params ?? []))
|
|
10
|
+
const rest = async ({ tableName, command, noAuth }: { tableName: string; command: string; noAuth?: boolean; }, ...params: any[]) => post({ path: `db/${tableName}/${command}`, noAuth, token }, ...(params ?? []))
|
|
36
11
|
const dbRest = (tableName: string, command: string, ...params: any[]) => rest({ tableName, command }, ...(params ?? []))
|
|
37
12
|
const dbRestNoAuth = (tableName: string, command: string, ...params: any[]) => rest({ tableName, command, noAuth: true }, ...(params ?? []));
|
|
38
|
-
const sqlRest = (query: string, ...params: any[]) => post({ path: `db/sql
|
|
39
|
-
const sqlMethods = (methodName: string, ...params: any[]) => post({ path: `methods/${methodName}
|
|
13
|
+
const sqlRest = (query: string, ...params: any[]) => post({ path: `db/sql`, token }, query, ...(params ?? []))
|
|
14
|
+
const sqlMethods = (methodName: string, ...params: any[]) => post({ path: `methods/${methodName}`, token }, ...(params ?? []))
|
|
40
15
|
|
|
41
16
|
await test("Rest api test", async () => {
|
|
42
17
|
const dataFilter = { id: 123123123, last_updated: Date.now() };
|
|
@@ -59,7 +34,7 @@ export const clientRestApi = async(db: DBHandlerClient, auth: Auth, log: (...arg
|
|
|
59
34
|
const sqlRes = await sqlRest("select 1 as a", {}, { returnType: "rows" });
|
|
60
35
|
assert.deepStrictEqual(sqlRes, [{ a: 1 }]);
|
|
61
36
|
|
|
62
|
-
const restTableSchema = await post({ path: "schema" });
|
|
37
|
+
const restTableSchema = await post({ path: "schema", token });
|
|
63
38
|
assert.deepStrictEqual(tableSchema, restTableSchema.tableSchema);
|
|
64
39
|
await Promise.all(tableSchema.map(async tbl => {
|
|
65
40
|
const cols = await db[tbl.name]?.getColumns?.();
|
|
@@ -78,4 +53,30 @@ export const clientRestApi = async(db: DBHandlerClient, auth: Auth, log: (...arg
|
|
|
78
53
|
|
|
79
54
|
|
|
80
55
|
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const post = async ({ path, noAuth, token }: { path: string; token: string; noAuth?: boolean}, ...params: any[]) => {
|
|
59
|
+
const headers = new Headers({
|
|
60
|
+
'Authorization': `Bearer ${Buffer.from(noAuth? "noAuth" : token, "utf-8").toString("base64")}`,
|
|
61
|
+
'Accept': 'application/json',
|
|
62
|
+
'Content-Type': 'application/json'
|
|
63
|
+
});
|
|
64
|
+
const res = await fetch(`http://127.0.0.1:3001/api/${path}`, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers,
|
|
67
|
+
body: !params?.length? undefined : JSON.stringify(params)
|
|
68
|
+
});
|
|
69
|
+
const resBodyJson = await res.text()
|
|
70
|
+
.then(text => {
|
|
71
|
+
try {
|
|
72
|
+
return JSON.parse(text);
|
|
73
|
+
} catch {
|
|
74
|
+
return text;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if(res.status !== 200){
|
|
79
|
+
return Promise.reject(resBodyJson);
|
|
80
|
+
}
|
|
81
|
+
return resBodyJson;
|
|
81
82
|
}
|
|
@@ -2,7 +2,11 @@ import { strict as assert } from 'assert';
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import { DBOFullyTyped } from "../dist/DBSchemaBuilder";
|
|
4
4
|
import type { DBHandlerClient } from "./client";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
test,
|
|
7
|
+
//@ts-ignore
|
|
8
|
+
describe
|
|
9
|
+
} from "node:test";
|
|
6
10
|
import { pickKeys } from "prostgles-types";
|
|
7
11
|
|
|
8
12
|
|
|
@@ -78,12 +82,20 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
78
82
|
|
|
79
83
|
await db.sql("TRUNCATE files CASCADE");
|
|
80
84
|
});
|
|
85
|
+
|
|
86
|
+
await test("Having clause", async () => {
|
|
87
|
+
const res = await db.items.find!({}, { select: { name: 1, c: { $countAll: [] } }, having: { c: 2 } });
|
|
88
|
+
assert.deepStrictEqual(res, [{
|
|
89
|
+
c: '2',
|
|
90
|
+
name: 'a'
|
|
91
|
+
}]);
|
|
92
|
+
})
|
|
81
93
|
|
|
82
94
|
const json = { a: true, arr: "2", arr1: 3, arr2: [1], arrStr: ["1123.string"] }
|
|
83
95
|
await test("merge json", async () => {
|
|
84
96
|
const inserted = await db.tjson.insert!({ colOneOf: "a", json }, { returning: "*" });
|
|
85
97
|
const res = await db.tjson.update!({ colOneOf: "a" },{ json: { $merge: [{ a: false }] } }, { returning: "*" });
|
|
86
|
-
assert.deepStrictEqual(res[0].json, { ...json, a: false });
|
|
98
|
+
assert.deepStrictEqual(res?.[0].json, { ...json, a: false });
|
|
87
99
|
});
|
|
88
100
|
|
|
89
101
|
await test("json array converted to pg array filter bug", async () => {
|
|
@@ -172,7 +184,7 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
172
184
|
|
|
173
185
|
const newF = await db.files.findOne!({ id: original.id });
|
|
174
186
|
|
|
175
|
-
assert.equal(newF
|
|
187
|
+
assert.equal(newF?.original_name, newFile.name)
|
|
176
188
|
});
|
|
177
189
|
|
|
178
190
|
await test("getColumns definition", async () => {
|
|
@@ -528,8 +540,8 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
528
540
|
await test("template_string function", async () => {
|
|
529
541
|
const res = await db.various.findOne!({ name: 'abc9' }, { select: { tstr: { $template_string: ["{name} is hehe"] } } });
|
|
530
542
|
const res2 = await db.various.findOne!({ name: 'abc9' }, { select: { tstr: { $template_string: ["is hehe"] } } });
|
|
531
|
-
assert.equal(res
|
|
532
|
-
assert.equal(res2
|
|
543
|
+
assert.equal(res?.tstr, "abc9 is hehe")
|
|
544
|
+
assert.equal(res2?.tstr, "is hehe")
|
|
533
545
|
});
|
|
534
546
|
|
|
535
547
|
await test("Between filtering", async () => {
|
|
@@ -577,8 +589,8 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
577
589
|
await test("Function example", async () => {
|
|
578
590
|
|
|
579
591
|
const f = await db.items4.findOne!({}, { select: { public: 1, p_5: { $left: ["public", 3] } } });
|
|
580
|
-
assert.equal(f
|
|
581
|
-
assert.equal(f
|
|
592
|
+
assert.equal(f?.p_5.length, 3);
|
|
593
|
+
assert.equal(f?.p_5, f.public.substr(0, 3));
|
|
582
594
|
|
|
583
595
|
// Nested function
|
|
584
596
|
const fg = await db.items2.findOne!({}, { select: { id: 1, name: 1, items3: { name: "$upper" } } });// { $upper: ["public"] } } });
|
|
@@ -816,7 +828,7 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
816
828
|
select: {
|
|
817
829
|
"*": 1,
|
|
818
830
|
items2: "*",
|
|
819
|
-
items2j: db.leftJoin
|
|
831
|
+
items2j: db.leftJoin?.items2({}, "*")
|
|
820
832
|
}
|
|
821
833
|
});
|
|
822
834
|
|
|
@@ -848,7 +860,7 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
848
860
|
/* $rowhash -> Custom column that returms md5(ctid + allowed select columns). Used in joins & CRUD to bypass PKey details */
|
|
849
861
|
await test("$rowhash example", async () => {
|
|
850
862
|
const rowhash = await db.items.findOne!({}, { select: { $rowhash: 1, "*": 1 }});
|
|
851
|
-
const f = { $rowhash: rowhash
|
|
863
|
+
const f = { $rowhash: rowhash?.$rowhash };
|
|
852
864
|
const rowhashView = await db.v_items.findOne!({}, { select: { $rowhash: 1 }});
|
|
853
865
|
const rh1 = await db.items.findOne!({ $rowhash: rowhash?.$rowhash }, { select: { $rowhash: 1 }});
|
|
854
866
|
const rhView = await db.v_items.findOne!({ $rowhash: rowhashView?.$rowhash }, { select: { $rowhash: 1 }});
|
|
@@ -1076,7 +1088,7 @@ export const isomorphicQueries = async (db: DBOFullyTyped | DBHandlerClient, log
|
|
|
1076
1088
|
{
|
|
1077
1089
|
select: {
|
|
1078
1090
|
"*": 1,
|
|
1079
|
-
i0: db.innerJoin
|
|
1091
|
+
i0: db.innerJoin?.items_multi(
|
|
1080
1092
|
{ name: "multi0" },
|
|
1081
1093
|
"*",
|
|
1082
1094
|
{ path: [{ table: "items", on: [{ items0_id: "id" }] }] }
|
|
@@ -21,26 +21,26 @@
|
|
|
21
21
|
},
|
|
22
22
|
"../..": {
|
|
23
23
|
"name": "prostgles-server",
|
|
24
|
-
"version": "4.2.
|
|
24
|
+
"version": "4.2.46",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@types/express": "^4.17.13",
|
|
28
|
-
"@types/json-schema": "^7.0.11",
|
|
29
|
-
"@types/pg": "^8.10.9",
|
|
30
27
|
"bluebird": "^3.7.2",
|
|
31
28
|
"body-parser": "^1.20.2",
|
|
32
|
-
"check-disk-space": "^3.
|
|
29
|
+
"check-disk-space": "^3.4.0",
|
|
33
30
|
"file-type": "^18.5.0",
|
|
34
|
-
"pg": "^8.11.
|
|
35
|
-
"pg-cursor": "^2.10.
|
|
36
|
-
"pg-promise": "^11.
|
|
31
|
+
"pg": "^8.11.5",
|
|
32
|
+
"pg-cursor": "^2.10.5",
|
|
33
|
+
"pg-promise": "^11.6.0",
|
|
37
34
|
"prostgles-client": "^4.0.53",
|
|
38
|
-
"prostgles-types": "^4.0.
|
|
35
|
+
"prostgles-types": "^4.0.75"
|
|
39
36
|
},
|
|
40
37
|
"devDependencies": {
|
|
41
38
|
"@types/bluebird": "^3.5.36",
|
|
39
|
+
"@types/express": "^4.17.21",
|
|
42
40
|
"@types/file-type": "^10.9.1",
|
|
41
|
+
"@types/json-schema": "^7.0.15",
|
|
43
42
|
"@types/node": "^18.0.3",
|
|
43
|
+
"@types/pg": "^8.11.5",
|
|
44
44
|
"@types/pg-cursor": "^2.7.2",
|
|
45
45
|
"@types/sharp": "^0.30.4",
|
|
46
46
|
"@types/socket.io": "^3.0.2",
|
|
@@ -1529,11 +1529,11 @@
|
|
|
1529
1529
|
"version": "file:../..",
|
|
1530
1530
|
"requires": {
|
|
1531
1531
|
"@types/bluebird": "^3.5.36",
|
|
1532
|
-
"@types/express": "^4.17.
|
|
1532
|
+
"@types/express": "^4.17.21",
|
|
1533
1533
|
"@types/file-type": "^10.9.1",
|
|
1534
|
-
"@types/json-schema": "^7.0.
|
|
1534
|
+
"@types/json-schema": "^7.0.15",
|
|
1535
1535
|
"@types/node": "^18.0.3",
|
|
1536
|
-
"@types/pg": "^8.
|
|
1536
|
+
"@types/pg": "^8.11.5",
|
|
1537
1537
|
"@types/pg-cursor": "^2.7.2",
|
|
1538
1538
|
"@types/sharp": "^0.30.4",
|
|
1539
1539
|
"@types/socket.io": "^3.0.2",
|
|
@@ -1541,14 +1541,14 @@
|
|
|
1541
1541
|
"@typescript-eslint/parser": "^5.62.0",
|
|
1542
1542
|
"bluebird": "^3.7.2",
|
|
1543
1543
|
"body-parser": "^1.20.2",
|
|
1544
|
-
"check-disk-space": "^3.
|
|
1544
|
+
"check-disk-space": "^3.4.0",
|
|
1545
1545
|
"eslint": "^8.51.0",
|
|
1546
1546
|
"file-type": "^18.5.0",
|
|
1547
|
-
"pg": "^8.11.
|
|
1548
|
-
"pg-cursor": "^2.10.
|
|
1549
|
-
"pg-promise": "^11.
|
|
1547
|
+
"pg": "^8.11.5",
|
|
1548
|
+
"pg-cursor": "^2.10.5",
|
|
1549
|
+
"pg-promise": "^11.6.0",
|
|
1550
1550
|
"prostgles-client": "^4.0.53",
|
|
1551
|
-
"prostgles-types": "^4.0.
|
|
1551
|
+
"prostgles-types": "^4.0.75",
|
|
1552
1552
|
"typescript": "^5.3.3"
|
|
1553
1553
|
}
|
|
1554
1554
|
},
|