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
@@ -12,9 +12,11 @@ type AuthSocketSchema = {
12
12
 
13
13
  type ExpressReq = {
14
14
  body?: AnyObject;
15
+ query?: AnyObject;
15
16
  cookies?: AnyObject;
16
17
  params?: AnyObject;
17
18
  path: string;
19
+ originalUrl: string;
18
20
  }
19
21
  type ExpressRes = {
20
22
  status: (code: number) => ({ json: (response: AnyObject) => any; });
@@ -104,22 +106,22 @@ export type Auth<DBO = DbHandler> = {
104
106
  /**
105
107
  * User data used on server. Mainly used in http request auth
106
108
  */
107
- getUser: (sid: string, dbo: DBO, db: DB, client: AuthClientRequest) => Promise<AnyObject | null | undefined>;
109
+ getUser: (sid: string | undefined, dbo: DBO, db: DB, client: AuthClientRequest) => Promise<AnyObject | undefined> | AnyObject | undefined;
108
110
 
109
111
  /**
110
112
  * User data sent to client. Mainly used in socket request auth
111
113
  */
112
- getClientUser: (sid: string, dbo: DBO, db: DB) => Promise<AnyObject | null | undefined>;
114
+ getClientUser: (sid: string, dbo: DBO, db: DB) => Promise<AnyObject | undefined> | AnyObject | undefined;
113
115
 
114
- register?: (params: AnyObject, dbo: DBO, db: DB) => Promise<BasicSession>;
115
- login?: (params: AnyObject, dbo: DBO, db: DB) => Promise<BasicSession>;
116
- logout?: (sid: string, dbo: DBO, db: DB) => Promise<any>;
116
+ register?: (params: AnyObject, dbo: DBO, db: DB) => Promise<BasicSession> | BasicSession;
117
+ login?: (params: AnyObject, dbo: DBO, db: DB) => Promise<BasicSession> | BasicSession;
118
+ logout?: (sid: string | undefined, dbo: DBO, db: DB) => Promise<any>;
117
119
 
118
120
  /**
119
121
  * If provided then then session info will be saved on socket.__prglCache and reused from there
120
122
  */
121
123
  cacheSession?: {
122
- getSession: (sid: string, dbo: DBO, db: DB) => Promise<BasicSession>
124
+ getSession: (sid: string | undefined, dbo: DBO, db: DB) => Promise<BasicSession>
123
125
  }
124
126
  }
125
127
 
@@ -133,8 +135,8 @@ export default class AuthHandler {
133
135
  protected opts?: Auth;
134
136
  dbo: DbHandler;
135
137
  db: DB;
136
- sidKeyName: string;
137
- returnURL: string;
138
+ sidKeyName?: string;
139
+ returnURL?: string;
138
140
 
139
141
  loginRoute?: string;
140
142
  logoutGetPath?: string;
@@ -146,17 +148,18 @@ export default class AuthHandler {
146
148
  this.loginRoute = prostgles.opts.auth?.expressConfig?.loginRoute || "/login";
147
149
  this.logoutGetPath = prostgles.opts.auth?.expressConfig?.logoutGetPath || "/logout";
148
150
  }
151
+ if(!prostgles.dbo || !prostgles.db) throw "dbo or db missing";
149
152
  this.dbo = prostgles.dbo;
150
153
  this.db = prostgles.db;
151
154
  }
152
155
 
153
- validateSid = (sid: string) => {
156
+ validateSid = (sid: string | undefined) => {
154
157
  if (!sid) return undefined;
155
158
  if (typeof sid !== "string") throw "sid missing or not a string";
156
159
  return sid;
157
160
  }
158
161
 
159
- matchesRoute = (route: string, clientFullRoute: string) => {
162
+ matchesRoute = (route: string | undefined, clientFullRoute: string) => {
160
163
  return route && clientFullRoute && (
161
164
  route === clientFullRoute ||
162
165
  clientFullRoute.startsWith(route) && ["/", "?", "#"].includes(clientFullRoute.slice(-1))
@@ -190,6 +193,7 @@ export default class AuthHandler {
190
193
  }
191
194
  const cookieOpts = { ...options, secure: true, sameSite: "strict", ...(this.opts?.expressConfig?.cookieOptions || {}) };
192
195
  const cookieData = sid;
196
+ if(!this.sidKeyName || !this.returnURL) throw "sidKeyName or returnURL missing"
193
197
  res.cookie(this.sidKeyName, cookieData, cookieOpts);
194
198
  const successURL = getReturnUrl(req, this.returnURL) || "/";
195
199
  res.redirect(successURL);
@@ -199,14 +203,15 @@ export default class AuthHandler {
199
203
  }
200
204
  }
201
205
 
202
- getUser = async (clientReq: AuthClientRequest): Promise<AnyObject> => {
206
+ getUser = async (clientReq: AuthClientRequest): Promise<AnyObject | undefined> => {
207
+ if(!this.sidKeyName || !this.opts?.getUser) throw "sidKeyName or this.opts.getUser missing"
203
208
  const sid = "httpReq" in clientReq? clientReq.httpReq?.cookies?.[this.sidKeyName] : clientReq.socket
204
209
  if (!sid) return undefined;
205
210
 
206
211
  try {
207
- return this.throttledFunc(() => {
212
+ return this.throttledFunc(async () => {
208
213
 
209
- return this.opts.getUser(this.validateSid(sid), this.dbo, this.db, clientReq);
214
+ return this.opts!.getUser(this.validateSid(sid), this.dbo, this.db, clientReq);
210
215
  }, 50)
211
216
  } catch (err) {
212
217
  console.error(err);
@@ -240,8 +245,8 @@ export default class AuthHandler {
240
245
  if (app && magicLinks) {
241
246
  const { route = "/magic-link", check } = magicLinks;
242
247
  if (!check) throw "Check must be defined for magicLinks";
243
- app.get(`${route}/:id`, async (req, res) => {
244
- const { id } = req.params;
248
+ app.get(`${route}/:id`, async (req: ExpressReq, res: ExpressRes) => {
249
+ const { id } = req.params ?? {};
245
250
 
246
251
  if (typeof id !== "string" || !id) {
247
252
  res.status(404).json({ msg: "Invalid magic-link id. Expecting a string" });
@@ -285,14 +290,14 @@ export default class AuthHandler {
285
290
 
286
291
  });
287
292
 
288
- if (app && this.logoutGetPath) {
293
+ if (app && this.logoutGetPath && this.opts.logout) {
289
294
  app.get(this.logoutGetPath, async (req: ExpressReq, res: ExpressRes) => {
290
295
  const sid = this.validateSid(req?.cookies?.[sidKeyName]);
291
296
  if (sid) {
292
297
  try {
293
298
  await this.throttledFunc(() => {
294
299
 
295
- return this.opts.logout(req?.cookies?.[sidKeyName], this.dbo as any, this.db);
300
+ return this.opts!.logout!(req?.cookies?.[sidKeyName], this.dbo as any, this.db);
296
301
  })
297
302
  } catch (err) {
298
303
  console.error(err);
@@ -305,7 +310,7 @@ export default class AuthHandler {
305
310
  if (app && Array.isArray(publicRoutes)) {
306
311
 
307
312
  /* Redirect if not logged in and requesting non public content */
308
- app.get('*', async (req, res) => {
313
+ app.get('*', async (req: ExpressReq, res: ExpressRes) => {
309
314
  const clientReq: AuthClientRequest = { httpReq: req }
310
315
  const getUser = this.getUser;
311
316
  try {
@@ -355,7 +360,7 @@ export default class AuthHandler {
355
360
 
356
361
  return new Promise(async (resolve, reject) => {
357
362
 
358
- let interval, result: any, error: any, finished = false;
363
+ let interval: NodeJS.Timeout, result: any, error: any, finished = false;
359
364
 
360
365
  /**
361
366
  * Throttle response times to prevent timing attacks
@@ -384,18 +389,18 @@ export default class AuthHandler {
384
389
  }
385
390
 
386
391
  loginThrottled = async (params: AnyObject): Promise<BasicSession> => {
387
- if (!this.opts.login) throw "Auth login config missing";
392
+ if (!this.opts?.login) throw "Auth login config missing";
388
393
  const { responseThrottle = 500 } = this.opts;
389
394
 
390
395
  return this.throttledFunc(async () => {
391
- let result = await this.opts.login(params, this.dbo as any, this.db);
396
+ let result = await this.opts?.login?.(params, this.dbo as any, this.db);
392
397
  const err = {
393
398
  msg: "Bad login result type. \nExpecting: undefined | null | { sid: string; expires: number } but got: " + JSON.stringify(result)
394
399
  }
395
400
  if(result && (typeof result.sid !== "string" || typeof result.expires !== "number") || !result && ![undefined, null].includes(result)) {
396
401
  throw err
397
402
  }
398
-
403
+ if(!result) throw "Could not login"
399
404
  return result;
400
405
  }, responseThrottle);
401
406
 
@@ -408,18 +413,19 @@ export default class AuthHandler {
408
413
  * @param localParams
409
414
  * @returns string
410
415
  */
411
- getSID(localParams: LocalParams): string {
412
- if (!this.opts) return null;
416
+ getSID(localParams: LocalParams): string | undefined {
417
+ if (!this.opts) return undefined;
413
418
 
414
419
  const { sidKeyName } = this.opts;
415
420
 
416
- if (!sidKeyName || !localParams) return null;
421
+ if (!sidKeyName || !localParams) return undefined;
417
422
 
418
423
  if (localParams.socket) {
419
424
  const querySid = localParams.socket?.handshake?.query?.[sidKeyName];
420
425
  let rawSid = querySid;
421
426
  if (!rawSid) {
422
427
  const cookie_str = localParams.socket?.handshake?.headers?.cookie;
428
+ if(!cookie_str) throw "cookie_str missing";
423
429
  const cookie = parseCookieStr(cookie_str);
424
430
  rawSid = cookie[sidKeyName];
425
431
  }
@@ -432,7 +438,7 @@ export default class AuthHandler {
432
438
 
433
439
  function parseCookieStr(cookie_str: string): any {
434
440
  if (!cookie_str || typeof cookie_str !== "string") return {}
435
- return cookie_str.replace(/\s/g, '').split(";").reduce((prev, current) => {
441
+ return cookie_str.replace(/\s/g, '').split(";").reduce<AnyObject>((prev, current) => {
436
442
  const [name, value] = current.split('=');
437
443
  prev[name] = value;
438
444
  return prev
@@ -445,7 +451,7 @@ export default class AuthHandler {
445
451
 
446
452
  const getSession = this.opts.cacheSession?.getSession;
447
453
  const isSocket = "socket" in localParams
448
- if(getSession && isSocket && localParams.socket.__prglCache){
454
+ if(getSession && isSocket && localParams.socket?.__prglCache){
449
455
  const { session, user, clientUser } = localParams.socket.__prglCache;
450
456
  const isValid = this.isValidSocketSession(localParams.socket, session)
451
457
  if(isValid){
@@ -460,9 +466,9 @@ export default class AuthHandler {
460
466
 
461
467
  const res = await this.throttledFunc(async () => {
462
468
 
463
- const { getUser, getClientUser } = this.opts;
469
+ const { getUser, getClientUser } = this.opts ?? {};
464
470
 
465
- if (getUser && localParams && (localParams.httpReq || localParams.socket)) {
471
+ if (getUser && getClientUser && localParams && (localParams.httpReq || localParams.socket)) {
466
472
  const sid = this.getSID(localParams);
467
473
  const clientReq = localParams.httpReq? { httpReq: localParams.httpReq } : { socket: localParams.socket };
468
474
  let user, clientUser;
@@ -472,7 +478,7 @@ export default class AuthHandler {
472
478
  }
473
479
  if(getSession && isSocket){
474
480
  const session = await getSession(sid, this.dbo as any, this.db)
475
- if(session?.expires && user && clientUser){
481
+ if(session?.expires && user && clientUser && localParams.socket){
476
482
  localParams.socket.__prglCache = {
477
483
  session,
478
484
  user,
@@ -493,7 +499,7 @@ export default class AuthHandler {
493
499
 
494
500
  isValidSocketSession = (socket: PRGLIOSocket, session: BasicSession): boolean => {
495
501
  const hasExpired = Boolean(session && session.expires <= Date.now())
496
- if(this.opts.expressConfig?.publicRoutes && !this.opts.expressConfig?.disableSocketAuthGuard){
502
+ if(this.opts?.expressConfig?.publicRoutes && !this.opts.expressConfig?.disableSocketAuthGuard){
497
503
  if(hasExpired){
498
504
  socket.emit(CHANNELS.AUTHGUARD, { shouldReload: true });
499
505
  throw ""
@@ -502,10 +508,10 @@ export default class AuthHandler {
502
508
  return Boolean(session && !hasExpired);
503
509
  }
504
510
 
505
- makeSocketAuth = async (socket): Promise<AuthSocketSchema> => {
511
+ makeSocketAuth = async (socket: PRGLIOSocket): Promise<AuthSocketSchema> => {
506
512
  if (!this.opts) return {};
507
513
 
508
- let auth: AuthSocketSchema = {};
514
+ let auth: Partial<Record<keyof Omit<AuthSocketSchema, "user">, boolean | undefined>> & { user?: AnyObject | undefined } = {};
509
515
 
510
516
  if (this.opts.expressConfig?.publicRoutes && !this.opts.expressConfig?.disableSocketAuthGuard) {
511
517
 
@@ -536,10 +542,14 @@ export default class AuthHandler {
536
542
  } = this.opts;
537
543
  const login = this.loginThrottled
538
544
 
539
- let handlers = [
540
- { func: (params: any, dbo: DbHandler, db: DB) => register(params, dbo, db), ch: CHANNELS.REGISTER, name: "register" },
541
- { func: (params: any, dbo: DbHandler, db: DB) => login(params), ch: CHANNELS.LOGIN, name: "login" },
542
- { func: (params: any, dbo: DbHandler, db: DB) => logout(this.getSID({ socket }), dbo, db), ch: CHANNELS.LOGOUT, name: "logout" }
545
+ let handlers: {
546
+ name: keyof Omit<AuthSocketSchema, "user">;
547
+ ch: string;
548
+ func: Function;
549
+ }[] = [
550
+ { func: (params: any, dbo: DbHandler, db: DB) => register?.(params, dbo, db), ch: CHANNELS.REGISTER, name: "register" as keyof Omit<AuthSocketSchema, "user"> },
551
+ { func: (params: any, dbo: DbHandler, db: DB) => login(params), ch: CHANNELS.LOGIN, name: "login" as keyof Omit<AuthSocketSchema, "user"> },
552
+ { func: (params: any, dbo: DbHandler, db: DB) => logout?.(this.getSID({ socket }), dbo, db), ch: CHANNELS.LOGOUT, name: "logout" as keyof Omit<AuthSocketSchema, "user">}
543
553
  ].filter(h => h.func);
544
554
 
545
555
  const usrData = await this.getClientInfo({ socket });
@@ -552,7 +562,7 @@ export default class AuthHandler {
552
562
  auth[name] = true;
553
563
 
554
564
  socket.removeAllListeners(ch)
555
- socket.on(ch, async (params: any, cb = (...callback) => { }) => {
565
+ socket.on(ch, async (params: any, cb = (...callback: any) => { }) => {
556
566
 
557
567
  try {
558
568
  if (!socket) throw "socket missing??!!";
@@ -578,8 +588,8 @@ export default class AuthHandler {
578
588
  /**
579
589
  * AUTH
580
590
  */
581
- function getReturnUrl(req, name: string) {
582
- if (req?.query?.returnURL) {
591
+ function getReturnUrl(req: ExpressReq, name?: string) {
592
+ if (req?.query?.returnURL && name) {
583
593
  return decodeURIComponent(req?.query?.[name]);
584
594
  }
585
595
  return null;
@@ -1,6 +1,7 @@
1
1
  import { PostgresNotifListenManager, PrglNotifListener } from "./PostgresNotifListenManager";
2
2
  import { DB, PGP } from "./Prostgles";
3
3
  import { SQLRequest, SQLOptions, CHANNELS, asName } from "prostgles-types";
4
+ import { getKeys, PRGLIOSocket } from "./DboBuilder";
4
5
 
5
6
  export class DBEventsManager {
6
7
 
@@ -23,7 +24,7 @@ export class DBEventsManager {
23
24
  sockets: []
24
25
  };
25
26
 
26
- notifManager: PostgresNotifListenManager;
27
+ notifManager?: PostgresNotifListenManager;
27
28
 
28
29
  db_pg: DB;
29
30
  pgp: PGP
@@ -50,7 +51,7 @@ export class DBEventsManager {
50
51
  });
51
52
  }
52
53
 
53
- onNotice = notice => {
54
+ onNotice = (notice: any) => {
54
55
  if(this.notice && this.notice.sockets.length){
55
56
  this.notice.sockets.map(s => {
56
57
  s.emit(this.notice.socketChannel, notice);
@@ -63,7 +64,7 @@ export class DBEventsManager {
63
64
  return c.c;
64
65
  }
65
66
 
66
- async addNotify(query: string, socket?, func?): Promise<{
67
+ async addNotify(query: string, socket?: PRGLIOSocket, func?: any): Promise<{
67
68
  socketChannel: string;
68
69
  socketUnsubChannel: string;
69
70
  notifChannel: string;
@@ -135,8 +136,8 @@ export class DBEventsManager {
135
136
  }
136
137
  }
137
138
 
138
- removeNotify(channel: string, socket?, func?){
139
- if(this.notifies[channel]){
139
+ removeNotify(channel?: string, socket?: PRGLIOSocket, func?: any){
140
+ if(channel && this.notifies[channel]){
140
141
  if(socket){
141
142
  this.notifies[channel].sockets = this.notifies[channel].sockets.filter(s => s.id !== socket.id);
142
143
  } else if(func){
@@ -145,9 +146,15 @@ export class DBEventsManager {
145
146
 
146
147
  /* UNLISTEN if no listeners ?? */
147
148
  }
149
+
150
+ if(socket){
151
+ getKeys(this.notifies).forEach(channel => {
152
+ this.notifies[channel].sockets = this.notifies[channel].sockets.filter(s => s.id !== socket.id);
153
+ })
154
+ }
148
155
  }
149
156
 
150
- addNotice(socket){
157
+ addNotice(socket: PRGLIOSocket){
151
158
  if(!socket || !socket.id) throw "Expecting a socket obj with id";
152
159
 
153
160
  if(!this.notice.sockets.find(s => s.id === socket.id)){
@@ -164,7 +171,7 @@ export class DBEventsManager {
164
171
  return { socketChannel, socketUnsubChannel, }
165
172
  }
166
173
 
167
- removeNotice(socket){
174
+ removeNotice(socket: PRGLIOSocket){
168
175
  if(!socket || !socket.id) throw "Expecting a socket obj with id";
169
176
  this.notice.sockets = this.notice.sockets.filter(s => s.id !== socket.id)
170
177
  }