prostgles-server 3.0.87 → 3.0.89
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/.eslintignore +5 -0
- package/.eslintrc.json +30 -0
- package/dist/DBEventsManager.js +1 -1
- package/dist/DBEventsManager.js.map +1 -1
- package/dist/DBSchemaBuilder.d.ts.map +1 -1
- package/dist/DBSchemaBuilder.js +6 -6
- package/dist/DBSchemaBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/Functions.js +9 -9
- package/dist/DboBuilder/QueryBuilder/Functions.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js.map +1 -1
- package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler.js +18 -20
- package/dist/DboBuilder/TableHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler.d.ts +0 -10
- package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler.js +50 -63
- package/dist/DboBuilder/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/delete.js +0 -1
- package/dist/DboBuilder/delete.js.map +1 -1
- package/dist/DboBuilder/getColumns.js +5 -4
- package/dist/DboBuilder/getColumns.js.map +1 -1
- package/dist/DboBuilder/getCondition.d.ts.map +1 -1
- package/dist/DboBuilder/getCondition.js +6 -6
- package/dist/DboBuilder/getCondition.js.map +1 -1
- package/dist/DboBuilder/insert.js +15 -16
- package/dist/DboBuilder/insert.js.map +1 -1
- package/dist/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/dist/DboBuilder/insertDataParse.js +9 -10
- package/dist/DboBuilder/insertDataParse.js.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.js +2 -2
- package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
- package/dist/DboBuilder/runSQL.d.ts.map +1 -1
- package/dist/DboBuilder/runSQL.js +5 -5
- package/dist/DboBuilder/runSQL.js.map +1 -1
- package/dist/DboBuilder/subscribe.js +3 -3
- package/dist/DboBuilder/subscribe.js.map +1 -1
- package/dist/DboBuilder/update.js +5 -6
- package/dist/DboBuilder/update.js.map +1 -1
- package/dist/DboBuilder/uploadFile.d.ts.map +1 -1
- package/dist/DboBuilder/uploadFile.js +1 -1
- package/dist/DboBuilder/uploadFile.js.map +1 -1
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +13 -14
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +3 -5
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.js +7 -7
- package/dist/Filtering.js.map +1 -1
- package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js +295 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js.map +1 -0
- package/dist/JSONBValidation/validation.d.ts +108 -0
- package/dist/JSONBValidation/validation.d.ts.map +1 -0
- package/dist/JSONBValidation/validation.js +222 -0
- package/dist/JSONBValidation/validation.js.map +1 -0
- package/dist/PostgresNotifListenManager.js +1 -1
- package/dist/PostgresNotifListenManager.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +20 -20
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +10 -7
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/dist/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser.js +122 -125
- package/dist/PublishParser.js.map +1 -1
- package/dist/SyncReplication.d.ts.map +1 -1
- package/dist/SyncReplication.js +19 -16
- package/dist/SyncReplication.js.map +1 -1
- package/dist/TableConfig.d.ts +9 -5
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +33 -12
- package/dist/TableConfig.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shortestPath.js +11 -11
- package/dist/shortestPath.js.map +1 -1
- package/dist/validation.d.ts +50 -24
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +177 -53
- package/dist/validation.js.map +1 -1
- package/lib/AuthHandler.d.ts +11 -11
- package/lib/AuthHandler.d.ts.map +1 -1
- package/lib/DBEventsManager.js +1 -1
- package/lib/DBEventsManager.ts +1 -1
- package/lib/DBSchemaBuilder.d.ts +3 -3
- package/lib/DBSchemaBuilder.d.ts.map +1 -1
- package/lib/DBSchemaBuilder.js +6 -6
- package/lib/DBSchemaBuilder.ts +10 -12
- package/lib/DboBuilder/QueryBuilder/Functions.d.ts +3 -3
- package/lib/DboBuilder/QueryBuilder/Functions.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/Functions.js +9 -9
- package/lib/DboBuilder/QueryBuilder/Functions.ts +13 -13
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts +3 -3
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +12 -12
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.ts +5 -5
- package/lib/DboBuilder/TableHandler.d.ts +1 -1
- package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
- package/lib/DboBuilder/TableHandler.js +18 -20
- package/lib/DboBuilder/TableHandler.ts +21 -20
- package/lib/DboBuilder/ViewHandler.d.ts +1 -11
- package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/lib/DboBuilder/ViewHandler.js +50 -63
- package/lib/DboBuilder/ViewHandler.ts +68 -97
- package/lib/DboBuilder/delete.js +0 -1
- package/lib/DboBuilder/delete.ts +1 -1
- package/lib/DboBuilder/getColumns.js +5 -4
- package/lib/DboBuilder/getColumns.ts +5 -5
- package/lib/DboBuilder/getCondition.d.ts.map +1 -1
- package/lib/DboBuilder/getCondition.js +6 -6
- package/lib/DboBuilder/getCondition.ts +7 -7
- package/lib/DboBuilder/insert.js +15 -16
- package/lib/DboBuilder/insert.ts +18 -18
- package/lib/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/lib/DboBuilder/insertDataParse.js +9 -10
- package/lib/DboBuilder/insertDataParse.ts +42 -43
- package/lib/DboBuilder/parseUpdateRules.js +2 -2
- package/lib/DboBuilder/parseUpdateRules.ts +2 -2
- package/lib/DboBuilder/runSQL.d.ts.map +1 -1
- package/lib/DboBuilder/runSQL.js +5 -5
- package/lib/DboBuilder/runSQL.ts +6 -6
- package/lib/DboBuilder/subscribe.d.ts +1 -1
- package/lib/DboBuilder/subscribe.d.ts.map +1 -1
- package/lib/DboBuilder/subscribe.js +3 -3
- package/lib/DboBuilder/subscribe.ts +3 -3
- package/lib/DboBuilder/update.js +5 -6
- package/lib/DboBuilder/update.ts +6 -6
- package/lib/DboBuilder/uploadFile.d.ts.map +1 -1
- package/lib/DboBuilder/uploadFile.js +1 -1
- package/lib/DboBuilder/uploadFile.ts +2 -2
- package/lib/DboBuilder.d.ts +22 -22
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.js +13 -14
- package/lib/DboBuilder.ts +19 -19
- package/lib/FileManager.d.ts +6 -6
- package/lib/FileManager.d.ts.map +1 -1
- package/lib/FileManager.js +3 -5
- package/lib/FileManager.ts +7 -6
- package/lib/Filtering.d.ts +1 -1
- package/lib/Filtering.d.ts.map +1 -1
- package/lib/Filtering.js +7 -7
- package/lib/Filtering.ts +7 -7
- package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.js +294 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +293 -0
- package/lib/JSONBValidation/validation.d.ts +108 -0
- package/lib/JSONBValidation/validation.d.ts.map +1 -0
- package/lib/JSONBValidation/validation.js +221 -0
- package/lib/JSONBValidation/validation.ts +332 -0
- package/lib/PostgresNotifListenManager.d.ts +1 -1
- package/lib/PostgresNotifListenManager.d.ts.map +1 -1
- package/lib/PostgresNotifListenManager.js +1 -1
- package/lib/PostgresNotifListenManager.ts +1 -1
- package/lib/Prostgles.d.ts +14 -14
- package/lib/Prostgles.d.ts.map +1 -1
- package/lib/Prostgles.js +20 -20
- package/lib/Prostgles.ts +22 -21
- package/lib/PubSubManager/PubSubManager.d.ts +7 -7
- package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.js +10 -7
- package/lib/PubSubManager/initPubSubManager.ts +12 -7
- package/lib/PublishParser.d.ts +32 -32
- package/lib/PublishParser.d.ts.map +1 -1
- package/lib/PublishParser.js +121 -124
- package/lib/PublishParser.ts +125 -127
- package/lib/SchemaWatch.d.ts +1 -1
- package/lib/SchemaWatch.d.ts.map +1 -1
- package/lib/SyncReplication.d.ts +5 -5
- package/lib/SyncReplication.d.ts.map +1 -1
- package/lib/SyncReplication.js +19 -16
- package/lib/SyncReplication.ts +470 -471
- package/lib/TableConfig.d.ts +28 -24
- package/lib/TableConfig.d.ts.map +1 -1
- package/lib/TableConfig.js +33 -12
- package/lib/TableConfig.ts +55 -21
- package/lib/index.js +1 -1
- package/lib/index.ts +1 -1
- package/lib/shortestPath.d.ts +1 -1
- package/lib/shortestPath.d.ts.map +1 -1
- package/lib/shortestPath.js +11 -11
- package/lib/shortestPath.ts +11 -11
- package/package.json +10 -6
- package/tests/client/PID.txt +1 -1
- package/tests/client/package-lock.json +53 -31
- package/tests/client/package.json +4 -1
- package/tests/isomorphic_queries.d.ts +4 -1
- package/tests/isomorphic_queries.d.ts.map +1 -1
- package/tests/isomorphic_queries.js +38 -30
- package/tests/isomorphic_queries.ts +40 -33
- package/tests/server/DBoGenerated.d.ts +1 -1
- package/tests/server/index.js +8 -7
- package/tests/server/index.ts +10 -8
- package/tests/server/package-lock.json +76 -58
- package/tests/server/package.json +2 -2
- package/tests/server/server.ts +2 -3
- package/lib/validation.d.ts +0 -100
- package/lib/validation.d.ts.map +0 -1
- package/lib/validation.js +0 -280
- package/lib/validation.ts +0 -360
package/lib/FileManager.js
CHANGED
|
@@ -64,13 +64,11 @@ class FileManager {
|
|
|
64
64
|
}
|
|
65
65
|
return this.prostgles.dbo;
|
|
66
66
|
}
|
|
67
|
-
;
|
|
68
67
|
get db() {
|
|
69
68
|
if (!this.prostgles?.db)
|
|
70
69
|
throw "this.prostgles.db missing";
|
|
71
70
|
return this.prostgles.db;
|
|
72
71
|
}
|
|
73
|
-
;
|
|
74
72
|
tableName;
|
|
75
73
|
fileRoute;
|
|
76
74
|
get fileRouteExpress() {
|
|
@@ -140,7 +138,7 @@ class FileManager {
|
|
|
140
138
|
if (!config)
|
|
141
139
|
throw new Error("File table config missing");
|
|
142
140
|
const buffer = typeof file === "string" ? Buffer.from(file, 'utf8') : file;
|
|
143
|
-
|
|
141
|
+
const result = await (0, exports.getFileTypeFromFilename)(fileName);
|
|
144
142
|
if (tableName && colName) {
|
|
145
143
|
const tableConfig = config.referencedTables?.[tableName];
|
|
146
144
|
if (tableConfig && (0, prostgles_types_1.isObject)(tableConfig) && tableConfig.referenceColumns[colName]) {
|
|
@@ -649,10 +647,10 @@ const getFileType = async (file, fileName) => {
|
|
|
649
647
|
};
|
|
650
648
|
exports.getFileType = getFileType;
|
|
651
649
|
function bytesToSize(bytes) {
|
|
652
|
-
|
|
650
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
653
651
|
if (bytes == 0)
|
|
654
652
|
return '0 Byte';
|
|
655
|
-
|
|
653
|
+
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)) + "");
|
|
656
654
|
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
|
|
657
655
|
}
|
|
658
656
|
exports.bytesToSize = bytesToSize;
|
package/lib/FileManager.ts
CHANGED
|
@@ -108,11 +108,12 @@ export default class FileManager {
|
|
|
108
108
|
throw "this.prostgles.dbo missing"
|
|
109
109
|
}
|
|
110
110
|
return this.prostgles.dbo
|
|
111
|
-
}
|
|
111
|
+
}
|
|
112
|
+
|
|
112
113
|
get db(): DB {
|
|
113
114
|
if(!this.prostgles?.db) throw "this.prostgles.db missing"
|
|
114
115
|
return this.prostgles.db
|
|
115
|
-
}
|
|
116
|
+
}
|
|
116
117
|
|
|
117
118
|
tableName?: string;
|
|
118
119
|
|
|
@@ -196,7 +197,7 @@ export default class FileManager {
|
|
|
196
197
|
|
|
197
198
|
const buffer = typeof file === "string"? Buffer.from(file, 'utf8') : file;
|
|
198
199
|
|
|
199
|
-
|
|
200
|
+
const result = await getFileTypeFromFilename(fileName);
|
|
200
201
|
if(tableName && colName){
|
|
201
202
|
const tableConfig = config.referencedTables?.[tableName];
|
|
202
203
|
|
|
@@ -727,7 +728,7 @@ export const removeExpressRoute = (app: ExpressApp | undefined, routePaths: (str
|
|
|
727
728
|
const routes = app?._router?.stack;
|
|
728
729
|
if(routes){
|
|
729
730
|
routes.forEach((route, i) => {
|
|
730
|
-
if(routePaths.filter(isDefined).includes(route.route?.path
|
|
731
|
+
if(routePaths.filter(isDefined).includes(route.route?.path as any)){
|
|
731
732
|
routes.splice(i, 1);
|
|
732
733
|
}
|
|
733
734
|
})
|
|
@@ -781,9 +782,9 @@ export const getFileType = async (file: Buffer | string, fileName: string): Prom
|
|
|
781
782
|
}
|
|
782
783
|
|
|
783
784
|
export function bytesToSize(bytes: number) {
|
|
784
|
-
|
|
785
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
785
786
|
if (bytes == 0) return '0 Byte';
|
|
786
|
-
|
|
787
|
+
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)) + "");
|
|
787
788
|
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
|
|
788
789
|
}
|
|
789
790
|
|
package/lib/Filtering.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { FullFilter } from "prostgles-types";
|
|
|
4
4
|
* Parse a single filter
|
|
5
5
|
* Ensure only single key objects reach this point
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
type ParseFilterItemArgs = {
|
|
8
8
|
filter: FullFilter;
|
|
9
9
|
select?: SelectItem[];
|
|
10
10
|
tableAlias?: string;
|
package/lib/Filtering.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Filtering.d.ts","sourceRoot":"","sources":["Filtering.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EACa,UAAU,EAG7B,MAAM,iBAAiB,CAAC;AAGzB;;;EAGE;AACF,
|
|
1
|
+
{"version":3,"file":"Filtering.d.ts","sourceRoot":"","sources":["Filtering.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EACa,UAAU,EAG7B,MAAM,iBAAiB,CAAC;AAGzB;;;EAGE;AACF,KAAK,mBAAmB,GAAG;IAAG,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AACzG,eAAO,MAAM,eAAe,SAAU,mBAAmB,KAAG,MAqV3D,CAAA"}
|
package/lib/Filtering.js
CHANGED
|
@@ -72,7 +72,7 @@ const parseFilterItem = (args) => {
|
|
|
72
72
|
const getSep = (fromIdx = 0) => {
|
|
73
73
|
const strPart = remainingStr.slice(fromIdx);
|
|
74
74
|
let idx = strPart.indexOf("->");
|
|
75
|
-
|
|
75
|
+
const idxx = strPart.indexOf("->>");
|
|
76
76
|
if (idx > -1) {
|
|
77
77
|
/* if -> matches then check if it's the last separator */
|
|
78
78
|
if (idx === idxx)
|
|
@@ -105,14 +105,14 @@ const parseFilterItem = (args) => {
|
|
|
105
105
|
}
|
|
106
106
|
else if (remainingStr.startsWith(".")) {
|
|
107
107
|
leftQ = getLeftQ(selItem);
|
|
108
|
-
|
|
108
|
+
const getSep = (fromIdx = 0) => {
|
|
109
109
|
const idx = remainingStr.slice(fromIdx).indexOf(".");
|
|
110
110
|
if (idx > -1)
|
|
111
111
|
return fromIdx + idx;
|
|
112
112
|
return idx;
|
|
113
113
|
};
|
|
114
114
|
let currIdx = getSep();
|
|
115
|
-
|
|
115
|
+
const res = {};
|
|
116
116
|
let curObj = res;
|
|
117
117
|
while (currIdx > -1) {
|
|
118
118
|
let nextIdx = getSep(currIdx + 1);
|
|
@@ -231,7 +231,7 @@ const parseFilterItem = (args) => {
|
|
|
231
231
|
if (!filterValue?.length) {
|
|
232
232
|
return " FALSE ";
|
|
233
233
|
}
|
|
234
|
-
|
|
234
|
+
const _fVal = filterValue.filter((v) => v !== null);
|
|
235
235
|
let c1 = "", c2 = "";
|
|
236
236
|
if (_fVal.length) {
|
|
237
237
|
c1 = leftQ + " IN " + parseRightVal(_fVal, "csv");
|
|
@@ -244,7 +244,7 @@ const parseFilterItem = (args) => {
|
|
|
244
244
|
if (!filterValue?.length) {
|
|
245
245
|
return " TRUE ";
|
|
246
246
|
}
|
|
247
|
-
|
|
247
|
+
const _fVal = filterValue.filter((v) => v !== null);
|
|
248
248
|
let c1 = "", c2 = "";
|
|
249
249
|
if (_fVal.length)
|
|
250
250
|
c1 = leftQ + " NOT IN " + parseRightVal(_fVal, "csv");
|
|
@@ -272,7 +272,7 @@ const parseFilterItem = (args) => {
|
|
|
272
272
|
/* MAYBE TEXT OR MAYBE ARRAY */
|
|
273
273
|
}
|
|
274
274
|
else if (["@>", "<@", "$contains", "$containedBy", "&&", "@@"].includes(filterOperand)) {
|
|
275
|
-
|
|
275
|
+
const operand = filterOperand === "@@" ? "@@" :
|
|
276
276
|
["@>", "$contains"].includes(filterOperand) ? "@>" :
|
|
277
277
|
["&&"].includes(filterOperand) ? "&&" :
|
|
278
278
|
"<@";
|
|
@@ -285,7 +285,7 @@ const parseFilterItem = (args) => {
|
|
|
285
285
|
let lq = `to_tsvector(${leftQ}::text)`;
|
|
286
286
|
if (selItem && selItem.columnPGDataType === "tsvector")
|
|
287
287
|
lq = leftQ;
|
|
288
|
-
|
|
288
|
+
const res = `${lq} ${operand} ` + `${funcName}${parseRightVal(funcArgs, "csv")}`;
|
|
289
289
|
return res;
|
|
290
290
|
}
|
|
291
291
|
else {
|
package/lib/Filtering.ts
CHANGED
|
@@ -101,7 +101,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
101
101
|
const getSep = (fromIdx = 0): GetSepRes => {
|
|
102
102
|
const strPart = remainingStr.slice(fromIdx)
|
|
103
103
|
let idx = strPart.indexOf("->");
|
|
104
|
-
|
|
104
|
+
const idxx = strPart.indexOf("->>");
|
|
105
105
|
if(idx > -1) {
|
|
106
106
|
/* if -> matches then check if it's the last separator */
|
|
107
107
|
if(idx === idxx) return { idx: idx + fromIdx, sep: "->>" }
|
|
@@ -140,13 +140,13 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
140
140
|
} else if(remainingStr.startsWith(".")){
|
|
141
141
|
leftQ = getLeftQ(selItem);
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
const getSep = (fromIdx = 0) => {
|
|
144
144
|
const idx = remainingStr.slice(fromIdx).indexOf(".");
|
|
145
145
|
if(idx > -1) return fromIdx + idx;
|
|
146
146
|
return idx;
|
|
147
147
|
}
|
|
148
148
|
let currIdx = getSep();
|
|
149
|
-
|
|
149
|
+
const res: any = {};
|
|
150
150
|
let curObj = res;
|
|
151
151
|
|
|
152
152
|
while(currIdx > -1){
|
|
@@ -279,7 +279,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
279
279
|
return " FALSE ";
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
const _fVal: any[] = filterValue.filter((v: any) => v !== null);
|
|
283
283
|
let c1 = "", c2 = "";
|
|
284
284
|
if(_fVal.length) {
|
|
285
285
|
c1 = leftQ + " IN " + parseRightVal(_fVal, "csv");
|
|
@@ -292,7 +292,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
292
292
|
return " TRUE ";
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
const _fVal: any[] = filterValue.filter((v: any) => v !== null);
|
|
296
296
|
let c1 = "", c2 = "";
|
|
297
297
|
if(_fVal.length) c1 = leftQ + " NOT IN " + parseRightVal(_fVal, "csv");
|
|
298
298
|
if(filterValue.includes(null)) c2 = ` ${leftQ} IS NOT NULL `;
|
|
@@ -318,7 +318,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
318
318
|
|
|
319
319
|
/* MAYBE TEXT OR MAYBE ARRAY */
|
|
320
320
|
} else if(["@>", "<@", "$contains", "$containedBy", "&&", "@@"].includes(filterOperand)){
|
|
321
|
-
|
|
321
|
+
const operand = filterOperand === "@@"? "@@":
|
|
322
322
|
["@>", "$contains"].includes(filterOperand)? "@>" :
|
|
323
323
|
["&&"].includes(filterOperand)? "&&" :
|
|
324
324
|
"<@";
|
|
@@ -332,7 +332,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
|
|
|
332
332
|
let lq = `to_tsvector(${leftQ}::text)`;
|
|
333
333
|
if(selItem && selItem.columnPGDataType === "tsvector") lq = leftQ!;
|
|
334
334
|
|
|
335
|
-
|
|
335
|
+
const res = `${lq} ${operand} ` + `${funcName}${parseRightVal(funcArgs, "csv")}`;
|
|
336
336
|
|
|
337
337
|
return res;
|
|
338
338
|
} else {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate_jsonb_schema_sql.d.ts","sourceRoot":"","sources":["validate_jsonb_schema_sql.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,wBAAwB,mCAA6C,CAAC;AACnF,eAAO,MAAM,yBAAyB,QAiSrC,CAAC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate_jsonb_schema_sql = exports.VALIDATE_SCHEMA_FUNCNAME = void 0;
|
|
4
|
+
exports.VALIDATE_SCHEMA_FUNCNAME = "prostgles.validate_jsonb_schema";
|
|
5
|
+
exports.validate_jsonb_schema_sql = `
|
|
6
|
+
DROP FUNCTION IF EXISTS ${exports.VALIDATE_SCHEMA_FUNCNAME}(jsonb_schema text, data jsonb, checked_path text[]);
|
|
7
|
+
|
|
8
|
+
CREATE OR REPLACE FUNCTION ${exports.VALIDATE_SCHEMA_FUNCNAME}(jsonb_schema TEXT, data JSONB, checked_path TEXT[] DEFAULT ARRAY[]::TEXT[]) RETURNS boolean AS
|
|
9
|
+
$f$
|
|
10
|
+
DECLARE
|
|
11
|
+
sub_schema RECORD;
|
|
12
|
+
array_element RECORD;
|
|
13
|
+
schema JSONB;
|
|
14
|
+
path text;
|
|
15
|
+
allowed_types text[] = '{any,boolean,number,integer,string,boolean[],number[],integer[],string[],any[]}';
|
|
16
|
+
typeStr TEXT = NULL;
|
|
17
|
+
optional boolean;
|
|
18
|
+
nullable boolean;
|
|
19
|
+
colname TEXT;
|
|
20
|
+
|
|
21
|
+
extra_keys TEXT[];
|
|
22
|
+
BEGIN
|
|
23
|
+
path = concat_ws(', ',
|
|
24
|
+
'Path: ' || array_to_string(checked_path, '.'),
|
|
25
|
+
'Data: ' || data::TEXT,
|
|
26
|
+
'JSONBSchema: ' || schema::TEXT
|
|
27
|
+
);
|
|
28
|
+
colname = COALESCE(checked_path[1], '');
|
|
29
|
+
|
|
30
|
+
IF length(jsonb_schema) = 0 THEN
|
|
31
|
+
RAISE EXCEPTION 'Empty schema. %', path USING HINT = path, COLUMN = colname;
|
|
32
|
+
END IF;
|
|
33
|
+
|
|
34
|
+
/* 'string' */
|
|
35
|
+
IF ARRAY[jsonb_schema] <@ allowed_types THEN
|
|
36
|
+
schema = jsonb_build_object('type', jsonb_schema);
|
|
37
|
+
/* { "type": ... } */
|
|
38
|
+
ELSIF BTRIM(jsonb_schema) ILIKE '{%' THEN
|
|
39
|
+
schema = jsonb_schema::JSONB;
|
|
40
|
+
ELSE
|
|
41
|
+
RAISE EXCEPTION $$Invalid schema. Expecting 'typename' or { "type": "typename" } but received: %, %$$, jsonb_schema, path USING HINT = path, COLUMN = colname;
|
|
42
|
+
END IF;
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
nullable = COALESCE((schema->'nullable')::BOOLEAN, FALSE);
|
|
46
|
+
IF data IS NULL OR jsonb_typeof(data) = 'null' THEN
|
|
47
|
+
IF NOT nullable THEN
|
|
48
|
+
RAISE EXCEPTION 'Is not nullable. %', path USING HINT = path, COLUMN = colname;
|
|
49
|
+
ELSE
|
|
50
|
+
RETURN true;
|
|
51
|
+
END IF;
|
|
52
|
+
END IF;
|
|
53
|
+
|
|
54
|
+
IF schema ? 'enum' THEN
|
|
55
|
+
IF
|
|
56
|
+
jsonb_typeof(schema->'enum') != 'array' OR
|
|
57
|
+
jsonb_array_length(schema->'enum') < 1
|
|
58
|
+
THEN
|
|
59
|
+
RAISE EXCEPTION 'Invalid schema enum (%) .Must be a non empty array %', schema->'enum', path USING HINT = path, COLUMN = colname;
|
|
60
|
+
END IF;
|
|
61
|
+
|
|
62
|
+
IF NOT jsonb_build_array(data) <@ (schema->'enum') THEN
|
|
63
|
+
RAISE EXCEPTION 'Data not in allowed enum list (%), %', schema->'enum', path USING HINT = path, COLUMN = colname;
|
|
64
|
+
END IF;
|
|
65
|
+
|
|
66
|
+
ELSIF schema ? 'type' THEN
|
|
67
|
+
|
|
68
|
+
IF jsonb_typeof(schema->'type') = 'string' THEN
|
|
69
|
+
typeStr = schema->>'type';
|
|
70
|
+
IF NOT ARRAY[typeStr] <@ allowed_types THEN
|
|
71
|
+
RAISE EXCEPTION 'Bad schema type type %, allowed types: %. %',typeStr, allowed_types, path USING HINT = path, COLUMN = colname;
|
|
72
|
+
END IF;
|
|
73
|
+
|
|
74
|
+
/** Primitive array */
|
|
75
|
+
IF typeStr LIKE '%[]' THEN
|
|
76
|
+
|
|
77
|
+
typeStr = left(typeStr, -2);
|
|
78
|
+
|
|
79
|
+
IF jsonb_typeof(data) != 'array' THEN
|
|
80
|
+
RAISE EXCEPTION 'Types not matching. Expecting an array. %', path USING HINT = path, COLUMN = colname;
|
|
81
|
+
END IF;
|
|
82
|
+
|
|
83
|
+
FOR array_element IN
|
|
84
|
+
SELECT value, row_number() OVER() -1 as idx
|
|
85
|
+
FROM jsonb_array_elements(data)
|
|
86
|
+
LOOP
|
|
87
|
+
IF NOT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
88
|
+
CASE WHEN schema->'allowedValues' IS NOT NULL THEN
|
|
89
|
+
jsonb_build_object('type', typeStr, 'allowedValues', schema->'allowedValues')::TEXT
|
|
90
|
+
ELSE typeStr END,
|
|
91
|
+
array_element.value,
|
|
92
|
+
checked_path || array_element.idx::TEXT
|
|
93
|
+
) THEN
|
|
94
|
+
|
|
95
|
+
RETURN FALSE;
|
|
96
|
+
END IF;
|
|
97
|
+
END LOOP;
|
|
98
|
+
|
|
99
|
+
RETURN TRUE;
|
|
100
|
+
|
|
101
|
+
/** Primitive */
|
|
102
|
+
ELSE
|
|
103
|
+
|
|
104
|
+
IF (
|
|
105
|
+
typeStr = 'number' AND jsonb_typeof(data) != typeStr OR
|
|
106
|
+
(typeStr = 'integer' AND (jsonb_typeof(data) != 'number' OR ceil(data::NUMERIC) != floor(data::NUMERIC))) OR
|
|
107
|
+
typeStr = 'boolean' AND jsonb_typeof(data) != typeStr OR
|
|
108
|
+
typeStr = 'string' AND jsonb_typeof(data) != typeStr OR
|
|
109
|
+
typeStr = 'any' AND jsonb_typeof(data) = 'null'
|
|
110
|
+
) THEN
|
|
111
|
+
RAISE EXCEPTION 'Data type not matching. Expected: %, Actual: %, %', typeStr, jsonb_typeof(data), path USING HINT = path, COLUMN = colname;
|
|
112
|
+
END IF;
|
|
113
|
+
|
|
114
|
+
IF schema ? 'allowedValues' AND NOT(jsonb_build_array(data) <@ (schema->'allowedValues')) THEN
|
|
115
|
+
IF (
|
|
116
|
+
SELECT COUNT(distinct jsonb_typeof(value))
|
|
117
|
+
FROM jsonb_array_elements(schema->'allowedValues')
|
|
118
|
+
) > 1 THEN
|
|
119
|
+
RAISE EXCEPTION 'Invalid schema. schema.allowedValues (%) contains more than one data type . %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
120
|
+
END IF;
|
|
121
|
+
|
|
122
|
+
IF EXISTS(
|
|
123
|
+
SELECT 1
|
|
124
|
+
FROM jsonb_array_elements(schema->'allowedValues')
|
|
125
|
+
WHERE jsonb_typeof(value) != jsonb_typeof(data)
|
|
126
|
+
) THEN
|
|
127
|
+
RAISE EXCEPTION 'Invalid schema. schema.allowedValues (%) contains contains values not matchine the schema.type %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
128
|
+
END IF;
|
|
129
|
+
|
|
130
|
+
RAISE EXCEPTION 'Data not in allowedValues (%). %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
131
|
+
|
|
132
|
+
END IF;
|
|
133
|
+
|
|
134
|
+
END IF;
|
|
135
|
+
|
|
136
|
+
/* Object */
|
|
137
|
+
ELSIF jsonb_typeof(schema->'type') = 'object' THEN
|
|
138
|
+
|
|
139
|
+
IF jsonb_typeof(data) != 'object' THEN
|
|
140
|
+
RAISE EXCEPTION E'Expecting an object: \n %', path USING HINT = path, COLUMN = colname;
|
|
141
|
+
END IF;
|
|
142
|
+
|
|
143
|
+
extra_keys = ARRAY(SELECT k FROM (
|
|
144
|
+
SELECT jsonb_object_keys(data) as k
|
|
145
|
+
EXCEPT
|
|
146
|
+
SELECT jsonb_object_keys(schema->'type') as k
|
|
147
|
+
) t);
|
|
148
|
+
|
|
149
|
+
IF array_length(extra_keys, 1) > 0 THEN
|
|
150
|
+
RAISE EXCEPTION E'Object contains invalid keys: % \n %',
|
|
151
|
+
array_to_string(extra_keys, ', '), path USING HINT = path, COLUMN = colname;
|
|
152
|
+
END IF;
|
|
153
|
+
|
|
154
|
+
FOR sub_schema IN
|
|
155
|
+
SELECT key, value
|
|
156
|
+
FROM jsonb_each(schema->'type')
|
|
157
|
+
LOOP
|
|
158
|
+
optional = COALESCE((sub_schema.value->'optional')::BOOLEAN, FALSE);
|
|
159
|
+
IF NOT (data ? sub_schema.key) THEN
|
|
160
|
+
|
|
161
|
+
IF NOT optional THEN
|
|
162
|
+
RAISE EXCEPTION 'Types not matching. Required property (%) is missing. %',sub_schema.key , path USING HINT = path, COLUMN = colname;
|
|
163
|
+
ELSE
|
|
164
|
+
RETURN true;
|
|
165
|
+
END IF;
|
|
166
|
+
END IF;
|
|
167
|
+
|
|
168
|
+
IF NOT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
169
|
+
-- sub_schema.value::TEXT,
|
|
170
|
+
CASE WHEN jsonb_typeof(sub_schema.value) = 'string' THEN TRIM(both '"' from sub_schema.value::TEXT) ELSE sub_schema.value::TEXT END,
|
|
171
|
+
data->sub_schema.key,
|
|
172
|
+
checked_path || sub_schema.key
|
|
173
|
+
) THEN
|
|
174
|
+
RETURN false;
|
|
175
|
+
END IF;
|
|
176
|
+
|
|
177
|
+
END LOOP;
|
|
178
|
+
ELSE
|
|
179
|
+
RAISE EXCEPTION 'Unexpected schema.type ( % ), %',jsonb_typeof(schema->'type'), path USING HINT = path, COLUMN = colname;
|
|
180
|
+
END IF;
|
|
181
|
+
|
|
182
|
+
/* oneOf: [{ key_name: { type: "string" } }] */
|
|
183
|
+
ELSIF schema ? 'oneOf' THEN
|
|
184
|
+
IF jsonb_typeof(schema->'oneOf') != 'array' THEN
|
|
185
|
+
RAISE EXCEPTION 'Unexpected oneOf schema. Expecting an array of objects but received: % , %',schema->>'oneOf', path USING HINT = path, COLUMN = colname;
|
|
186
|
+
END IF;
|
|
187
|
+
|
|
188
|
+
FOR sub_schema IN
|
|
189
|
+
SELECT jsonb_build_object('type', value) as value
|
|
190
|
+
FROM jsonb_array_elements(schema->'oneOf')
|
|
191
|
+
LOOP
|
|
192
|
+
|
|
193
|
+
BEGIN
|
|
194
|
+
|
|
195
|
+
IF ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
196
|
+
sub_schema.value::TEXT,
|
|
197
|
+
data,
|
|
198
|
+
checked_path
|
|
199
|
+
) THEN
|
|
200
|
+
RETURN true;
|
|
201
|
+
END IF;
|
|
202
|
+
|
|
203
|
+
/* Ignore exceptions in case the last schema will match */
|
|
204
|
+
EXCEPTION WHEN others THEN
|
|
205
|
+
END;
|
|
206
|
+
END LOOP;
|
|
207
|
+
|
|
208
|
+
RAISE EXCEPTION 'Could not validate against any oneOf schemas ( % ), %', schema->>'oneOf', path USING HINT = path, COLUMN = colname;
|
|
209
|
+
|
|
210
|
+
/* arrayOf: { key_name: { type: "string" } } */
|
|
211
|
+
ELSIF jsonb_typeof(schema->'arrayOf') = 'object' THEN
|
|
212
|
+
IF jsonb_typeof(data) != 'array' THEN
|
|
213
|
+
RAISE EXCEPTION 'Is not an array. %', path USING HINT = path, COLUMN = colname;
|
|
214
|
+
END IF;
|
|
215
|
+
|
|
216
|
+
FOR array_element IN
|
|
217
|
+
SELECT value, row_number() OVER() -1 as idx
|
|
218
|
+
FROM jsonb_array_elements(data)
|
|
219
|
+
LOOP
|
|
220
|
+
IF NOT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
221
|
+
(schema - 'arrayOf' || jsonb_build_object('type', schema->'arrayOf'))::TEXT, -- RENAME
|
|
222
|
+
array_element.value, checked_path || array_element.idx::TEXT
|
|
223
|
+
) THEN
|
|
224
|
+
RETURN false;
|
|
225
|
+
END IF;
|
|
226
|
+
END LOOP;
|
|
227
|
+
|
|
228
|
+
ELSE
|
|
229
|
+
RAISE EXCEPTION 'Unexpected schema: %, %', schema, path USING HINT = path, COLUMN = colname;
|
|
230
|
+
END IF;
|
|
231
|
+
|
|
232
|
+
RETURN true;
|
|
233
|
+
END;
|
|
234
|
+
$f$ LANGUAGE 'plpgsql' IMMUTABLE;
|
|
235
|
+
|
|
236
|
+
COMMENT ON FUNCTION ${exports.VALIDATE_SCHEMA_FUNCNAME}
|
|
237
|
+
IS $$Used to validate jsonb data against a schema:
|
|
238
|
+
validate_jsonb_schema(
|
|
239
|
+
'{ "type": { "a": "number[]" } }',
|
|
240
|
+
'{ "a": [2] }'
|
|
241
|
+
)
|
|
242
|
+
$$;
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
/* TESTS */
|
|
246
|
+
|
|
247
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
248
|
+
'{ "enum": ["a", "b", 2] }',
|
|
249
|
+
'"a"'::JSONB
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
253
|
+
'{ "enum": ["a", "b", 2] }',
|
|
254
|
+
'2'::JSONB
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
258
|
+
'{
|
|
259
|
+
"oneOf": [
|
|
260
|
+
{ "a": "string" } ,
|
|
261
|
+
{
|
|
262
|
+
"a": {
|
|
263
|
+
"type": "boolean",
|
|
264
|
+
"allowedValues": [false],
|
|
265
|
+
"optional": true
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}',
|
|
270
|
+
'{ "a": false }'
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
274
|
+
'{ "arrayOf": { "a": "string", "narr": { "arrayOf": { "a": { "type": "string", "optional": false, "nullable": true } } } } }',
|
|
275
|
+
'[{ "a": "ddd", "narr": [{ "a": null }] }]'::JSONB
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
279
|
+
'{ "type": { "a": { "type": "integer[]", "allowedValues": [2] } } }'::TEXT,
|
|
280
|
+
'{ "a": [2, 2] }'
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}(
|
|
284
|
+
'{ "type": { "a": { "type": "string[]", "allowedValues": ["2"] } } }'::TEXT,
|
|
285
|
+
'{ "a": ["2"] }'
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}('{ "type": "any"}', '{}');
|
|
289
|
+
|
|
290
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}('{ "type": { "a": { "enum": ["a"] } } }', '{ "a": "a"}');
|
|
291
|
+
|
|
292
|
+
SELECT ${exports.VALIDATE_SCHEMA_FUNCNAME}('{ "arrayOf": { "a": { "enum": ["a"] } } }', '[{ "a": "a"}]');
|
|
293
|
+
|
|
294
|
+
`;
|