prostgles-server 2.0.144 → 2.0.147

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/AuthHandler.d.ts +15 -13
  2. package/dist/AuthHandler.d.ts.map +1 -1
  3. package/dist/AuthHandler.js +41 -43
  4. package/dist/AuthHandler.js.map +1 -1
  5. package/dist/DBEventsManager.d.ts +6 -5
  6. package/dist/DBEventsManager.d.ts.map +1 -1
  7. package/dist/DBEventsManager.js +8 -2
  8. package/dist/DBEventsManager.js.map +1 -1
  9. package/dist/DboBuilder.d.ts +62 -50
  10. package/dist/DboBuilder.d.ts.map +1 -1
  11. package/dist/DboBuilder.js +229 -170
  12. package/dist/DboBuilder.js.map +1 -1
  13. package/dist/FileManager.d.ts +5 -5
  14. package/dist/FileManager.d.ts.map +1 -1
  15. package/dist/FileManager.js +48 -21
  16. package/dist/FileManager.js.map +1 -1
  17. package/dist/Filtering.d.ts.map +1 -1
  18. package/dist/Filtering.js +11 -9
  19. package/dist/Filtering.js.map +1 -1
  20. package/dist/PostgresNotifListenManager.d.ts +3 -3
  21. package/dist/PostgresNotifListenManager.d.ts.map +1 -1
  22. package/dist/PostgresNotifListenManager.js +7 -5
  23. package/dist/PostgresNotifListenManager.js.map +1 -1
  24. package/dist/Prostgles.d.ts +6 -9
  25. package/dist/Prostgles.d.ts.map +1 -1
  26. package/dist/Prostgles.js +122 -83
  27. package/dist/Prostgles.js.map +1 -1
  28. package/dist/PubSubManager.d.ts +9 -9
  29. package/dist/PubSubManager.d.ts.map +1 -1
  30. package/dist/PubSubManager.js +10 -9
  31. package/dist/PubSubManager.js.map +1 -1
  32. package/dist/QueryBuilder.d.ts +26 -8
  33. package/dist/QueryBuilder.d.ts.map +1 -1
  34. package/dist/QueryBuilder.js +114 -46
  35. package/dist/QueryBuilder.js.map +1 -1
  36. package/dist/SyncReplication.d.ts +1 -1
  37. package/dist/SyncReplication.d.ts.map +1 -1
  38. package/dist/SyncReplication.js +31 -29
  39. package/dist/SyncReplication.js.map +1 -1
  40. package/dist/TableConfig.d.ts +0 -1
  41. package/dist/TableConfig.d.ts.map +1 -1
  42. package/dist/TableConfig.js +25 -17
  43. package/dist/TableConfig.js.map +1 -1
  44. package/dist/shortestPath.d.ts.map +1 -1
  45. package/dist/shortestPath.js.map +1 -1
  46. package/dist/utils.d.ts +2 -0
  47. package/dist/utils.d.ts.map +1 -1
  48. package/dist/utils.js +6 -0
  49. package/dist/utils.js.map +1 -1
  50. package/lib/AuthHandler.ts +50 -40
  51. package/lib/DBEventsManager.ts +14 -7
  52. package/lib/DboBuilder.ts +265 -199
  53. package/lib/FileManager.ts +30 -21
  54. package/lib/Filtering.ts +19 -16
  55. package/lib/PostgresNotifListenManager.ts +11 -10
  56. package/lib/Prostgles.ts +89 -73
  57. package/lib/PubSubManager.ts +13 -11
  58. package/lib/QueryBuilder.ts +135 -54
  59. package/lib/SyncReplication.ts +10 -10
  60. package/lib/TableConfig.ts +23 -15
  61. package/lib/shortestPath.ts +6 -4
  62. package/lib/utils.ts +7 -1
  63. package/package.json +7 -8
  64. package/tests/client/PID.txt +1 -1
  65. package/tests/client/index.js +10 -7
  66. package/tests/client/index.ts +12 -8
  67. package/tests/client/package-lock.json +14 -14
  68. package/tests/client/package.json +2 -2
  69. package/tests/client/tsconfig.json +2 -2
  70. package/tests/client_only_queries.js +127 -104
  71. package/tests/client_only_queries.ts +43 -17
  72. package/tests/isomorphic_queries.js +44 -6
  73. package/tests/isomorphic_queries.ts +42 -6
  74. package/tests/server/package-lock.json +27 -29
  75. package/tests/server/package.json +2 -2
  76. package/tests/server/tsconfig.json +2 -2
  77. package/tsconfig.json +3 -2
@@ -8,7 +8,7 @@ import * as sharp from "sharp";
8
8
 
9
9
  import { DB, DbHandler, Prostgles } from './Prostgles';
10
10
  import { asName, AnyObject } from 'prostgles-types';
11
- import { TableHandler } from './DboBuilder';
11
+ import { getKeys, TableHandler } from './DboBuilder';
12
12
 
13
13
  const HOUR = 3600 * 1000;
14
14
 
@@ -65,18 +65,24 @@ export type UploadedItem = {
65
65
 
66
66
  export default class FileManager {
67
67
 
68
- s3Client: S3;
68
+ s3Client?: S3;
69
69
 
70
70
  config: S3Config | LocalConfig;
71
- imageOptions: ImageOptions;
72
-
73
- prostgles: Prostgles;
74
- get dbo(): DbHandler { return this.prostgles.dbo };
75
- get db(): DB { return this.prostgles.db };
71
+ imageOptions?: ImageOptions;
72
+
73
+ prostgles?: Prostgles;
74
+ get dbo(): DbHandler {
75
+ if(!this.prostgles?.dbo) throw "this.prostgles.dbo missing"
76
+ return this.prostgles.dbo
77
+ };
78
+ get db(): DB {
79
+ if(!this.prostgles?.db) throw "this.prostgles.db missing"
80
+ return this.prostgles.db
81
+ };
76
82
 
77
- tableName: string;
83
+ tableName?: string;
78
84
 
79
- private fileRoute: string;
85
+ private fileRoute?: string;
80
86
 
81
87
  constructor(config: FileManager["config"], imageOptions?: ImageOptions){
82
88
  this.config = config;
@@ -106,7 +112,7 @@ export default class FileManager {
106
112
  const nameParts = fileName.split(".");
107
113
 
108
114
  const nameExt = nameParts[nameParts.length - 1].toLowerCase(),
109
- mime = Object.keys(CONTENT_TYPE_TO_EXT).find(k => CONTENT_TYPE_TO_EXT[k].includes(nameExt));
115
+ mime = getKeys(CONTENT_TYPE_TO_EXT).find(k => (CONTENT_TYPE_TO_EXT[k] as readonly string[]).includes(nameExt));
110
116
 
111
117
  let type = {
112
118
  fileName,
@@ -119,17 +125,17 @@ export default class FileManager {
119
125
  if(!mime){
120
126
  /* Set correct/missing extension */
121
127
  if(["xml", "txt", "csv", "tsv", "doc"].includes(nameExt)){
122
- type = { ...type, mime: "text/" + nameExt, ext: nameExt };
128
+ type = { ...type, mime: ("text/" + nameExt) as any, ext: nameExt };
123
129
  } else if(["svg"].includes(nameExt)){
124
130
  type = { ...type, mime: "image/svg+xml", ext: nameExt };
125
131
  } else if(Buffer.isBuffer(file)){
126
- const res = await FileType.fromBuffer(file);
132
+ const res: any = await FileType.fromBuffer(file);
127
133
  type = {
128
134
  ...res,
129
135
  fileName,
130
136
  }
131
137
  } else if(typeof file === "string"){
132
- const res = await FileType.fromFile(file);
138
+ const res: any = await FileType.fromFile(file);
133
139
  type = {
134
140
  ...res,
135
141
  fileName,
@@ -158,10 +164,12 @@ export default class FileManager {
158
164
  if(nameExt !== ext) fileName = nameParts.slice(0, -1).join('') + "." + ext;
159
165
  }
160
166
 
161
- return {
167
+ const res = {
162
168
  ...type,
163
169
  fileName
164
170
  }
171
+ if(!res.mime) throw "Could not find mime"
172
+ return res as any;
165
173
  }
166
174
 
167
175
  // async getUploadURL(fileName: string): Promise<string> {
@@ -227,7 +235,7 @@ export default class FileManager {
227
235
  ContentType: mime,
228
236
  Body: file
229
237
  };
230
- this.s3Client.upload(params, (err, res: ManagedUpload.SendData) => {
238
+ this.s3Client.upload(params, (err: any, res: ManagedUpload.SendData) => {
231
239
 
232
240
  if(err){
233
241
  reject("Something went wrong");
@@ -279,8 +287,8 @@ export default class FileManager {
279
287
  }
280
288
  }
281
289
  _data = await sharp(data)
282
- .resize(opts)
283
- .withMetadata(Boolean(imageOptions.keepMetadata))
290
+ .resize(opts as any)
291
+ .withMetadata(Boolean(imageOptions?.keepMetadata) as any)
284
292
  // .jpeg({ quality: 80 })
285
293
  .toBuffer()
286
294
  } else if(!imageOptions?.keepMetadata) {
@@ -304,10 +312,10 @@ export default class FileManager {
304
312
  Key: fileName,
305
313
  Expires: expiresInSeconds || 30 * 60
306
314
  };
307
- return await this.s3Client.getSignedUrlPromise("getObject", params);
315
+ return await this.s3Client?.getSignedUrlPromise("getObject", params);
308
316
  }
309
317
 
310
- private parseSQLIdentifier = async (name: string ) => asSQLIdentifier(name, this.prostgles.db);// this.prostgles.dbo.sql<"value">("select format('%I', $1)", [name], { returnType: "value" } )
318
+ private parseSQLIdentifier = async (name: string ) => asSQLIdentifier(name, this.prostgles!.db!);// this.prostgles.dbo.sql<"value">("select format('%I', $1)", [name], { returnType: "value" } )
311
319
 
312
320
  init = async (prg: Prostgles) => {
313
321
  this.prostgles = prg;
@@ -315,6 +323,7 @@ export default class FileManager {
315
323
  // const { dbo, db, opts } = prg;
316
324
 
317
325
  const { fileTable } = prg.opts;
326
+ if(!fileTable) throw "fileTable missing";
318
327
  const { tableName = "media", referencedTables = {} } = fileTable;
319
328
  this.tableName = tableName;
320
329
 
@@ -376,7 +385,7 @@ export default class FileManager {
376
385
  console.log(`Created ${action}`);
377
386
 
378
387
  } else {
379
- const cols = await this.dbo[lookupTableName].getColumns();
388
+ const cols = await this.dbo[lookupTableName].getColumns!();
380
389
  const badCols = cols.filter(c => !c.references);
381
390
  await Promise.all(badCols.map(async badCol => {
382
391
  console.error(
@@ -436,7 +445,7 @@ export default class FileManager {
436
445
  const { name } = req.params;
437
446
  if(typeof name !== "string" || !name) throw "Invalid media name";
438
447
 
439
- const media = await mediaTable.findOne({ name }, { select: { id: 1, name: 1, signed_url: 1, signed_url_expires: 1, content_type: 1 } }, { httpReq: req });
448
+ const media = await mediaTable.findOne({ name }, { select: { id: 1, name: 1, signed_url: 1, signed_url_expires: 1, content_type: 1 } }, { httpReq: req } as any);
440
449
 
441
450
  if(!media) {
442
451
  /**
package/lib/Filtering.ts CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { SelectItem } from "./QueryBuilder";
4
4
  import { isEmpty, FullFilter, EXISTS_KEYS, FilterDataType, GeomFilterKeys, GeomFilter_Funcs, TextFilter_FullTextSearchFilterKeys } from "prostgles-types";
5
- import { isPlainObject } from "./DboBuilder";
5
+ import { getKeys, isPlainObject } from "./DboBuilder";
6
6
 
7
7
  /**
8
8
  * Parse a single filter
@@ -17,9 +17,9 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
17
17
  const mErr = (msg: string) => {
18
18
  throw `${msg}: ${JSON.stringify(_f, null, 2)}`
19
19
  },
20
- asValue = (v) => pgp.as.format("$1", [v]);
20
+ asValue = (v: any) => pgp.as.format("$1", [v]);
21
21
 
22
- const fKeys = Object.keys(_f)
22
+ const fKeys = getKeys(_f)
23
23
  if(fKeys.length === 0){
24
24
  return "";
25
25
  } else if(fKeys.length > 1){
@@ -33,7 +33,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
33
33
  .join(" AND ")
34
34
  }
35
35
 
36
- const fKey = fKeys[0];
36
+ const fKey: string = fKeys[0];
37
37
 
38
38
  /* Exists filter */
39
39
  if(EXISTS_KEYS.find(k => k in _f)){
@@ -42,17 +42,17 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
42
42
 
43
43
  let selItem: SelectItem | undefined;
44
44
  if(select) selItem = select.find(s => fKey === s.alias);
45
- let rightF: FilterDataType = _f[fKey];
45
+ let rightF: FilterDataType = (_f as any)[fKey];
46
46
 
47
47
  const getLeftQ = (selItm: SelectItem) => {
48
- if(selItm.type === "function") return selItem.getQuery();
49
- return selItem.getQuery(tableAlias);
48
+ if(selItm.type === "function") return selItm.getQuery();
49
+ return selItm.getQuery(tableAlias);
50
50
  }
51
51
 
52
52
  /**
53
53
  * Parsed left side of the query
54
54
  */
55
- let leftQ: string;// = asName(selItem.alias);
55
+ let leftQ: string | undefined;// = asName(selItem.alias);
56
56
 
57
57
  /* Check if string notation. Build obj if necessary */
58
58
  const dot_notation_delims = ["->", "."];
@@ -65,7 +65,10 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
65
65
  dot_notation_delims.find(dn => fKey.slice(s.alias.length).startsWith(dn))
66
66
  );
67
67
  }
68
- if(!selItem) mErr("Bad filter. Could not match to a column or alias: ");
68
+ if(!selItem) {
69
+ mErr("Bad filter. Could not match to a column or alias: ");
70
+ throw " "
71
+ }
69
72
  const remainingStr = fKey.slice(selItem.alias.length);
70
73
 
71
74
  /* Is json path spec */
@@ -135,7 +138,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
135
138
  }
136
139
 
137
140
  const key = remainingStr.slice(currIdx + 1, nIdx);
138
- curObj[key] = nextIdx > -1? {} : _f[fKey];
141
+ curObj[key] = nextIdx > -1? {} : (_f as any)[fKey];
139
142
  curObj = curObj[key];
140
143
 
141
144
  currIdx = nextIdx;
@@ -155,7 +158,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
155
158
 
156
159
  /* Matching sel item */
157
160
  if(isPlainObject(rightF)){
158
- const parseRightVal = (val, expect: "csv" | "array" | null = null) => {
161
+ const parseRightVal = (val: any, expect: "csv" | "array" | null = null) => {
159
162
  const checkIfArr = () => {
160
163
  if(!Array.isArray(val)) return mErr("This type of filter/column expects an Array of items");
161
164
  }
@@ -177,7 +180,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
177
180
 
178
181
  const fOpType = filterKeys[0];
179
182
  const fVal = rightF[fOpType];
180
- let sOpType: string;
183
+ let sOpType: string | undefined;
181
184
  let sVal: any;
182
185
 
183
186
  if(fVal && isPlainObject(fVal)){
@@ -227,7 +230,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
227
230
  return " FALSE ";
228
231
  }
229
232
 
230
- let _fVal: any[] = fVal.filter(v => v !== null);
233
+ let _fVal: any[] = fVal.filter((v: any) => v !== null);
231
234
  let c1 = "", c2 = "";
232
235
  if(_fVal.length) c1 = leftQ + " IN " + parseRightVal(_fVal, "csv");
233
236
  if(fVal.includes(null)) c2 = ` ${leftQ} IS NULL `;
@@ -238,7 +241,7 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
238
241
  return " TRUE ";
239
242
  }
240
243
 
241
- let _fVal: any[] = fVal.filter(v => v !== null);
244
+ let _fVal: any[] = fVal.filter((v: any) => v !== null);
242
245
  let c1 = "", c2 = "";
243
246
  if(_fVal.length) c1 = leftQ + " NOT IN " + parseRightVal(_fVal, "csv");
244
247
  if(fVal.includes(null)) c2 = ` ${leftQ} IS NOT NULL `;
@@ -274,9 +277,9 @@ export const parseFilterItem = (args: ParseFilterItemArgs): string => {
274
277
  return leftQ + operand + parseRightVal(fVal, "array");
275
278
 
276
279
  /* FTSQuery */
277
- } else if(["@@"].includes(fOpType) && TextFilter_FullTextSearchFilterKeys.includes(sOpType)) {
280
+ } else if(["@@"].includes(fOpType) && TextFilter_FullTextSearchFilterKeys.includes(sOpType!)) {
278
281
  let lq = `to_tsvector(${leftQ}::text)`;
279
- if(selItem && selItem.columnPGDataType === "tsvector") lq = leftQ;
282
+ if(selItem && selItem.columnPGDataType === "tsvector") lq = leftQ!;
280
283
 
281
284
  let res = `${lq} ${operand} ` + `${sOpType}${parseRightVal(sVal, "csv")}`;
282
285
 
@@ -9,14 +9,14 @@ import pgPromise from "pg-promise";
9
9
 
10
10
  export type PrglNotifListener = (args: { length: number; processId: number; channel: string; payload: string; name: string; }) => void;
11
11
  export class PostgresNotifListenManager {
12
- connection: pgPromise.IConnected<{}, pg.IClient>;
12
+ connection?: pgPromise.IConnected<{}, pg.IClient>;
13
13
  db_pg: DB;
14
14
  notifListener: PrglNotifListener;
15
15
  db_channel_name: string;
16
16
  isListening: any;
17
17
  client: any;
18
18
 
19
- static create = (db_pg, notifListener: PrglNotifListener, db_channel_name: string): Promise<PostgresNotifListenManager> => {
19
+ static create = (db_pg: DB, notifListener: PrglNotifListener, db_channel_name: string): Promise<PostgresNotifListenManager> => {
20
20
  let res = new PostgresNotifListenManager(db_pg, notifListener, db_channel_name, true);
21
21
  return res.init();
22
22
  }
@@ -32,7 +32,7 @@ export class PostgresNotifListenManager {
32
32
 
33
33
  async init(): Promise<PostgresNotifListenManager> {
34
34
 
35
- this.connection = null;
35
+ this.connection = undefined;
36
36
 
37
37
  this.isListening = await this.startListening();
38
38
  return this;
@@ -84,26 +84,27 @@ export class PostgresNotifListenManager {
84
84
  }
85
85
  }
86
86
 
87
- reconnect(delay = null, maxAttempts = null) {
87
+ reconnect(delay: number | undefined = 0, maxAttempts: number | undefined = 0) {
88
88
  if(!this.db_pg || !this.notifListener) throw "db_pg OR notifListener missing";
89
89
 
90
- delay = delay > 0 ? parseInt(delay) : 0;
91
- maxAttempts = maxAttempts > 0 ? parseInt(maxAttempts) : 1;
90
+ delay = delay > 0 ? parseInt(delay + "") : 0;
91
+ maxAttempts = maxAttempts > 0 ? parseInt(maxAttempts + "") : 1;
92
92
 
93
- const setListeners = (client, notifListener, db_channel_name) => {
93
+ const setListeners = (client: pg.IClient, notifListener: PrglNotifListener, db_channel_name: string) => {
94
94
  client.on('notification', notifListener);
95
95
  this.client = client;
96
+ if(!this.connection) throw "Connection missing";
96
97
  return this.connection.none('LISTEN $1~', db_channel_name)
97
98
  .catch(error => {
98
99
  console.log("PostgresNotifListenManager: unexpected error: ", error); // unlikely to ever happen
99
100
  });
100
101
  },
101
- removeListeners = (client) => {
102
+ removeListeners = (client: pg.IClient) => {
102
103
  client.removeListener('notification', this.notifListener);
103
104
  },
104
- onConnectionLost = (err, e) => {
105
+ onConnectionLost = (err: any, e: pgPromise.ILostContext<pg.IClient>) => {
105
106
  console.log('PostgresNotifListenManager: Connectivity Problem:', err);
106
- this.connection = null; // prevent use of the broken connection
107
+ this.connection = undefined; // prevent use of the broken connection
107
108
  removeListeners(e.client);
108
109
  this.reconnect(5000, 10) // retry 10 times, with 5-second intervals
109
110
  .then(() => {