prostgles-server 4.2.559 → 4.2.560

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 (70) hide show
  1. package/dist/DboBuilder/DboBuilder.d.ts +3 -3
  2. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  3. package/dist/DboBuilder/DboBuilder.js +18 -29
  4. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  5. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +17 -4
  6. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  7. package/dist/DboBuilder/ViewHandler/ViewHandler.js +16 -2
  8. package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
  9. package/dist/DboBuilder/ViewHandler/count.d.ts +2 -1
  10. package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
  11. package/dist/DboBuilder/ViewHandler/count.js +5 -2
  12. package/dist/DboBuilder/ViewHandler/count.js.map +1 -1
  13. package/dist/DboBuilder/ViewHandler/find.d.ts +4 -1
  14. package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
  15. package/dist/DboBuilder/ViewHandler/find.js +9 -5
  16. package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
  17. package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts +9 -0
  18. package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts.map +1 -0
  19. package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js +73 -0
  20. package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js.map +1 -0
  21. package/dist/DboBuilder/ViewHandler/size.d.ts +2 -1
  22. package/dist/DboBuilder/ViewHandler/size.d.ts.map +1 -1
  23. package/dist/DboBuilder/ViewHandler/size.js +7 -5
  24. package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
  25. package/dist/DboBuilder/dboBuilderUtils.d.ts +1 -0
  26. package/dist/DboBuilder/dboBuilderUtils.d.ts.map +1 -1
  27. package/dist/DboBuilder/dboBuilderUtils.js +4 -2
  28. package/dist/DboBuilder/dboBuilderUtils.js.map +1 -1
  29. package/dist/DboBuilder/{QueryStreamer.d.ts → runSql/QueryStreamer.d.ts} +4 -6
  30. package/dist/DboBuilder/runSql/QueryStreamer.d.ts.map +1 -0
  31. package/dist/DboBuilder/{QueryStreamer.js → runSql/QueryStreamer.js} +5 -22
  32. package/dist/DboBuilder/runSql/QueryStreamer.js.map +1 -0
  33. package/dist/DboBuilder/runSql/getAdminClient.d.ts +26 -0
  34. package/dist/DboBuilder/runSql/getAdminClient.d.ts.map +1 -0
  35. package/dist/DboBuilder/runSql/getAdminClient.js +32 -0
  36. package/dist/DboBuilder/runSql/getAdminClient.js.map +1 -0
  37. package/dist/Prostgles.d.ts +2 -0
  38. package/dist/Prostgles.d.ts.map +1 -1
  39. package/dist/Prostgles.js +3 -1
  40. package/dist/Prostgles.js.map +1 -1
  41. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  42. package/dist/PublishParser/PublishParser.js +2 -1
  43. package/dist/PublishParser/PublishParser.js.map +1 -1
  44. package/dist/WebsocketAPI/onSocketConnected.d.ts.map +1 -1
  45. package/dist/WebsocketAPI/onSocketConnected.js +14 -6
  46. package/dist/WebsocketAPI/onSocketConnected.js.map +1 -1
  47. package/dist/initProstgles.d.ts.map +1 -1
  48. package/dist/initProstgles.js +2 -0
  49. package/dist/initProstgles.js.map +1 -1
  50. package/dist/runClientRequest.d.ts +1 -1
  51. package/dist/runClientRequest.d.ts.map +1 -1
  52. package/dist/runClientRequest.js +28 -6
  53. package/dist/runClientRequest.js.map +1 -1
  54. package/lib/DboBuilder/DboBuilder.ts +20 -31
  55. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +27 -3
  56. package/lib/DboBuilder/ViewHandler/count.ts +6 -2
  57. package/lib/DboBuilder/ViewHandler/find.ts +16 -7
  58. package/lib/DboBuilder/ViewHandler/getDbHandlerWithAbort.ts +98 -0
  59. package/lib/DboBuilder/ViewHandler/size.ts +8 -5
  60. package/lib/DboBuilder/dboBuilderUtils.ts +4 -1
  61. package/lib/DboBuilder/{QueryStreamer.ts → runSql/QueryStreamer.ts} +10 -32
  62. package/lib/DboBuilder/runSql/getAdminClient.ts +31 -0
  63. package/lib/Prostgles.ts +4 -1
  64. package/lib/PublishParser/PublishParser.ts +3 -1
  65. package/lib/WebsocketAPI/onSocketConnected.ts +15 -7
  66. package/lib/initProstgles.ts +3 -0
  67. package/lib/runClientRequest.ts +49 -10
  68. package/package.json +2 -2
  69. package/dist/DboBuilder/QueryStreamer.d.ts.map +0 -1
  70. package/dist/DboBuilder/QueryStreamer.js.map +0 -1
@@ -20,12 +20,14 @@ const TABLE_METHODS = {
20
20
  getInfo: 1,
21
21
  sync: 1,
22
22
  insertMany: 1,
23
+ abort: 1,
23
24
  };
24
25
  const TABLE_METHODS_KEYS = (0, prostgles_types_1.getKeys)(TABLE_METHODS);
25
26
  const SOCKET_ONLY_COMMANDS = [
26
27
  "subscribe",
27
28
  "subscribeOne",
28
29
  "sync",
30
+ "abort",
29
31
  ];
30
32
  const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
31
33
  /* Channel name will only include client-sent params so we ignore table_rules enforced params */
@@ -37,7 +39,15 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
37
39
  command: { enum: TABLE_METHODS_KEYS },
38
40
  param1: { type: "any", optional: true },
39
41
  param2: { type: "any", optional: true },
40
- param3: { type: "any", optional: true },
42
+ param3: {
43
+ type: {
44
+ abortSignalId: { type: "string", optional: true },
45
+ returning: { type: "any", optional: true },
46
+ returnQuery: { type: "boolean", optional: true },
47
+ returnType: { type: "string", optional: true },
48
+ },
49
+ optional: true,
50
+ },
41
51
  }, nonValidatedArgs, "tableName");
42
52
  if (validation.error !== undefined) {
43
53
  throw validation.error;
@@ -56,11 +66,6 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
56
66
  throw clientInfo;
57
67
  }
58
68
  const parsedTableRule = await this.publishParser.getParsedTableRule({ tableName, clientReq }, clientInfo, scope);
59
- this.publishParser.validateRequestRule({ tableName, command, clientReq }, parsedTableRule, scope);
60
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
61
- if (!parsedTableRule) {
62
- throw `Invalid OR disallowed request: ${tableName}.${command} `;
63
- }
64
69
  const sessionUser = !clientInfo.user ? undefined : ({
65
70
  ...(0, parseFieldFilter_1.parseFieldFilter)(
66
71
  //@ts-ignore
@@ -72,6 +77,23 @@ const runClientRequest = async function (nonValidatedArgs, clientReq, scope) {
72
77
  isRemoteRequest: { user: sessionUser },
73
78
  scope,
74
79
  };
80
+ if (command === "abort") {
81
+ const validation = (0, prostgles_types_1.getJSONBObjectSchemaValidationError)({
82
+ tableName: { type: "string" },
83
+ command: { enum: ["abort"] },
84
+ param1: {
85
+ type: { command: { enum: prostgles_types_1.ABORTABLE_METHODS }, abortSignalId: "string" },
86
+ },
87
+ }, nonValidatedArgs, "tableName", undefined, { allowExtraProperties: true });
88
+ if (validation.error !== undefined) {
89
+ throw validation.error;
90
+ }
91
+ this.publishParser.validateRequestRule({ tableName, command: validation.data.param1.command, clientReq }, parsedTableRule, scope);
92
+ return tableHandler.abortRemoteQuery(validation.data.param1.abortSignalId, localParams);
93
+ }
94
+ else {
95
+ this.publishParser.validateRequestRule({ tableName, command, clientReq }, parsedTableRule, scope);
96
+ }
75
97
  if (param3 && param3.returnQuery) {
76
98
  const isAllowed = await (0, runSQL_1.canRunSQL)(this, clientReq);
77
99
  if (isAllowed) {
@@ -1 +1 @@
1
- {"version":3,"file":"runClientRequest.js","sourceRoot":"","sources":["../lib/runClientRequest.ts"],"names":[],"mappings":";;;AACA,qDAMyB;AAIzB,gFAA6E;AAC7E,uDAAuD;AAKvD,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,WAAW,EAAE,CAAC;IACd,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;IACP,UAAU,EAAE,CAAC;CACwE,CAAC;AAExF,MAAM,kBAAkB,GAAG,IAAA,yBAAO,EAAC,aAAa,CAAC,CAAC;AAClD,MAAM,oBAAoB,GAAG;IAC3B,WAAW;IACX,cAAc;IACd,MAAM;CACsC,CAAC;AAkBxC,MAAM,gBAAgB,GAAG,KAAK,WAEnC,gBAAsB,EACtB,SAA4B,EAC5B,KAAkC;IAElC,gGAAgG;IAChG,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACrC,MAAM,uCAAuC,CAAC;IAChD,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,qDAAmC,EACpD;QACE,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC7B,OAAO,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;QACrC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;KACxC,EACD,gBAAgB,EAChB,WAAW,CACZ,CAAC;IACF,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,UAAU,CAAC,KAAK,CAAC;IACzB,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC;IAEvE,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE,CAAC;QACzE,MAAM,CACJ,8EAA8E;YAC9E,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAChC,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,aAAa,SAAS,4BAA4B,CAAC;IAC3D,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAC9E,IAAI,UAAU,KAAK,sBAAsB,EAAE,CAAC;QAC1C,MAAM,UAAU,CAAC;IACnB,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,kBAAkB,CACjE,EAAE,SAAS,EAAE,SAAS,EAAE,EACxB,UAAU,EACV,KAAK,CACN,CAAC;IACF,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;IAElG,uEAAuE;IACvE,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,kCAAkC,SAAS,IAAI,OAAO,GAAG,CAAC;IAClE,CAAC;IAED,MAAM,WAAW,GACf,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAC7B;QACE,GAAG,IAAA,mCAAgB;QACjB,YAAY;QACZ,UAAU,CAAC,aAAa,IAAI,EAAE,EAC9B,KAAK,EACL,IAAA,yBAAO,EAAC,UAAU,CAAC,IAAI,CAAC,CACzB;QACD,GAAI,IAAA,0BAAQ,EAAC,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAc;KAC3D,CACF,CAAC;IACJ,MAAM,WAAW,GAAgB;QAC/B,SAAS;QACT,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;QACtC,KAAK;KACN,CAAC;IACF,IAAI,MAAM,IAAK,MAAsB,CAAC,WAAW,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,IAAA,kBAAS,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,SAAS,EAAE,CAAC;YACd,WAAW,CAAC,WAAW,GAAI,MAAsB,CAAC,WAAW,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,MAAM,+CAA+C,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAEO,CAAC;IAE/C,OAAQ,YAAY,CAAC,OAAO,CAAgD,CAC1E,MAAM,EACN,MAAM,EACN,MAAM,EACN,eAAe,EACf,WAAW,CACa,CAAC;AAC7B,CAAC,CAAC;AAhGW,QAAA,gBAAgB,oBAgG3B;AAEK,MAAM,sBAAsB,GAAG,KAAK,WAEzC,SAA4B;IAE5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;QAC9E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACvC,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACvF,MAAM,eAAe,GAAG,aAAa,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;QAC1F,OAAO,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,GAAG,CAAC;IAC7D,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,SAAS,EAAE,CAAC;IAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACzC,CAAC,CAAC;AAfW,QAAA,sBAAsB,0BAejC;AAEK,MAAM,mBAAmB,GAAG,KAAK,WAEtC,eAA2B,EAC3B,SAA4B;IAE5B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,8BAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,4BAA4B,CAAC;IACrC,CAAC;IACD,MAAM,UAAU,GAAG,IAAA,qDAAmC,EACpD;QACE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvC,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;KACzC,EACD,eAAe,EACf,OAAO,CACR,CAAC;IACF,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,UAAU,CAAC,KAAK,CAAC;IACzB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;AACvE,CAAC,CAAC;AAxBW,QAAA,mBAAmB,uBAwB9B;AAMK,MAAM,eAAe,GAAG,KAAK,WAElC,eAA2B,EAC3B,SAA4B;IAE5B,MAAM,UAAU,GAAG,IAAA,qDAAmC,EACpD;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;KACvC,EACD,eAAe,EACf,QAAQ,CACT,CAAC;IACF,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,UAAU,CAAC,KAAK,CAAC;IACzB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC;IAChC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAE7F,MAAM,kBAAkB,GAAG,gBAAgB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC;QAC7B,MAAM,8BAA8B,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC;IAC7C,IAAI,CAAC,WAAW,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,gCAAgC,CAAC;IAC9E,CAAC;IAED,MAAM,iBAAiB,GACrB,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,+CAA6B,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC;IAEzF,IAAI,iBAAiB,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QAChE,MAAM,OAAO,CAAC;IAChB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,KAAc,CAAC,CAAC;IAEzD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AA1CW,QAAA,eAAe,mBA0C1B"}
1
+ {"version":3,"file":"runClientRequest.js","sourceRoot":"","sources":["../lib/runClientRequest.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ import type {
20
20
  TableSchema,
21
21
  TxCB,
22
22
  } from "./DboBuilderTypes";
23
- import { QueryStreamer } from "./QueryStreamer";
23
+ import { QueryStreamer } from "./runSql/QueryStreamer";
24
24
  import { TableHandler } from "./TableHandler/TableHandler";
25
25
  import type { JoinPaths } from "./ViewHandler/ViewHandler";
26
26
  import { parseJoinPath } from "./ViewHandler/parseJoinPath";
@@ -69,18 +69,27 @@ export class DboBuilder {
69
69
 
70
70
  queryStreamer: QueryStreamer;
71
71
 
72
+ private constructor(prostgles: Prostgles) {
73
+ this.prostgles = prostgles;
74
+ if (!this.prostgles.db) throw "db missing";
75
+ this.db = this.prostgles.db;
76
+ this.dbo = {};
77
+ this.dboMap = new Map();
78
+ this.queryStreamer = new QueryStreamer(this);
79
+ }
80
+
81
+ private init = async () => {
82
+ await this.build();
83
+ /* If watchSchema is enabled then PubSubManager must be created (if possible) because it creates the event trigger */
84
+ if (this.prostgles.schemaWatch?.type.watchType === "DDL_trigger") {
85
+ await this.getPubSubManager();
86
+ }
87
+
88
+ return this;
89
+ };
90
+
72
91
  get tables(): TableSchema[] {
73
92
  return this.tablesOrViews ?? [];
74
- // .map(({ name, columns }) => {
75
- // const info = this.dboMap.get(name)?.tableOrViewInfo;
76
- // if (!info) return undefined;
77
- // return {
78
- // name,
79
- // info,
80
- // columns,
81
- // } satisfies DbTableInfo;
82
- // })
83
- // .filter(isDefined);
84
93
  }
85
94
 
86
95
  getDetailedFieldInfo = async (fields: pg.IColumn[]) => {
@@ -130,32 +139,12 @@ export class DboBuilder {
130
139
 
131
140
  onSchemaChange?: (event: { command: string; query: string }) => void;
132
141
 
133
- private constructor(prostgles: Prostgles) {
134
- this.prostgles = prostgles;
135
- if (!this.prostgles.db) throw "db missing";
136
- this.db = this.prostgles.db;
137
- this.dbo = {};
138
- this.dboMap = new Map();
139
- this.queryStreamer = new QueryStreamer(this);
140
- }
141
-
142
- private init = async () => {
143
- await this.build();
144
- /* If watchSchema is enabled then PubSubManager must be created (if possible) because it creates the event trigger */
145
- if (this.prostgles.schemaWatch?.type.watchType === "DDL_trigger") {
146
- await this.getPubSubManager();
147
- }
148
-
149
- return this;
150
- };
151
-
152
142
  public static create = async (prostgles: Prostgles): Promise<DboBuilder> => {
153
143
  const res = new DboBuilder(prostgles);
154
144
  return await res.init();
155
145
  };
156
146
 
157
147
  destroy = async () => {
158
- await this.queryStreamer.destroy().catch(console.error);
159
148
  return this._pubSubManager?.destroy();
160
149
  };
161
150
 
@@ -20,7 +20,7 @@ import type { TableSchema } from "../DboBuilderTypes";
20
20
  import { getValidatedTableRules } from "../TableRules/getValidatedTableRules";
21
21
  import { getColumns } from "../getColumns";
22
22
  import { count } from "./count";
23
- import { find } from "./find";
23
+ import { find, type Param3 } from "./find";
24
24
  import { getInfo } from "./getInfo";
25
25
  import { parseFieldFilter } from "./parseFieldFilter";
26
26
  import { prepareWhere } from "./prepareWhere";
@@ -30,6 +30,8 @@ import { subscribe } from "./subscribe";
30
30
  import { validateViewRules } from "./validateViewRules";
31
31
  import { escapeTSNames } from "../../utils/utils";
32
32
  import type { TableDefinition } from "../../TableConfig/TableConfig";
33
+ import { getDbHandlerWithAbort } from "./getDbHandlerWithAbort";
34
+ import type { VoidFunction } from "../../SchemaWatch/SchemaWatch";
33
35
 
34
36
  export type JoinPaths = {
35
37
  t1: string;
@@ -112,6 +114,28 @@ export class ViewHandler {
112
114
  return localParams?.tx || this.tx;
113
115
  };
114
116
 
117
+ abortRemoteQuery = (abortSignalId: string, localParams: LocalParams) => {
118
+ const sid = this.dboBuilder.prostgles.authHandler.getSIDNoError(localParams.clientReq);
119
+ if (!sid) {
120
+ throw new Error(
121
+ "Cannot get SID from client request. Ensure that the client is authenticated before using abortable queries.",
122
+ );
123
+ }
124
+ const abortableQuery = this.activeQueries.get(abortSignalId);
125
+ if (!abortableQuery || abortableQuery.sid !== sid) {
126
+ throw new Error(
127
+ `No active query found with abortSignalId ${abortSignalId}. Ensure that the query was initiated with the correct abortSignalId.`,
128
+ );
129
+ }
130
+ abortableQuery.abort();
131
+ };
132
+
133
+ activeQueries = new Map<
134
+ string,
135
+ { abort: VoidFunction; query: string; start: number; sid: string | undefined }
136
+ >();
137
+ getDbHandlerWithAbort = getDbHandlerWithAbort.bind(this);
138
+
115
139
  _log = ({
116
140
  command,
117
141
  data,
@@ -178,7 +202,7 @@ export class ViewHandler {
178
202
  async findOne(
179
203
  filter?: Filter,
180
204
  selectParams?: SelectParams,
181
- _param3_unused?: undefined,
205
+ param3?: Param3,
182
206
  table_rules?: ParsedTableRule,
183
207
  localParams?: LocalParams,
184
208
  ): Promise<any> {
@@ -191,7 +215,7 @@ export class ViewHandler {
191
215
  const result = await this.find(
192
216
  filter,
193
217
  { ...params, limit: 1, returnType: "row" },
194
- undefined,
218
+ param3,
195
219
  table_rules,
196
220
  localParams,
197
221
  );
@@ -8,12 +8,13 @@ import {
8
8
  } from "../dboBuilderUtils";
9
9
  import type { ViewHandler } from "./ViewHandler";
10
10
  import { getReturnTypeQuery } from "./getReturnTypeQuery";
11
+ import type { Param3 } from "./find";
11
12
 
12
13
  export async function count(
13
14
  this: ViewHandler,
14
15
  _filter?: Filter,
15
16
  selectParams?: SelectParams,
16
- _param3_unused?: undefined,
17
+ param3?: Param3,
17
18
  table_rules?: ParsedTableRule,
18
19
  localParams?: LocalParams,
19
20
  ): Promise<number> {
@@ -54,7 +55,10 @@ export async function count(
54
55
  return queryToReturn as unknown[];
55
56
  }
56
57
 
57
- const handler = this.tx?.t ?? this.db;
58
+ const handler = this.getDbHandlerWithAbort(localParams, {
59
+ abortSignal: selectParams?.abortSignal,
60
+ abortSignalId: param3?.abortSignalId,
61
+ });
58
62
  return handler.one(queryWithRLS).then(({ count }) => +count);
59
63
  });
60
64
 
@@ -13,19 +13,23 @@ import { getSelectQuery } from "../QueryBuilder/getSelectQuery";
13
13
  import { getReturnTypeQuery } from "./getReturnTypeQuery";
14
14
  import type { ViewHandler } from "./ViewHandler";
15
15
 
16
+ export type Param3 = {
17
+ abortSignalId?: string;
18
+ };
19
+
16
20
  export const find = async function (
17
21
  this: ViewHandler,
18
- filter?: Filter,
22
+ filter: Filter = {},
19
23
  selectParams?: SelectParams,
20
- _?: undefined,
24
+ param3?: Param3,
21
25
  tableRules?: ParsedTableRule,
22
26
  localParams?: LocalParams,
23
27
  ): Promise<any[]> {
24
28
  const start = Date.now();
25
- const command =
26
- selectParams?.limit === 1 && selectParams.returnType === "row" ? "findOne" : "find";
29
+ const { limit, returnType, abortSignal } = selectParams ?? {};
30
+
31
+ const command = limit === 1 && returnType === "row" ? "findOne" : "find";
27
32
  try {
28
- filter = filter || {};
29
33
  const allowedReturnTypes = Object.keys({
30
34
  row: 1,
31
35
  statement: 1,
@@ -52,6 +56,7 @@ export const find = async function (
52
56
  returnType: 1,
53
57
  groupBy: 1,
54
58
  having: 1,
59
+ abortSignal: 1,
55
60
  } satisfies Record<keyof SelectParams, 1>);
56
61
 
57
62
  const invalidParams = Object.keys(selectParams).filter((k) => !validParamNames.includes(k));
@@ -96,7 +101,7 @@ export const find = async function (
96
101
  this,
97
102
  filter,
98
103
  selectParamsLimitCheck,
99
- _,
104
+ undefined,
100
105
  tableRules,
101
106
  localParams,
102
107
  );
@@ -109,6 +114,7 @@ export const find = async function (
109
114
  );
110
115
 
111
116
  const queryWithRLS = withUserRLS(localParams, queryWithoutRLS);
117
+
112
118
  const queryToReturn = await getReturnTypeQuery({
113
119
  handler: this,
114
120
  localParams,
@@ -123,7 +129,10 @@ export const find = async function (
123
129
 
124
130
  const query = queryWithRLS;
125
131
  const isOneOrNone = returnType === "row" || returnType === "value";
126
- const dbHandler = this.getTransaction(localParams)?.t ?? this.db;
132
+ const dbHandler = this.getDbHandlerWithAbort(localParams, {
133
+ abortSignal,
134
+ abortSignalId: param3?.abortSignalId,
135
+ });
127
136
  const queryPromise =
128
137
  isOneOrNone ?
129
138
  dbHandler.oneOrNone<AnyObject>(query).then((data) => (data ? [data] : []))
@@ -0,0 +1,98 @@
1
+ import type { DB } from "../../initProstgles";
2
+ import { QUERY_ID_PREFIX, type LocalParams } from "../DboBuilder";
3
+ import type { ViewHandler } from "./ViewHandler";
4
+ import type * as pgPromise from "pg-promise";
5
+
6
+ export function getDbHandlerWithAbort(
7
+ this: ViewHandler,
8
+ localParams: LocalParams | undefined,
9
+ params: { abortSignal: AbortSignal | undefined; abortSignalId: string | undefined },
10
+ ): Pick<DB | pgPromise.ITask<{}>, "any" | "one" | "many" | "manyOrNone" | "none" | "oneOrNone"> {
11
+ if (params.abortSignal && params.abortSignalId) {
12
+ throw new Error("Cannot provide both abortSignal and abortSignalId");
13
+ }
14
+
15
+ if (params.abortSignal?.aborted) {
16
+ throw new Error("Query aborted before execution");
17
+ }
18
+
19
+ const abortSignal =
20
+ params.abortSignal ?? AbortSignal.timeout(localParams?.clientReq ? 7_000 : 120_000);
21
+ const abortSignalId = params.abortSignalId ?? crypto.randomUUID();
22
+
23
+ if (this.activeQueries.has(abortSignalId)) {
24
+ throw new Error(
25
+ `A query with abortSignalId ${params.abortSignalId} is already active. Ensure that each query has a unique abortSignalId.`,
26
+ );
27
+ }
28
+ const handler = this.getTransaction(localParams)?.t ?? this.db;
29
+ const { adminClient } = this.dboBuilder.prostgles;
30
+ if (!adminClient) {
31
+ throw new Error(
32
+ "adminClient not available. Ensure prostgles.adminClient is initialized before using abortable queries.",
33
+ );
34
+ }
35
+ const sid = this.dboBuilder.prostgles.authHandler.getSIDNoError(localParams?.clientReq);
36
+ if (!sid && localParams?.clientReq) {
37
+ throw new Error(
38
+ "Cannot get SID from client request. Ensure that the client is authenticated before using abortable queries.",
39
+ );
40
+ }
41
+ const withAbortQuery = <Args extends unknown[], R extends Promise<any>>(
42
+ func: (query: string, ...args: Args) => R,
43
+ ) => {
44
+ return (query: string, ...args: Args) => {
45
+ const queryIdPrefix = query.split("\n", 1)[0];
46
+
47
+ const queryHasIdPrefix = queryIdPrefix?.startsWith(QUERY_ID_PREFIX);
48
+ if (!queryIdPrefix || !queryHasIdPrefix) {
49
+ throw new Error(
50
+ "Query does not have a prostgles query id prefix. Ensure that the query is generated using prostgles methods that include the query id.",
51
+ );
52
+ }
53
+
54
+ const abort = () => {
55
+ /** Only terminate if there is exactly one matching query with a query id prefix */
56
+
57
+ void adminClient
58
+ .query(
59
+ `
60
+ SELECT pg_terminate_backend(pid), *
61
+ FROM pg_stat_activity
62
+ WHERE query LIKE $1 AND pid <> pg_backend_pid()
63
+ `,
64
+ [`${queryIdPrefix}%`],
65
+ )
66
+ .then((res) => {
67
+ // if (params.abortSignalId) {
68
+ // console.log(JSON.stringify(res.rows));
69
+ // process.exit(1);
70
+ // }
71
+ })
72
+ .catch((err) => {
73
+ // ignore error
74
+ });
75
+ };
76
+ this.activeQueries.set(abortSignalId, {
77
+ query,
78
+ start: Date.now(),
79
+ sid,
80
+ abort,
81
+ });
82
+ abortSignal.addEventListener("abort", abort);
83
+ return func(query, ...args).finally(() => {
84
+ abortSignal.removeEventListener("abort", abort);
85
+ this.activeQueries.delete(abortSignalId);
86
+ });
87
+ };
88
+ };
89
+
90
+ return {
91
+ manyOrNone: withAbortQuery(handler.manyOrNone.bind(handler)),
92
+ one: withAbortQuery(handler.one.bind(handler)),
93
+ oneOrNone: withAbortQuery(handler.oneOrNone.bind(handler)),
94
+ any: withAbortQuery(handler.any.bind(handler)),
95
+ none: withAbortQuery(handler.none.bind(handler)),
96
+ many: withAbortQuery(handler.many.bind(handler)),
97
+ };
98
+ }
@@ -8,11 +8,12 @@ import {
8
8
  } from "../dboBuilderUtils";
9
9
  import type { ViewHandler } from "./ViewHandler";
10
10
  import { getReturnTypeQuery } from "./getReturnTypeQuery";
11
+ import type { Param3 } from "./find";
11
12
  export async function size(
12
13
  this: ViewHandler,
13
14
  _filter?: Filter,
14
15
  selectParams?: SelectParams,
15
- param3_unused?: undefined,
16
+ param3?: Param3,
16
17
  table_rules?: ParsedTableRule,
17
18
  localParams?: LocalParams,
18
19
  ): Promise<string> {
@@ -22,7 +23,7 @@ export async function size(
22
23
  const result = await this.find(
23
24
  filter,
24
25
  { ...selectParams, limit: 2 },
25
- undefined,
26
+ param3,
26
27
  table_rules,
27
28
  localParams,
28
29
  ).then(async (_allowed) => {
@@ -57,9 +58,11 @@ export async function size(
57
58
  return queryToReturn as unknown[];
58
59
  }
59
60
 
60
- return (this.tx?.t || this.db)
61
- .one<{ size: string | null }>(queryWithRLS)
62
- .then(({ size }) => size || "0");
61
+ const handler = this.getDbHandlerWithAbort(localParams, {
62
+ abortSignal: selectParams?.abortSignal,
63
+ abortSignalId: param3?.abortSignalId,
64
+ });
65
+ return handler.one<{ size: string | null }>(queryWithRLS).then(({ size }) => size || "0");
63
66
  });
64
67
  await this._log({
65
68
  command: "size",
@@ -176,6 +176,8 @@ export const getCanExecute = async (db: DB) => {
176
176
  return false;
177
177
  };
178
178
 
179
+ export const QUERY_ID_PREFIX = "-- prostgles query id: ";
180
+
179
181
  export const withUserRLS = (localParams: LocalParams | undefined, query: string) => {
180
182
  const user = localParams?.isRemoteRequest?.user;
181
183
  const queryPrefix = `SET SESSION "prostgles.user" \nTO`;
@@ -184,5 +186,6 @@ export const withUserRLS = (localParams: LocalParams | undefined, query: string)
184
186
  firstQuery = pgp.as.format(`${queryPrefix} \${user};`, { user });
185
187
  }
186
188
 
187
- return [firstQuery, query].join("\n");
189
+ const queryId = crypto.randomUUID();
190
+ return [QUERY_ID_PREFIX + queryId, firstQuery, query].filter(Boolean).join("\n");
188
191
  };
@@ -2,13 +2,14 @@ import * as pg from "pg";
2
2
  import type CursorType from "pg-cursor";
3
3
  import type { SQLOptions, SocketSQLStreamPacket, SocketSQLStreamServer } from "prostgles-types";
4
4
  import { CHANNELS, omitKeys, pickKeys } from "prostgles-types";
5
- import type { BasicCallback } from "../PubSubManager/PubSubManager";
6
- import type { VoidFunction } from "../SchemaWatch/SchemaWatch";
7
- import type { DB } from "../initProstgles";
8
- import type { DboBuilder } from "./DboBuilder";
9
- import type { PRGLIOSocket } from "./DboBuilderTypes";
10
- import { getErrorAsObject, getSerializedClientErrorFromPGError } from "./dboBuilderUtils";
11
- import { getDetailedFieldInfo } from "./runSql/runSqlUtils";
5
+ import type { BasicCallback } from "../../PubSubManager/PubSubManager";
6
+ import type { VoidFunction } from "../../SchemaWatch/SchemaWatch";
7
+ import type { DB } from "../../initProstgles";
8
+ import type { DboBuilder } from "../DboBuilder";
9
+ import type { PRGLIOSocket } from "../DboBuilderTypes";
10
+ import { getErrorAsObject, getSerializedClientErrorFromPGError } from "../dboBuilderUtils";
11
+ import { getDetailedFieldInfo } from "./runSqlUtils";
12
+ import { getConnectionDetails } from "./getAdminClient";
12
13
  const Cursor = require("pg-cursor") as typeof CursorType;
13
14
 
14
15
  type ClientStreamedRequest = {
@@ -44,36 +45,13 @@ export class QueryStreamer {
44
45
  db: DB;
45
46
  dboBuilder: DboBuilder;
46
47
  socketQueries: Map<string, Map<number, StreamedQuery>> = new Map();
47
- adminClient: pg.Client;
48
48
  constructor(dboBuilder: DboBuilder) {
49
49
  this.dboBuilder = dboBuilder;
50
50
  this.db = dboBuilder.db;
51
- const setAdminClient = () => {
52
- this.adminClient = this.getConnection(undefined, { keepAlive: true });
53
- return this.adminClient.connect();
54
- };
55
- this.adminClient = this.getConnection(
56
- (error) => {
57
- if (error.message?.includes("database") && error.message?.includes("does not exist"))
58
- return;
59
- console.log("Admin client error. Reconnecting...", error);
60
- void setAdminClient();
61
- },
62
- { keepAlive: true },
63
- );
64
- void this.adminClient.connect();
65
- }
66
-
67
- destroy() {
68
- return this.adminClient.end().catch((err) => {
69
- console.error("Error ending admin client connection", err);
70
- });
71
51
  }
72
52
 
73
53
  getConnection = (onError: ((err: any) => void) | undefined, extraOptions?: pg.ClientConfig) => {
74
- const connectionInfo =
75
- typeof this.db.$cn === "string" ? { connectionString: this.db.$cn } : (this.db.$cn as any);
76
- const client = new pg.Client({ ...connectionInfo, ...extraOptions });
54
+ const client = new pg.Client({ ...getConnectionDetails(this.db), ...extraOptions });
77
55
  client.on("error", (err) => {
78
56
  onError?.(err);
79
57
  });
@@ -272,7 +250,7 @@ export class QueryStreamer {
272
250
  }
273
251
  try {
274
252
  const stopFunction = opts?.terminate ? "pg_terminate_backend" : "pg_cancel_backend";
275
- const rows = await this.adminClient.query(
253
+ const rows = await this.dboBuilder.prostgles.adminClient!.query(
276
254
  `SELECT ${stopFunction}(pid), pid, state, query FROM pg_stat_activity WHERE pid = $1`,
277
255
  [processID],
278
256
  );
@@ -0,0 +1,31 @@
1
+ import * as pg from "pg";
2
+ import type { DB } from "../../initProstgles";
3
+
4
+ export const getAdminClient = async (db: DB, onDbDropped?: () => void): Promise<pg.Client> => {
5
+ const adminClient = new pg.Client({
6
+ ...getConnectionDetails(db),
7
+ application_name: "prostgles-admin-client",
8
+ keepAlive: true,
9
+ });
10
+ if (onDbDropped) {
11
+ adminClient.on("error", (err) => {
12
+ if (
13
+ err.message.includes("terminating connection due to administrator command") ||
14
+ (err.message.includes("database") && err.message.includes("does not exist"))
15
+ ) {
16
+ onDbDropped();
17
+ }
18
+ });
19
+ }
20
+ await adminClient.connect();
21
+ return adminClient;
22
+ };
23
+
24
+ export const getConnectionDetails = (db: DB) => {
25
+ const opts = db.$pool.options as pg.ClientConfig;
26
+ return {
27
+ ...opts,
28
+ password: opts.password,
29
+ keepAlive: true,
30
+ } satisfies pg.ClientConfig;
31
+ };
package/lib/Prostgles.ts CHANGED
@@ -60,6 +60,7 @@ const DEFAULT_KEYWORDS = {
60
60
  import { randomUUID } from "crypto";
61
61
  import * as fs from "fs";
62
62
  import type { TableHandler } from "./DboBuilder/TableHandler/TableHandler";
63
+ import type { getAdminClient } from "./DboBuilder/runSql/getAdminClient";
63
64
 
64
65
  export class Prostgles {
65
66
  /**
@@ -81,6 +82,7 @@ export class Prostgles {
81
82
  };
82
83
 
83
84
  db?: DB;
85
+ adminClient?: Awaited<ReturnType<typeof getAdminClient>>;
84
86
  pgp?: PGP;
85
87
  dbo?: DBHandlerServer;
86
88
  _dboBuilder?: DboBuilder;
@@ -173,8 +175,9 @@ export class Prostgles {
173
175
  !this.db ||
174
176
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
175
177
  !this.db.connect
176
- )
178
+ ) {
177
179
  throw "something went wrong getting a db connection";
180
+ }
178
181
  }
179
182
 
180
183
  getTSFileName() {
@@ -160,7 +160,9 @@ export class PublishParser {
160
160
  tableRule: ParsedTableRule,
161
161
  scope: PermissionScope | undefined,
162
162
  ) {
163
- if (!command || !tableName) throw "command OR tableName are missing";
163
+ if (!command || !tableName) {
164
+ throw "command OR tableName are missing";
165
+ }
164
166
 
165
167
  const [rule] =
166
168
  getObjectEntries(SQL_COMMAND_TABLE_METHODS).find(([_, methods]) =>
@@ -32,20 +32,28 @@ export async function onSocketConnected(this: Prostgles, socket: PRGLIOSocket) {
32
32
  };
33
33
 
34
34
  socket.on("disconnect", () => {
35
- this.dbEventsManager?.removeNotice(socket);
36
- this.dbEventsManager?.removeNotify(undefined, socket);
37
- this.connectedSockets = this.connectedSockets.filter((s) => s.id !== socket.id);
38
- this.dboBuilder.queryStreamer.onDisconnect(socket.id);
39
35
  void this.opts.onLog?.({
40
36
  type: "disconnect",
41
37
  sid: this.authHandler.getValidatedSid({ socket }),
42
38
  socketId: socket.id,
43
39
  connectedSocketIds: this.connectedSockets.map((s) => s.id),
44
40
  });
45
-
46
- if (this.opts.onSocketDisconnect) {
47
- void this.opts.onSocketDisconnect({ socket, dbo: dbo as DBOFullyTyped, db, getUser });
41
+ this.dbEventsManager?.removeNotice(socket);
42
+ this.dbEventsManager?.removeNotify(undefined, socket);
43
+ this.connectedSockets = this.connectedSockets.filter((s) => s.id !== socket.id);
44
+ this.dboBuilder.queryStreamer.onDisconnect(socket.id);
45
+ const sid = this.authHandler.getSIDNoError({ socket });
46
+ if (sid) {
47
+ this.dboBuilder.dboMap.forEach((tableHandler) => {
48
+ tableHandler.activeQueries.forEach((activeQuery) => {
49
+ if (activeQuery.sid === sid) {
50
+ activeQuery.abort();
51
+ }
52
+ });
53
+ });
48
54
  }
55
+
56
+ void this.opts.onSocketDisconnect?.({ socket, dbo: dbo as DBOFullyTyped, db, getUser });
49
57
  });
50
58
 
51
59
  await this.opts.onLog?.({