prostgles-server 2.0.146 → 2.0.149
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 +15 -13
- package/dist/AuthHandler.d.ts.map +1 -1
- package/dist/AuthHandler.js +43 -44
- package/dist/AuthHandler.js.map +1 -1
- package/dist/DBEventsManager.d.ts +6 -5
- package/dist/DBEventsManager.d.ts.map +1 -1
- package/dist/DBEventsManager.js +8 -2
- package/dist/DBEventsManager.js.map +1 -1
- package/dist/DboBuilder.d.ts +54 -50
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +242 -206
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts +5 -5
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +59 -31
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.d.ts.map +1 -1
- package/dist/Filtering.js +17 -14
- package/dist/Filtering.js.map +1 -1
- package/dist/PostgresNotifListenManager.d.ts +3 -3
- package/dist/PostgresNotifListenManager.d.ts.map +1 -1
- package/dist/PostgresNotifListenManager.js +7 -5
- package/dist/PostgresNotifListenManager.js.map +1 -1
- package/dist/Prostgles.d.ts +6 -9
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +125 -86
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager.d.ts +8 -8
- package/dist/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager.js +58 -52
- package/dist/PubSubManager.js.map +1 -1
- package/dist/QueryBuilder.d.ts +6 -5
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/dist/QueryBuilder.js +124 -89
- package/dist/QueryBuilder.js.map +1 -1
- package/dist/SyncReplication.js +38 -35
- package/dist/SyncReplication.js.map +1 -1
- package/dist/TableConfig.d.ts +0 -1
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +36 -28
- package/dist/TableConfig.js.map +1 -1
- package/dist/shortestPath.d.ts.map +1 -1
- package/dist/shortestPath.js +2 -1
- package/dist/shortestPath.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -1
- package/dist/utils.js.map +1 -1
- package/lib/AuthHandler.ts +50 -40
- package/lib/DBEventsManager.ts +14 -7
- package/lib/DboBuilder.ts +231 -195
- package/lib/FileManager.ts +30 -21
- package/lib/Filtering.ts +19 -16
- package/lib/PostgresNotifListenManager.ts +11 -10
- package/lib/Prostgles.ts +89 -73
- package/lib/PubSubManager.ts +13 -11
- package/lib/QueryBuilder.ts +53 -29
- package/lib/SyncReplication.ts +10 -10
- package/lib/TableConfig.ts +23 -15
- package/lib/shortestPath.ts +6 -4
- package/lib/utils.ts +3 -2
- package/package.json +4 -3
- package/tests/client/PID.txt +1 -1
- package/tests/client/index.js +10 -7
- package/tests/client/index.ts +12 -8
- package/tests/client/package-lock.json +14 -14
- package/tests/client/package.json +2 -2
- package/tests/client/tsconfig.json +2 -2
- package/tests/client_only_queries.js +127 -104
- package/tests/client_only_queries.ts +43 -17
- package/tests/isomorphic_queries.js +22 -6
- package/tests/isomorphic_queries.ts +18 -6
- package/tests/server/package-lock.json +21 -19
- package/tests/server/package.json +2 -2
- package/tests/server/tsconfig.json +2 -2
- package/tsconfig.json +3 -2
package/lib/QueryBuilder.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
|
|
7
7
|
import { pgp, Filter, LocalParams, isPlainObject, TableHandler, ViewHandler, postgresToTsType } from "./DboBuilder";
|
|
8
|
-
import { TableRule
|
|
8
|
+
import { TableRule } from "./Prostgles";
|
|
9
9
|
import { SelectParamsBasic as SelectParams, isEmpty, FieldFilter, asName, TextFilter_FullTextSearchFilterKeys, TS_PG_Types, ColumnInfo, PG_COLUMN_UDT_DATA_TYPE } from "prostgles-types";
|
|
10
10
|
import { get, isObject } from "./utils";
|
|
11
11
|
|
|
@@ -164,6 +164,8 @@ export type FunctionSpec = {
|
|
|
164
164
|
* allowedFields passed for multicol functions (e.g.: $rowhash)
|
|
165
165
|
*/
|
|
166
166
|
getQuery: (params: GetQueryArgs) => string;
|
|
167
|
+
|
|
168
|
+
returnType?: PG_COLUMN_UDT_DATA_TYPE;
|
|
167
169
|
};
|
|
168
170
|
|
|
169
171
|
const MAX_COL_NUM = 1600;
|
|
@@ -256,8 +258,10 @@ let PostGIS_Funcs: FunctionSpec[] = [
|
|
|
256
258
|
|
|
257
259
|
if(!isPlainObject(arg2)) mErr();
|
|
258
260
|
const col = allColumns.find(c => c.name === args[0]);
|
|
261
|
+
if(!col) throw new Error("Col not found: " + args[0])
|
|
259
262
|
|
|
260
|
-
const {
|
|
263
|
+
const {
|
|
264
|
+
lat, lng, srid = 4326,
|
|
261
265
|
geojson, text, use_spheroid,
|
|
262
266
|
distance, spheroid = 'SPHEROID["WGS 84",6378137,298.257223563]',
|
|
263
267
|
debug
|
|
@@ -597,7 +601,7 @@ export const FUNCTIONS: FunctionSpec[] = [
|
|
|
597
601
|
second: "minute"
|
|
598
602
|
};
|
|
599
603
|
|
|
600
|
-
let res = `(date_trunc(${asValue(prevInt[unit] || "hour")}, ${col}) + date_part(${asValue(unit, "::text")}, ${col})::int / ${val} * interval ${asValue(val + " " + unit)})`;
|
|
604
|
+
let res = `(date_trunc(${asValue(prevInt[unit as "month"] || "hour")}, ${col}) + date_part(${asValue(unit, "::text")}, ${col})::int / ${val} * interval ${asValue(val + " " + unit)})`;
|
|
601
605
|
// console.log(res);
|
|
602
606
|
return res;
|
|
603
607
|
}
|
|
@@ -664,7 +668,7 @@ export const FUNCTIONS: FunctionSpec[] = [
|
|
|
664
668
|
} as FunctionSpec)),
|
|
665
669
|
|
|
666
670
|
/* Basic 1 arg col funcs */
|
|
667
|
-
...["upper", "lower", "length", "reverse", "trim", "initcap", "round", "ceil", "floor", "sign", "
|
|
671
|
+
...["upper", "lower", "length", "reverse", "trim", "initcap", "round", "ceil", "floor", "sign", "md5"].map(funcName => ({
|
|
668
672
|
name: "$" + funcName,
|
|
669
673
|
type: "function",
|
|
670
674
|
numArgs: 1,
|
|
@@ -675,6 +679,27 @@ export const FUNCTIONS: FunctionSpec[] = [
|
|
|
675
679
|
}
|
|
676
680
|
} as FunctionSpec)),
|
|
677
681
|
|
|
682
|
+
/* Interval funcs */
|
|
683
|
+
...["age", "difference"].map(funcName => ({
|
|
684
|
+
name: "$" + funcName,
|
|
685
|
+
type: "function",
|
|
686
|
+
numArgs: 1,
|
|
687
|
+
singleColArg: true,
|
|
688
|
+
getFields: (args: any[]) => args,
|
|
689
|
+
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
690
|
+
const validCols = args.filter(a => typeof a === "string").length
|
|
691
|
+
if(funcName === "difference" && validCols !== 2) throw new Error("Must have two column names")
|
|
692
|
+
if(![1,2].includes(validCols)) throw new Error("Must have one or two column names")
|
|
693
|
+
const [leftField, rightField] = args;
|
|
694
|
+
const leftQ = asNameAlias(leftField, tableAlias);
|
|
695
|
+
const rightQ = rightField? ("," + asNameAlias(rightField, tableAlias)) : "";
|
|
696
|
+
if(funcName === "age"){
|
|
697
|
+
return `${funcName}(${leftQ}, ${rightQ})`;
|
|
698
|
+
} else {
|
|
699
|
+
return `${leftQ} - ${rightQ}`;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
} as FunctionSpec)),
|
|
678
703
|
|
|
679
704
|
/* pgcrypto funcs */
|
|
680
705
|
...["crypt"].map(funcName => ({
|
|
@@ -714,7 +739,7 @@ export const FUNCTIONS: FunctionSpec[] = [
|
|
|
714
739
|
numArgs: 1,
|
|
715
740
|
minCols: 0,
|
|
716
741
|
singleColArg: false,
|
|
717
|
-
getFields: (args: any[]
|
|
742
|
+
getFields: (args: any[]) => [] as string[], // Fields not validated because we'll use the allowed ones anyway
|
|
718
743
|
getQuery: ({ allowedFields, args, tableAlias }) => {
|
|
719
744
|
let value = asValue(args[0]);
|
|
720
745
|
if(typeof value !== "string") throw "expecting string argument";
|
|
@@ -831,7 +856,7 @@ export const FUNCTIONS: FunctionSpec[] = [
|
|
|
831
856
|
let _cols = validCols.filter(c =>
|
|
832
857
|
/** Exclude numeric columns when the search tern contains a character */
|
|
833
858
|
!hasChars ||
|
|
834
|
-
postgresToTsType(c.colInfo
|
|
859
|
+
postgresToTsType(c.colInfo!.udt_name) !== "number"
|
|
835
860
|
);
|
|
836
861
|
|
|
837
862
|
/** This will break GROUP BY (non-integer constant in GROUP BY) */
|
|
@@ -1104,7 +1129,7 @@ export class SelectItemBuilder {
|
|
|
1104
1129
|
|
|
1105
1130
|
} else {
|
|
1106
1131
|
await Promise.all(selectKeys.map(async key => {
|
|
1107
|
-
const val = userSelect[key],
|
|
1132
|
+
const val: any = userSelect[key as keyof typeof userSelect],
|
|
1108
1133
|
throwErr = (extraErr: string = "") => {
|
|
1109
1134
|
console.trace(extraErr)
|
|
1110
1135
|
throw "Unexpected select -> " + JSON.stringify({ [key]: val }) + "\n" + extraErr;
|
|
@@ -1171,10 +1196,10 @@ export class SelectItemBuilder {
|
|
|
1171
1196
|
export async function getNewQuery(
|
|
1172
1197
|
_this: TableHandler,
|
|
1173
1198
|
filter: Filter,
|
|
1174
|
-
selectParams: SelectParams & { alias?: string },
|
|
1199
|
+
selectParams: (SelectParams & { alias?: string }) = {},
|
|
1175
1200
|
param3_unused = null,
|
|
1176
|
-
tableRules: TableRule,
|
|
1177
|
-
localParams: LocalParams,
|
|
1201
|
+
tableRules: TableRule | undefined,
|
|
1202
|
+
localParams: LocalParams | undefined,
|
|
1178
1203
|
columns: ColumnInfo[],
|
|
1179
1204
|
): Promise<NewQuery> {
|
|
1180
1205
|
|
|
@@ -1202,7 +1227,6 @@ export async function getNewQuery(
|
|
|
1202
1227
|
|
|
1203
1228
|
// const all_colnames = _this.column_names.slice(0).concat(COMPUTED_FIELDS.map(c => c.name));
|
|
1204
1229
|
|
|
1205
|
-
selectParams = selectParams || {};
|
|
1206
1230
|
const { select: userSelect = "*" } = selectParams,
|
|
1207
1231
|
// allCols = _this.column_names.slice(0),
|
|
1208
1232
|
// allFieldsIncludingComputed = allCols.concat(COMPUTED_FIELDS.map(c => c.name)),
|
|
@@ -1217,10 +1241,10 @@ export async function getNewQuery(
|
|
|
1217
1241
|
// console.log({ key, val })
|
|
1218
1242
|
let j_filter: Filter = {},
|
|
1219
1243
|
j_selectParams: SelectParams = {},
|
|
1220
|
-
j_path: string[],
|
|
1221
|
-
j_alias: string,
|
|
1222
|
-
j_tableRules: TableRule,
|
|
1223
|
-
j_table: string,
|
|
1244
|
+
j_path: string[] | undefined,
|
|
1245
|
+
j_alias: string | undefined,
|
|
1246
|
+
j_tableRules: TableRule | undefined,
|
|
1247
|
+
j_table: string | undefined,
|
|
1224
1248
|
j_isLeftJoin: boolean = true;
|
|
1225
1249
|
|
|
1226
1250
|
if(val === "*"){
|
|
@@ -1256,7 +1280,7 @@ export async function getNewQuery(
|
|
|
1256
1280
|
j_table = key;
|
|
1257
1281
|
}
|
|
1258
1282
|
}
|
|
1259
|
-
|
|
1283
|
+
if(!j_table) throw "j_table missing"
|
|
1260
1284
|
const _thisJoinedTable: any = _this.dboBuilder.dbo[j_table];
|
|
1261
1285
|
if(!_thisJoinedTable) {
|
|
1262
1286
|
throw `Joined table ${JSON.stringify(j_table)} is disallowed or inexistent \nOr you've forgot to put the function arguments into an array`;
|
|
@@ -1265,7 +1289,7 @@ export async function getNewQuery(
|
|
|
1265
1289
|
let isLocal = true;
|
|
1266
1290
|
if(localParams && (localParams.socket || localParams.httpReq)){
|
|
1267
1291
|
isLocal = false;
|
|
1268
|
-
j_tableRules = await _this.dboBuilder.publishParser
|
|
1292
|
+
j_tableRules = await _this.dboBuilder.publishParser?.getValidatedRequestRuleWusr({ tableName: j_table, command: "find", localParams });
|
|
1269
1293
|
}
|
|
1270
1294
|
|
|
1271
1295
|
if(isLocal || j_tableRules){
|
|
@@ -1319,7 +1343,7 @@ export async function getNewQuery(
|
|
|
1319
1343
|
where,
|
|
1320
1344
|
// having: cond.having,
|
|
1321
1345
|
limit: _this.prepareLimitQuery(selectParams.limit, p),
|
|
1322
|
-
orderBy: [_this.prepareSort(selectParams.orderBy, allowedFields, selectParams.alias,
|
|
1346
|
+
orderBy: [_this.prepareSort(selectParams.orderBy, allowedFields, selectParams.alias, undefined, select)],
|
|
1323
1347
|
offset: _this.prepareOffsetQuery(selectParams.offset)
|
|
1324
1348
|
} as NewQuery;
|
|
1325
1349
|
|
|
@@ -1336,19 +1360,19 @@ export function makeQuery(
|
|
|
1336
1360
|
q: NewQuery,
|
|
1337
1361
|
depth: number = 0,
|
|
1338
1362
|
joinFields: string[] = [],
|
|
1339
|
-
selectParams: SelectParams,
|
|
1363
|
+
selectParams: SelectParams = {},
|
|
1340
1364
|
): string {
|
|
1341
1365
|
const PREF = `prostgles`,
|
|
1342
1366
|
joins = q.joins || [],
|
|
1343
1367
|
// aggs = q.aggs || [],
|
|
1344
1368
|
makePref = (q: NewQuery) => !q.tableAlias? q.table : `${q.tableAlias || ""}_${q.table}`,
|
|
1345
|
-
makePrefANON = (joinAlias, table) => asName(!joinAlias? table : `${joinAlias || ""}_${table}`),
|
|
1369
|
+
makePrefANON = (joinAlias: string | undefined, table: string) => asName(!joinAlias? table : `${joinAlias || ""}_${table}`),
|
|
1346
1370
|
makePrefAN = (q: NewQuery) => asName(makePref(q));
|
|
1347
1371
|
|
|
1348
|
-
const indentLine = (numInd, str, indentStr = " ") => new Array(numInd).fill(indentStr).join("") + str;
|
|
1349
|
-
const indStr = (numInd, str: string) => str.split("\n").map(s => indentLine(numInd, s)).join("\n");
|
|
1350
|
-
const indjArr = (numInd, strArr: string[], indentStr = " "): string[] => strArr.map(str => indentLine(numInd, str) );
|
|
1351
|
-
const indJ = (numInd, strArr: string[], separator = " \n ", indentStr = " ") => indjArr(numInd, strArr, indentStr).join(separator);
|
|
1372
|
+
const indentLine = (numInd: number, str: string, indentStr = " ") => new Array(numInd).fill(indentStr).join("") + str;
|
|
1373
|
+
const indStr = (numInd: number, str: string) => str.split("\n").map(s => indentLine(numInd, s)).join("\n");
|
|
1374
|
+
const indjArr = (numInd: number, strArr: string[], indentStr = " "): string[] => strArr.map(str => indentLine(numInd, str) );
|
|
1375
|
+
const indJ = (numInd: number, strArr: string[], separator = " \n ", indentStr = " ") => indjArr(numInd, strArr, indentStr).join(separator);
|
|
1352
1376
|
const selectArrComma = (strArr: string[]): string[] => strArr.map((s, i, arr)=> s + (i < arr.length - 1? " , " : " "));
|
|
1353
1377
|
const prefJCAN = (q: NewQuery, str: string) => asName(`${q.tableAlias || q.table}_${PREF}_${str}`);
|
|
1354
1378
|
|
|
@@ -1357,7 +1381,7 @@ export function makeQuery(
|
|
|
1357
1381
|
const joinInfo = _this.getJoins(q1.table, q2.table, q2.$path, true);
|
|
1358
1382
|
const paths = joinInfo.paths;
|
|
1359
1383
|
|
|
1360
|
-
return
|
|
1384
|
+
return paths.flatMap(({ table, on }, i) => {
|
|
1361
1385
|
const getColName = (col: string, q: NewQuery) => {
|
|
1362
1386
|
if(table === q.table){
|
|
1363
1387
|
const colFromSelect = q.select.find(s => s.getQuery() === asName(col));
|
|
@@ -1404,7 +1428,7 @@ export function makeQuery(
|
|
|
1404
1428
|
/* Rename aggs to avoid collision with join cols */
|
|
1405
1429
|
if(s.type === "aggregation") return asName(`agg_${s.alias}`) + " AS " + asName(s.alias);
|
|
1406
1430
|
return asName(s.alias);
|
|
1407
|
-
}).concat(q2.joins
|
|
1431
|
+
}).concat(q2.joins?.map(j => asName(j.table)) ?? []).join(", ");
|
|
1408
1432
|
|
|
1409
1433
|
const _iiQ = makeQuery(
|
|
1410
1434
|
_this,
|
|
@@ -1441,7 +1465,7 @@ export function makeQuery(
|
|
|
1441
1465
|
}`
|
|
1442
1466
|
];
|
|
1443
1467
|
return jres;
|
|
1444
|
-
})
|
|
1468
|
+
});
|
|
1445
1469
|
}
|
|
1446
1470
|
|
|
1447
1471
|
const getGroupBy = (rootSelectItems: SelectItem[], groupByItems: SelectItem[]): string => {
|
|
@@ -1521,7 +1545,7 @@ export function makeQuery(
|
|
|
1521
1545
|
|
|
1522
1546
|
const rootSelectItems = q.select.filter(s => depth || s.selected)
|
|
1523
1547
|
|
|
1524
|
-
let rootGroupBy: string;
|
|
1548
|
+
let rootGroupBy: string | undefined;
|
|
1525
1549
|
if((selectParams.groupBy || aggs.length || q.joins && q.joins.length) && nonAggs.length){
|
|
1526
1550
|
// console.log({ aggs, nonAggs, joins: q.joins })
|
|
1527
1551
|
// rootGroupBy = getGroupBy(rootSelectItems, depth? rootSelectItems : nonAggs) + (aggs?.length? "" : ", ctid")
|
|
@@ -1585,7 +1609,7 @@ export function makeQuery(
|
|
|
1585
1609
|
, `${q.where} `
|
|
1586
1610
|
])
|
|
1587
1611
|
, `) ${makePrefAN(q)} `
|
|
1588
|
-
, ...
|
|
1612
|
+
, ...joins.flatMap((j, i)=> joinTables(q, j))
|
|
1589
1613
|
])
|
|
1590
1614
|
, ") t1"
|
|
1591
1615
|
])
|
package/lib/SyncReplication.ts
CHANGED
|
@@ -82,10 +82,10 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
82
82
|
throw `dbo.${table_name}.find or .count are missing or not allowed`;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const first_rows = await _this.dbo?.[table_name]?.find?.(_filter, { orderBy: (orderByAsc as OrderBy), select: sync_fields, limit, offset },
|
|
86
|
-
const last_rows = first_rows
|
|
85
|
+
const first_rows = await _this.dbo?.[table_name]?.find?.(_filter, { orderBy: (orderByAsc as OrderBy), select: sync_fields, limit, offset }, undefined, table_rules);
|
|
86
|
+
const last_rows = first_rows?.slice(-1);
|
|
87
87
|
// const last_rows = await _this?.dbo[table_name]?.find?.(_filter, { orderBy: (orderByDesc as OrderBy), select: sync_fields, limit: 1, offset: -offset || 0 }, null, table_rules);
|
|
88
|
-
const count = await _this.dbo?.[table_name]?.count?.(_filter,
|
|
88
|
+
const count = await _this.dbo?.[table_name]?.count?.(_filter, undefined, undefined, table_rules);
|
|
89
89
|
|
|
90
90
|
return { s_fr: first_rows?.[0] || null, s_lr: last_rows?.[0] || null, s_count: count }
|
|
91
91
|
},
|
|
@@ -146,7 +146,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
146
146
|
offset: offset || 0,
|
|
147
147
|
limit: batch_size
|
|
148
148
|
},
|
|
149
|
-
|
|
149
|
+
undefined,
|
|
150
150
|
table_rules
|
|
151
151
|
);
|
|
152
152
|
|
|
@@ -164,7 +164,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
164
164
|
return Promise.all(deleted.map(async d => {
|
|
165
165
|
const id_filter = filterObj(d, id_fields);
|
|
166
166
|
try {
|
|
167
|
-
await (_this.dbo[table_name] as TableHandler).delete(id_filter, undefined,
|
|
167
|
+
await (_this.dbo[table_name] as TableHandler).delete(id_filter, undefined, undefined, table_rules);
|
|
168
168
|
return 1;
|
|
169
169
|
} catch (e){
|
|
170
170
|
console.error(e)
|
|
@@ -195,7 +195,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
195
195
|
select: [synced_field, ...id_fields] ,
|
|
196
196
|
orderBy: (orderByAsc as OrderBy),
|
|
197
197
|
},
|
|
198
|
-
|
|
198
|
+
undefined,
|
|
199
199
|
table_rules
|
|
200
200
|
);
|
|
201
201
|
const inserts = data.filter(d => !existingData.find(ed => rowsIdsMatch(ed, d)));
|
|
@@ -216,7 +216,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
216
216
|
if(table_rules.insert && inserts.length){
|
|
217
217
|
// const qs = await tbl.insert(inserts, { fixIssues: true }, null, table_rules, { returnQuery: true });
|
|
218
218
|
// console.log("inserts", qs)
|
|
219
|
-
await tbl.insert(inserts, { fixIssues: true },
|
|
219
|
+
await tbl.insert(inserts, { fixIssues: true }, undefined, table_rules);
|
|
220
220
|
inserted = inserts.length;
|
|
221
221
|
}
|
|
222
222
|
|
|
@@ -308,7 +308,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
308
308
|
sync_fields.map(key => {
|
|
309
309
|
_filter[key] = c_lr[key];
|
|
310
310
|
});
|
|
311
|
-
server_row = await _this?.dbo?.[table_name]?.find?.(_filter, { select: sync_fields, limit: 1 },
|
|
311
|
+
server_row = await _this?.dbo?.[table_name]?.find?.(_filter, { select: sync_fields, limit: 1 }, undefined, table_rules);
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
// if(rowsFullyMatch(c_lr, s_lr)){ //c_count === s_count &&
|
|
@@ -337,7 +337,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
337
337
|
console.error({ syncIssue: "sync.lr[synced_field] is greater than lastRow[synced_field]"})
|
|
338
338
|
}
|
|
339
339
|
sync.lr = lastRow;
|
|
340
|
-
sync.last_synced = +sync.lr[synced_field];
|
|
340
|
+
sync.last_synced = +sync.lr?.[synced_field];
|
|
341
341
|
}
|
|
342
342
|
},
|
|
343
343
|
|
|
@@ -381,7 +381,7 @@ export const syncData = async (_this: PubSubManager, sync: SyncParams, clientDat
|
|
|
381
381
|
});
|
|
382
382
|
await Promise.all(to_delete.map(d => {
|
|
383
383
|
deleted++;
|
|
384
|
-
return (_this.dbo[table_name] as TableHandler).delete(filterObj(d, id_fields), { },
|
|
384
|
+
return (_this.dbo[table_name] as TableHandler).delete(filterObj(d, id_fields), { }, undefined, table_rules);
|
|
385
385
|
}));
|
|
386
386
|
sData = await getServerData(min_synced, offset);
|
|
387
387
|
}
|
package/lib/TableConfig.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnyObject, asName } from "prostgles-types";
|
|
2
|
-
import { DboBuilder, JoinInfo, LocalParams } from "./DboBuilder";
|
|
2
|
+
import { DboBuilder, getKeys, JoinInfo, LocalParams } from "./DboBuilder";
|
|
3
3
|
import { asSQLIdentifier, ALLOWED_EXTENSION, ALLOWED_CONTENT_TYPE } from "./FileManager";
|
|
4
4
|
import { DB, DbHandler, Prostgles } from "./Prostgles";
|
|
5
5
|
import { asValue } from "./PubSubManager";
|
|
@@ -184,9 +184,15 @@ export type TableConfig<LANG_IDS = { en: 1 }> = {
|
|
|
184
184
|
export default class TableConfigurator {
|
|
185
185
|
|
|
186
186
|
config?: TableConfig;
|
|
187
|
-
get dbo(): DbHandler {
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
get dbo(): DbHandler {
|
|
188
|
+
if(!this.prostgles.dbo) throw "this.prostgles.dbo missing"
|
|
189
|
+
return this.prostgles.dbo
|
|
190
|
+
};
|
|
191
|
+
get db(): DB {
|
|
192
|
+
if(!this.prostgles.db) throw "this.prostgles.db missing"
|
|
193
|
+
return this.prostgles.db
|
|
194
|
+
};
|
|
195
|
+
// sidKeyName: string;
|
|
190
196
|
prostgles: Prostgles
|
|
191
197
|
|
|
192
198
|
constructor(prostgles: Prostgles){
|
|
@@ -203,7 +209,7 @@ export default class TableConfigurator {
|
|
|
203
209
|
}
|
|
204
210
|
|
|
205
211
|
getColInfo = (params: {col: string, table: string}): ColExtraInfo | undefined => {
|
|
206
|
-
return this.config[params.table]?.[params.col]?.info;
|
|
212
|
+
return (this.config as any)[params.table]?.[params.col]?.info;
|
|
207
213
|
}
|
|
208
214
|
|
|
209
215
|
checkColVal = (params: {col: string, table: string, value: any }): void => {
|
|
@@ -218,6 +224,7 @@ export default class TableConfigurator {
|
|
|
218
224
|
|
|
219
225
|
getJoinInfo = (sourceTable: string, targetTable: string): JoinInfo | undefined => {
|
|
220
226
|
if(
|
|
227
|
+
this.config &&
|
|
221
228
|
sourceTable in this.config &&
|
|
222
229
|
this.config[sourceTable] &&
|
|
223
230
|
"columns" in this.config[sourceTable]
|
|
@@ -247,9 +254,10 @@ export default class TableConfigurator {
|
|
|
247
254
|
async init(){
|
|
248
255
|
let queries: string[] = [];
|
|
249
256
|
|
|
257
|
+
if(!this.config || !this.prostgles.pgp) throw "config or pgp missing"
|
|
250
258
|
/* Create lookup tables */
|
|
251
259
|
Object.keys(this.config).map(tableName => {
|
|
252
|
-
const tableConf = this.config[tableName];
|
|
260
|
+
const tableConf = this.config![tableName];
|
|
253
261
|
const { dropIfExists = false, dropIfExistsCascade = false } = tableConf;
|
|
254
262
|
if(dropIfExistsCascade){
|
|
255
263
|
queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
|
|
@@ -266,8 +274,8 @@ export default class TableConfigurator {
|
|
|
266
274
|
);`);
|
|
267
275
|
|
|
268
276
|
rows.map(row => {
|
|
269
|
-
const values = this.prostgles.pgp
|
|
270
|
-
queries.push(this.prostgles.pgp
|
|
277
|
+
const values = this.prostgles.pgp!.helpers.values(row)
|
|
278
|
+
queries.push(this.prostgles.pgp!.as.format(`INSERT INTO ${tableName} (${["id", ...keys].map(t => asName(t)).join(", ")}) ` + " VALUES ${values:raw} ;", { values} ))
|
|
271
279
|
});
|
|
272
280
|
// console.log("Created lookup table " + tableName)
|
|
273
281
|
}
|
|
@@ -284,7 +292,7 @@ export default class TableConfigurator {
|
|
|
284
292
|
|
|
285
293
|
/* Create referenced columns */
|
|
286
294
|
await Promise.all(Object.keys(this.config).map(async tableName => {
|
|
287
|
-
const tableConf = this.config[tableName];
|
|
295
|
+
const tableConf = this.config![tableName];
|
|
288
296
|
if("columns" in tableConf){
|
|
289
297
|
const getColDef = (name: string, colConf: ColumnConfig): string => {
|
|
290
298
|
const colNameEsc = asName(name);
|
|
@@ -318,13 +326,13 @@ export default class TableConfigurator {
|
|
|
318
326
|
}
|
|
319
327
|
}
|
|
320
328
|
|
|
321
|
-
const colDefs = [];
|
|
329
|
+
const colDefs: string[] = [];
|
|
322
330
|
Object.keys(tableConf.columns).filter(c => !("joinDef" in tableConf.columns[c])).map(colName => {
|
|
323
331
|
const colConf = tableConf.columns[colName];
|
|
324
332
|
|
|
325
333
|
if(!this.dbo[tableName]){
|
|
326
334
|
colDefs.push(getColDef(colName, colConf))
|
|
327
|
-
} else if(!colDefs.length && !this.dbo[tableName].columns
|
|
335
|
+
} else if(!colDefs.length && !this.dbo[tableName].columns?.find(c => colName === c.name)) {
|
|
328
336
|
|
|
329
337
|
if("references" in colConf && colConf.references){
|
|
330
338
|
|
|
@@ -354,13 +362,13 @@ export default class TableConfigurator {
|
|
|
354
362
|
}
|
|
355
363
|
}
|
|
356
364
|
if("constraints" in tableConf && tableConf.constraints){
|
|
357
|
-
|
|
358
|
-
queries.push(`ALTER TABLE ${asName(tableName)} ADD CONSTRAINT ${asName(constraintName)} ${tableConf.constraints[constraintName]} ;`);
|
|
365
|
+
getKeys(tableConf.constraints).map(constraintName => {
|
|
366
|
+
queries.push(`ALTER TABLE ${asName(tableName)} ADD CONSTRAINT ${asName(constraintName)} ${tableConf.constraints![constraintName]} ;`);
|
|
359
367
|
});
|
|
360
368
|
}
|
|
361
369
|
if("indexes" in tableConf && tableConf.indexes){
|
|
362
|
-
|
|
363
|
-
const { concurrently, unique, using, definition, replace } = tableConf.indexes[indexName];
|
|
370
|
+
getKeys(tableConf.indexes).map(indexName => {
|
|
371
|
+
const { concurrently, unique, using, definition, replace } = tableConf.indexes![indexName];
|
|
364
372
|
if(replace || typeof replace !== "boolean" && tableConf.replaceUniqueIndexes){
|
|
365
373
|
queries.push(`DROP INDEX IF EXISTS ${asName(indexName)} ;`);
|
|
366
374
|
}
|
package/lib/shortestPath.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { AnyObject } from "prostgles-types";
|
|
2
|
+
|
|
3
|
+
const shortestDistanceNode = (distances: AnyObject, visited: AnyObject) => {
|
|
2
4
|
let shortest = null;
|
|
3
5
|
|
|
4
6
|
for (let node in distances) {
|
|
@@ -16,18 +18,18 @@ export type Graph = {
|
|
|
16
18
|
|
|
17
19
|
export const findShortestPath = (graph: Graph, startNode: string, endNode: string): { distance: number, path: string[] } => {
|
|
18
20
|
// establish object for recording distances from the start node
|
|
19
|
-
let distances = {};
|
|
21
|
+
let distances: AnyObject = {};
|
|
20
22
|
distances[endNode] = "Infinity";
|
|
21
23
|
distances = Object.assign(distances, graph[startNode]);
|
|
22
24
|
|
|
23
25
|
// track paths
|
|
24
|
-
let parents = { endNode: null };
|
|
26
|
+
let parents: AnyObject = { endNode: null };
|
|
25
27
|
for (let child in graph[startNode]) {
|
|
26
28
|
parents[child] = startNode;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
// track nodes that have already been visited
|
|
30
|
-
let visited = [];
|
|
32
|
+
let visited: AnyObject = [];
|
|
31
33
|
|
|
32
34
|
// find the nearest node
|
|
33
35
|
let node = shortestDistanceNode(distances, visited);
|
package/lib/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { get } from "prostgles-types";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
export function isObject(obj: any){
|
|
4
|
+
export function isObject(obj: any): obj is Record<string, any> {
|
|
5
5
|
return Boolean(obj && typeof obj === "object" && !Array.isArray(obj) );
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
|
+
export const isDefined = <T>(v: T | undefined | void): v is T => v !== undefined && v !== null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prostgles-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.149",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,13 +29,14 @@
|
|
|
29
29
|
"bluebird": "^3.7.2",
|
|
30
30
|
"file-type": "^16.5.3",
|
|
31
31
|
"pg-promise": "^10.11.1",
|
|
32
|
-
"prostgles-types": "^1.5.
|
|
32
|
+
"prostgles-types": "^1.5.124",
|
|
33
33
|
"sharp": "^0.30.5"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@aws-sdk/types": "^3.34.0",
|
|
37
37
|
"@types/bluebird": "^3.5.36",
|
|
38
38
|
"@types/node": "^14.14.35",
|
|
39
|
-
"
|
|
39
|
+
"@types/sharp": "^0.30.2",
|
|
40
|
+
"typescript": "^4.7.2"
|
|
40
41
|
}
|
|
41
42
|
}
|
package/tests/client/PID.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
59576
|
package/tests/client/index.js
CHANGED
|
@@ -14,13 +14,16 @@ const log = (msg, extra) => {
|
|
|
14
14
|
log("Started client...");
|
|
15
15
|
const url = process.env.PRGL_CLIENT_URL || "http://127.0.0.1:3001", path = process.env.PRGL_CLIENT_PATH || "/teztz/s", socket = (0, socket_io_client_1.default)(url, { path, query: { token: "haha" } }), //
|
|
16
16
|
stopTest = (err) => {
|
|
17
|
-
|
|
18
|
-
log("Stopping client...");
|
|
19
|
-
if (err)
|
|
20
|
-
console.trace(err);
|
|
21
|
-
});
|
|
17
|
+
log("Stopping client due to error: " + JSON.stringify(err));
|
|
22
18
|
setTimeout(() => {
|
|
23
|
-
|
|
19
|
+
socket.emit("stop-test", !err ? err : { err: err.toString(), error: err }, cb => {
|
|
20
|
+
log("Stopping client...");
|
|
21
|
+
if (err)
|
|
22
|
+
console.trace(err);
|
|
23
|
+
});
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
process.exit(err ? 1 : 0);
|
|
26
|
+
}, 1000);
|
|
24
27
|
}, 1000);
|
|
25
28
|
};
|
|
26
29
|
try {
|
|
@@ -62,7 +65,7 @@ try {
|
|
|
62
65
|
catch (err) {
|
|
63
66
|
console.trace(err);
|
|
64
67
|
stopTest(err);
|
|
65
|
-
throw err;
|
|
68
|
+
// throw err;
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
});
|
package/tests/client/index.ts
CHANGED
|
@@ -15,15 +15,19 @@ const url = process.env.PRGL_CLIENT_URL || "http://127.0.0.1:3001",
|
|
|
15
15
|
path = process.env.PRGL_CLIENT_PATH || "/teztz/s",
|
|
16
16
|
socket = io(url, { path, query: { token: "haha" } }), //
|
|
17
17
|
stopTest = (err?) => {
|
|
18
|
-
|
|
18
|
+
log("Stopping client due to error: " + JSON.stringify(err));
|
|
19
19
|
|
|
20
|
-
log("Stopping client...");
|
|
21
|
-
if(err) console.trace(err);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
25
20
|
setTimeout(() => {
|
|
26
|
-
|
|
21
|
+
socket.emit("stop-test", !err? err : { err: err.toString(), error: err }, cb => {
|
|
22
|
+
|
|
23
|
+
log("Stopping client...");
|
|
24
|
+
if(err) console.trace(err);
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
});
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
process.exit(err? 1 : 0)
|
|
30
|
+
}, 1000);
|
|
27
31
|
}, 1000);
|
|
28
32
|
|
|
29
33
|
};
|
|
@@ -70,7 +74,7 @@ try {
|
|
|
70
74
|
} catch (err){
|
|
71
75
|
console.trace(err)
|
|
72
76
|
stopTest(err);
|
|
73
|
-
throw err;
|
|
77
|
+
// throw err;
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
});
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/node": "^14.14.16",
|
|
13
13
|
"@types/socket.io-client": "^1.4.35",
|
|
14
|
-
"prostgles-client": "^1.5.
|
|
14
|
+
"prostgles-client": "^1.5.138",
|
|
15
15
|
"prostgles-types": "^1.5.68",
|
|
16
|
-
"socket.io-client": "^4.5.
|
|
16
|
+
"socket.io-client": "^4.5.1"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"node_modules/@socket.io/component-emitter": {
|
|
@@ -73,9 +73,9 @@
|
|
|
73
73
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
74
74
|
},
|
|
75
75
|
"node_modules/prostgles-client": {
|
|
76
|
-
"version": "1.5.
|
|
77
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.
|
|
78
|
-
"integrity": "sha512
|
|
76
|
+
"version": "1.5.138",
|
|
77
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.138.tgz",
|
|
78
|
+
"integrity": "sha512-+xuu1erZ9mReRyGlTYLEvF0kB6VniVerXUW2ib/wRRBokBxKVKa5lB8cfZznP+Ch+U51gzzCIZzEVNlYSwy/cw==",
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"prostgles-types": "^1.5.123"
|
|
81
81
|
}
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
"integrity": "sha512-BL5I7lc8eqTa6z3SH5Z9g/1g1H+crlDoBCPH8zVEDBK3y5xMIiCW3SOYRZQfPfRM1lYnW4ljWzx3Cb2x9D1Ofg=="
|
|
87
87
|
},
|
|
88
88
|
"node_modules/socket.io-client": {
|
|
89
|
-
"version": "4.5.
|
|
90
|
-
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.
|
|
91
|
-
"integrity": "sha512-
|
|
89
|
+
"version": "4.5.1",
|
|
90
|
+
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
|
91
|
+
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
|
92
92
|
"dependencies": {
|
|
93
93
|
"@socket.io/component-emitter": "~3.1.0",
|
|
94
94
|
"debug": "~4.3.2",
|
|
@@ -187,9 +187,9 @@
|
|
|
187
187
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
|
188
188
|
},
|
|
189
189
|
"prostgles-client": {
|
|
190
|
-
"version": "1.5.
|
|
191
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.
|
|
192
|
-
"integrity": "sha512
|
|
190
|
+
"version": "1.5.138",
|
|
191
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.138.tgz",
|
|
192
|
+
"integrity": "sha512-+xuu1erZ9mReRyGlTYLEvF0kB6VniVerXUW2ib/wRRBokBxKVKa5lB8cfZznP+Ch+U51gzzCIZzEVNlYSwy/cw==",
|
|
193
193
|
"requires": {
|
|
194
194
|
"prostgles-types": "^1.5.123"
|
|
195
195
|
}
|
|
@@ -200,9 +200,9 @@
|
|
|
200
200
|
"integrity": "sha512-BL5I7lc8eqTa6z3SH5Z9g/1g1H+crlDoBCPH8zVEDBK3y5xMIiCW3SOYRZQfPfRM1lYnW4ljWzx3Cb2x9D1Ofg=="
|
|
201
201
|
},
|
|
202
202
|
"socket.io-client": {
|
|
203
|
-
"version": "4.5.
|
|
204
|
-
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.
|
|
205
|
-
"integrity": "sha512-
|
|
203
|
+
"version": "4.5.1",
|
|
204
|
+
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
|
205
|
+
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
|
206
206
|
"requires": {
|
|
207
207
|
"@socket.io/component-emitter": "~3.1.0",
|
|
208
208
|
"debug": "~4.3.2",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@types/node": "^14.14.16",
|
|
16
16
|
"@types/socket.io-client": "^1.4.35",
|
|
17
|
-
"prostgles-client": "^1.5.
|
|
17
|
+
"prostgles-client": "^1.5.138",
|
|
18
18
|
"prostgles-types": "^1.5.68",
|
|
19
|
-
"socket.io-client": "^4.5.
|
|
19
|
+
"socket.io-client": "^4.5.1"
|
|
20
20
|
}
|
|
21
21
|
}
|