prostgles-server 4.2.507 → 4.2.508

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 (149) hide show
  1. package/dist/DBSchemaBuilder/DBSchemaBuilder.d.ts +2 -2
  2. package/dist/DBSchemaBuilder/DBSchemaBuilder.d.ts.map +1 -1
  3. package/dist/DBSchemaBuilder/DBSchemaBuilder.spec.js +0 -4
  4. package/dist/DBSchemaBuilder/DBSchemaBuilder.spec.js.map +1 -1
  5. package/dist/DboBuilder/DboBuilder.d.ts +4 -5
  6. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  7. package/dist/DboBuilder/DboBuilder.js +13 -22
  8. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  9. package/dist/DboBuilder/DboBuilderTypes.d.ts +15 -23
  10. package/dist/DboBuilder/DboBuilderTypes.d.ts.map +1 -1
  11. package/dist/DboBuilder/DboBuilderTypes.js.map +1 -1
  12. package/dist/DboBuilder/TableHandler/DataValidator.js +1 -1
  13. package/dist/DboBuilder/TableHandler/DataValidator.js.map +1 -1
  14. package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
  15. package/dist/DboBuilder/TableHandler/TableHandler.js +9 -8
  16. package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
  17. package/dist/DboBuilder/TableHandler/insert/insert.d.ts.map +1 -1
  18. package/dist/DboBuilder/TableHandler/insert/insert.js +1 -1
  19. package/dist/DboBuilder/TableHandler/insert/insert.js.map +1 -1
  20. package/dist/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.js +2 -2
  21. package/dist/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.js.map +1 -1
  22. package/dist/DboBuilder/TableHandler/insertTest.d.ts.map +1 -1
  23. package/dist/DboBuilder/TableHandler/insertTest.js +1 -1
  24. package/dist/DboBuilder/TableHandler/insertTest.js.map +1 -1
  25. package/dist/DboBuilder/TableHandler/updateFile.js +1 -1
  26. package/dist/DboBuilder/TableHandler/updateFile.js.map +1 -1
  27. package/dist/DboBuilder/TableRules/{getValidatedRules.d.ts → getValidatedTableRules.d.ts} +2 -2
  28. package/dist/DboBuilder/TableRules/getValidatedTableRules.d.ts.map +1 -0
  29. package/dist/DboBuilder/TableRules/{getValidatedRules.js → getValidatedTableRules.js} +5 -13
  30. package/dist/DboBuilder/TableRules/getValidatedTableRules.js.map +1 -0
  31. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +3 -7
  32. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  33. package/dist/DboBuilder/ViewHandler/ViewHandler.js +2 -35
  34. package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
  35. package/dist/DboBuilder/ViewHandler/getInfo.d.ts.map +1 -1
  36. package/dist/DboBuilder/ViewHandler/getInfo.js +20 -16
  37. package/dist/DboBuilder/ViewHandler/getInfo.js.map +1 -1
  38. package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.d.ts +2 -2
  39. package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.d.ts.map +1 -1
  40. package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.js +2 -2
  41. package/dist/DboBuilder/ViewHandler/getValidatedSubscribeOptions.js.map +1 -1
  42. package/dist/DboBuilder/ViewHandler/subscribe.js +1 -1
  43. package/dist/DboBuilder/ViewHandler/subscribe.js.map +1 -1
  44. package/dist/DboBuilder/getColumns.d.ts.map +1 -1
  45. package/dist/DboBuilder/getColumns.js +0 -2
  46. package/dist/DboBuilder/getColumns.js.map +1 -1
  47. package/dist/FileManager/FileManager.d.ts.map +1 -1
  48. package/dist/FileManager/FileManager.js +3 -3
  49. package/dist/FileManager/FileManager.js.map +1 -1
  50. package/dist/FileManager/initFileManager.js +1 -1
  51. package/dist/FileManager/initFileManager.js.map +1 -1
  52. package/dist/Prostgles.d.ts +1 -1
  53. package/dist/Prostgles.d.ts.map +1 -1
  54. package/dist/Prostgles.js +9 -1
  55. package/dist/Prostgles.js.map +1 -1
  56. package/dist/PubSubManager/PubSubManager.d.ts +5 -7
  57. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  58. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  59. package/dist/PubSubManager/PubSubManagerUtils.d.ts +1 -0
  60. package/dist/PubSubManager/PubSubManagerUtils.d.ts.map +1 -1
  61. package/dist/PubSubManager/PubSubManagerUtils.js +2 -1
  62. package/dist/PubSubManager/PubSubManagerUtils.js.map +1 -1
  63. package/dist/PubSubManager/addSync.d.ts.map +1 -1
  64. package/dist/PubSubManager/addSync.js +5 -5
  65. package/dist/PubSubManager/addSync.js.map +1 -1
  66. package/dist/PubSubManager/addTrigger.js +1 -1
  67. package/dist/PubSubManager/addTrigger.js.map +1 -1
  68. package/dist/PublishParser/PublishParser.d.ts +1 -2
  69. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  70. package/dist/PublishParser/PublishParser.js +23 -12
  71. package/dist/PublishParser/PublishParser.js.map +1 -1
  72. package/dist/PublishParser/getDBSchemaTable.d.ts +6 -0
  73. package/dist/PublishParser/getDBSchemaTable.d.ts.map +1 -0
  74. package/dist/PublishParser/getDBSchemaTable.js +58 -0
  75. package/dist/PublishParser/getDBSchemaTable.js.map +1 -0
  76. package/dist/PublishParser/getSchemaFromPublish.d.ts +1 -2
  77. package/dist/PublishParser/getSchemaFromPublish.d.ts.map +1 -1
  78. package/dist/PublishParser/getSchemaFromPublish.js +39 -104
  79. package/dist/PublishParser/getSchemaFromPublish.js.map +1 -1
  80. package/dist/PublishParser/getTableRulesWithoutFileTable.d.ts.map +1 -1
  81. package/dist/PublishParser/getTableRulesWithoutFileTable.js +58 -127
  82. package/dist/PublishParser/getTableRulesWithoutFileTable.js.map +1 -1
  83. package/dist/PublishParser/publishTypesAndUtils.d.ts +31 -140
  84. package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
  85. package/dist/PublishParser/publishTypesAndUtils.js +18 -118
  86. package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
  87. package/dist/SyncReplication.d.ts.map +1 -1
  88. package/dist/SyncReplication.js +4 -6
  89. package/dist/SyncReplication.js.map +1 -1
  90. package/dist/TableConfig/TableConfig.d.ts +12 -5
  91. package/dist/TableConfig/TableConfig.d.ts.map +1 -1
  92. package/dist/TableConfig/TableConfig.js +16 -9
  93. package/dist/TableConfig/TableConfig.js.map +1 -1
  94. package/dist/TableConfig/getCreateSchemaQueries.d.ts +4 -9
  95. package/dist/TableConfig/getCreateSchemaQueries.d.ts.map +1 -1
  96. package/dist/TableConfig/getCreateSchemaQueries.js.map +1 -1
  97. package/dist/TableConfig/getTableColumnQueries.js +1 -1
  98. package/dist/TableConfig/getTableColumnQueries.js.map +1 -1
  99. package/dist/TableConfig/getTableConfigSchemaQueries.d.ts +4 -9
  100. package/dist/TableConfig/getTableConfigSchemaQueries.d.ts.map +1 -1
  101. package/dist/WebsocketAPI/getClientSchema.d.ts.map +1 -1
  102. package/dist/WebsocketAPI/getClientSchema.js +3 -3
  103. package/dist/WebsocketAPI/getClientSchema.js.map +1 -1
  104. package/dist/index.js.map +1 -1
  105. package/dist/initProstgles.d.ts +2 -3
  106. package/dist/initProstgles.d.ts.map +1 -1
  107. package/dist/initProstgles.js.map +1 -1
  108. package/dist/runClientRequest.d.ts.map +1 -1
  109. package/dist/runClientRequest.js +4 -8
  110. package/dist/runClientRequest.js.map +1 -1
  111. package/lib/DBSchemaBuilder/DBSchemaBuilder.spec.ts +1 -5
  112. package/lib/DBSchemaBuilder/DBSchemaBuilder.ts +2 -8
  113. package/lib/DboBuilder/DboBuilder.ts +18 -26
  114. package/lib/DboBuilder/DboBuilderTypes.ts +70 -59
  115. package/lib/DboBuilder/TableHandler/DataValidator.ts +1 -1
  116. package/lib/DboBuilder/TableHandler/TableHandler.ts +10 -14
  117. package/lib/DboBuilder/TableHandler/insert/insert.ts +1 -7
  118. package/lib/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.ts +3 -3
  119. package/lib/DboBuilder/TableHandler/insertTest.ts +5 -5
  120. package/lib/DboBuilder/TableHandler/updateFile.ts +1 -1
  121. package/lib/DboBuilder/TableRules/{getValidatedRules.ts → getValidatedTableRules.ts} +3 -10
  122. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +7 -41
  123. package/lib/DboBuilder/ViewHandler/getInfo.ts +24 -20
  124. package/lib/DboBuilder/ViewHandler/getValidatedSubscribeOptions.ts +4 -4
  125. package/lib/DboBuilder/ViewHandler/subscribe.ts +1 -1
  126. package/lib/DboBuilder/getColumns.ts +4 -14
  127. package/lib/FileManager/FileManager.ts +5 -6
  128. package/lib/FileManager/initFileManager.ts +1 -1
  129. package/lib/Prostgles.ts +10 -1
  130. package/lib/PubSubManager/PubSubManager.ts +12 -13
  131. package/lib/PubSubManager/PubSubManagerUtils.ts +1 -0
  132. package/lib/PubSubManager/addSync.ts +4 -7
  133. package/lib/PubSubManager/addTrigger.ts +1 -1
  134. package/lib/PublishParser/PublishParser.ts +30 -17
  135. package/lib/PublishParser/getDBSchemaTable.ts +73 -0
  136. package/lib/PublishParser/getSchemaFromPublish.ts +56 -147
  137. package/lib/PublishParser/getTableRulesWithoutFileTable.ts +74 -162
  138. package/lib/PublishParser/publishTypesAndUtils.ts +41 -167
  139. package/lib/SyncReplication.ts +6 -8
  140. package/lib/TableConfig/TableConfig.ts +25 -11
  141. package/lib/TableConfig/getCreateSchemaQueries.ts +8 -8
  142. package/lib/TableConfig/getTableColumnQueries.ts +1 -1
  143. package/lib/WebsocketAPI/getClientSchema.ts +5 -3
  144. package/lib/index.ts +1 -1
  145. package/lib/initProstgles.ts +2 -3
  146. package/lib/runClientRequest.ts +4 -6
  147. package/package.json +2 -2
  148. package/dist/DboBuilder/TableRules/getValidatedRules.d.ts.map +0 -1
  149. package/dist/DboBuilder/TableRules/getValidatedRules.js.map +0 -1
@@ -117,7 +117,7 @@ export async function initFileManager(this: FileManager, prg: Prostgles) {
117
117
  if (!this.dbo[refTable]) {
118
118
  throw `Referenced table (${refTable}) from fileTable.referencedTables prostgles init config does not exist`;
119
119
  }
120
- const cols = await (this.dbo[refTable] as TableHandler).getColumns();
120
+ const cols = await (this.dbo[refTable]).getColumns();
121
121
 
122
122
  for (const [colName] of Object.entries(tableConfig.referenceColumns)) {
123
123
  const existingCol = cols.find((c) => c.name === colName);
package/lib/Prostgles.ts CHANGED
@@ -27,7 +27,15 @@ import { pushSocketSchema } from "./WebsocketAPI/pushSocketSchema";
27
27
  export type DB = pgPromise.IDatabase<{}, pg.IClient>;
28
28
  export type DBorTx = DB | pgPromise.ITask<{}>;
29
29
 
30
- export const TABLE_METHODS = ["update", "find", "findOne", "insert", "delete", "upsert"] as const;
30
+ export const TABLE_METHODS = [
31
+ "update",
32
+ "find",
33
+ "findOne",
34
+ "insert",
35
+ "insertMany",
36
+ "delete",
37
+ "upsert",
38
+ ] as const satisfies (keyof TableHandler)[];
31
39
 
32
40
  /*
33
41
  1. Connect to db
@@ -51,6 +59,7 @@ const DEFAULT_KEYWORDS = {
51
59
 
52
60
  import { randomUUID } from "crypto";
53
61
  import * as fs from "fs";
62
+ import type { TableHandler } from "./DboBuilder/TableHandler/TableHandler";
54
63
 
55
64
  export class Prostgles {
56
65
  /**
@@ -3,13 +3,7 @@
3
3
  * Licensed under the MIT License. See LICENSE in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
 
6
- import type {
7
- DBHandlerServer,
8
- DboBuilder,
9
- PRGLIOSocket,
10
- TableInfo,
11
- TableOrViewInfo,
12
- } from "../DboBuilder/DboBuilder";
6
+ import type { DBHandlerServer, DboBuilder, PRGLIOSocket } from "../DboBuilder/DboBuilder";
13
7
  import type { PostgresNotifListenManager } from "../PostgresNotifListenManager";
14
8
  import type { DB } from "../Prostgles";
15
9
  import { addSync } from "./addSync";
@@ -19,7 +13,14 @@ import { initPubSubManager } from "./init/initPubSubManager";
19
13
  import { initialiseEventTriggers } from "./initialiseEventTriggers";
20
14
  import { refreshTriggers } from "./refreshTriggers";
21
15
 
22
- import type { AnyObject, FieldFilter, SelectParams, WAL } from "prostgles-types";
16
+ import type {
17
+ AnyObject,
18
+ FieldFilter,
19
+ SelectParams,
20
+ SyncTableInfo,
21
+ TableSchema,
22
+ WAL,
23
+ } from "prostgles-types";
23
24
  import { CHANNELS, getSerialisableError, type SubscribeOptions } from "prostgles-types";
24
25
 
25
26
  import { find, pickKeys } from "prostgles-types";
@@ -56,13 +57,11 @@ export type SyncParams = {
56
57
  is_syncing: boolean;
57
58
  };
58
59
 
59
- export type AddSyncParams = {
60
+ export type AddSyncParams = SyncTableInfo & {
60
61
  socket: PRGLIOSocket;
61
- table_info: TableInfo;
62
+ table_info: TableSchema;
62
63
  table_rules: ParsedTableRule;
63
- synced_field: string;
64
64
  allow_delete?: boolean;
65
- id_fields: string[];
66
65
  filter: object;
67
66
  params: {
68
67
  select: FieldFilter;
@@ -99,7 +98,7 @@ export type SubscriptionParams = {
99
98
  viewOptions?: ViewSubscriptionOptions;
100
99
  parentSubParams: Omit<SubscriptionParams, "parentSubParams"> | undefined;
101
100
 
102
- table_info: TableOrViewInfo;
101
+ table_info: TableSchema;
103
102
 
104
103
  /* Used as input */
105
104
  table_rules?: ParsedTableRule;
@@ -27,6 +27,7 @@ export const EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID =
27
27
  type PGP = pgPromise.IMain<{}, pg.IClient>;
28
28
  export const pgp: PGP = pgPromise({});
29
29
  export const asValue = (v: any, castAs?: ":csv") => pgp.as.format(`$1${castAs ?? ""}`, [v]);
30
+ export const DEFAULT_SYNC_THROTTLE = 100;
30
31
  export const DEFAULT_SYNC_BATCH_SIZE = 50;
31
32
 
32
33
  let lastLog: { count: number; msg: string } | undefined;
@@ -1,6 +1,6 @@
1
1
  import { find, tryCatchV2 } from "prostgles-types";
2
2
  import type { AddSyncParams, BasicCallback, PubSubManager } from "./PubSubManager";
3
- import { DEFAULT_SYNC_BATCH_SIZE, parseCondition } from "./PubSubManagerUtils";
3
+ import { parseCondition } from "./PubSubManagerUtils";
4
4
 
5
5
  /**
6
6
  * Returns a sync channel
@@ -17,11 +17,9 @@ export async function addSync(
17
17
  table_info = null,
18
18
  table_rules,
19
19
  synced_field = null,
20
- id_fields = [],
21
20
  filter = {},
22
21
  params,
23
22
  condition = "",
24
- throttle = 0,
25
23
  } = syncParams;
26
24
  const conditionParsed = parseCondition(condition);
27
25
  if (!socket || !table_info) throw "socket or table_info missing";
@@ -33,18 +31,17 @@ export async function addSync(
33
31
 
34
32
  this.upsertSocket(socket);
35
33
 
34
+ const syncConfig = this.dboBuilder.prostgles.tableConfigurator?.getTableSyncConfig(table_name);
35
+ if (!syncConfig) throw `Sync not configured for table ${table_name}`;
36
36
  const upsertSync = () => {
37
37
  const newSync = {
38
38
  channel_name: channelName,
39
39
  table_name,
40
40
  filter,
41
41
  condition: conditionParsed,
42
- synced_field,
43
42
  sid,
44
- id_fields,
45
43
  table_rules,
46
- throttle: Math.max(throttle || 0, table_rules.sync?.throttle || 0),
47
- batch_size: table_rules.sync?.batch_size || DEFAULT_SYNC_BATCH_SIZE,
44
+ ...syncConfig,
48
45
  socket_id: socket.id,
49
46
  is_sync: true,
50
47
  last_synced: 0,
@@ -26,7 +26,7 @@ export async function addTrigger(
26
26
  condition = "TRUE";
27
27
  }
28
28
 
29
- if (this.dbo[table_name]?.tableOrViewInfo?.isHyperTable) {
29
+ if (this.dbo[table_name]?.tableOrViewInfo.isHyperTable) {
30
30
  throw "Triggers do not work on timescaledb hypertables due to bug:\nhttps://github.com/timescale/timescaledb/issues/1084";
31
31
  }
32
32
 
@@ -1,4 +1,4 @@
1
- import { includes } from "prostgles-types";
1
+ import { getObjectEntries, includes, SQL_COMMAND_TABLE_METHODS } from "prostgles-types";
2
2
  import { getClientRequestIPsInfo } from "../Auth/AuthHandler";
3
3
  import type { AuthClientRequest, AuthResultWithSID } from "../Auth/AuthTypes";
4
4
  import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
@@ -17,7 +17,6 @@ import type {
17
17
  PublishParams,
18
18
  } from "./publishTypesAndUtils";
19
19
  import {
20
- RULE_TO_METHODS,
21
20
  parsePublishTableRule,
22
21
  type PermissionScope,
23
22
  type PublishObject,
@@ -37,7 +36,9 @@ export class PublishParser {
37
36
  // eslint-disable-next-line @typescript-eslint/unbound-method
38
37
  this.publishRawSQL = prostgles.opts.publishRawSQL;
39
38
  const { dbo, db } = prostgles;
40
- if (!dbo || !db) throw "INTERNAL ERROR: dbo and/or db missing";
39
+ if (!dbo || !db) {
40
+ throw "INTERNAL ERROR: dbo and/or db missing";
41
+ }
41
42
  this.dbo = dbo;
42
43
  this.db = db;
43
44
  }
@@ -83,14 +84,14 @@ export class PublishParser {
83
84
  /**
84
85
  * Parses the first level of publish. (If false then nothing if * then all tables and views)
85
86
  */
86
- async getPublishAsObject(
87
+ async getPublishObject(
87
88
  clientReq: AuthClientRequest,
88
89
  clientInfo: AuthResultWithSID | undefined,
89
90
  ): Promise<PublishObject | undefined> {
90
91
  const publishParams = await this.getPublishParams(clientReq, clientInfo);
91
- const _publish = await applyParamsIfFunc(this.publish, publishParams);
92
+ const publish = await applyParamsIfFunc(this.publish, publishParams);
92
93
 
93
- if (_publish === "*") {
94
+ if (publish === "*") {
94
95
  const publish: PublishObject = {};
95
96
  this.prostgles.dboBuilder.tablesOrViews?.map((tov) => {
96
97
  publish[tov.name] = "*";
@@ -98,7 +99,7 @@ export class PublishParser {
98
99
  return publish;
99
100
  }
100
101
 
101
- return _publish || undefined;
102
+ return publish || undefined;
102
103
  }
103
104
 
104
105
  async getValidatedRequestRuleWusr(
@@ -124,13 +125,12 @@ export class PublishParser {
124
125
 
125
126
  /* Must be local request -> allow everything */
126
127
  if (!clientReq) {
127
- return RULE_TO_METHODS.reduce(
128
- (a, v) => ({
129
- ...a,
130
- [v.rule]: v.no_limits,
131
- }),
132
- {},
133
- );
128
+ return {
129
+ select: { fields: "*", filterFields: "*", orderByFields: "*" },
130
+ insert: { returningFields: "*", fields: "*" },
131
+ update: { fields: "*", returningFields: "*", filterFields: "*" },
132
+ delete: { returningFields: "*", filterFields: "*" },
133
+ };
134
134
  }
135
135
 
136
136
  /* Must be from socket. Must have a publish */
@@ -160,7 +160,10 @@ export class PublishParser {
160
160
  ) {
161
161
  if (!command || !tableName) throw "command OR tableName are missing";
162
162
 
163
- const rule = RULE_TO_METHODS.find(({ methods }) => includes(methods, command));
163
+ const [rule] =
164
+ getObjectEntries(SQL_COMMAND_TABLE_METHODS).find(([_, methods]) =>
165
+ includes(methods, command),
166
+ ) ?? [];
164
167
  if (!rule) {
165
168
  throw "Invalid command: " + command;
166
169
  }
@@ -170,7 +173,15 @@ export class PublishParser {
170
173
  // Allow all commands
171
174
  } else {
172
175
  const tableScope = scope.tables;
173
- if (!tableScope?.[tableName] || !tableScope[tableName][rule.sqlRule]) {
176
+ const tableScopeCommands = tableScope?.[tableName];
177
+ const methodAllowedInScope =
178
+ tableScopeCommands &&
179
+ (rule === "schema" ?
180
+ getObjectEntries(tableScopeCommands).some(([_, value]) => {
181
+ return value;
182
+ })
183
+ : tableScopeCommands[rule]);
184
+ if (!methodAllowedInScope) {
174
185
  throw `Invalid or disallowed command: ${tableName}.${command}. The PermissionsScope does not allow this command.`;
175
186
  }
176
187
  }
@@ -185,7 +196,9 @@ export class PublishParser {
185
196
  }
186
197
  }
187
198
 
188
- if (!tableRule[rule.rule]) {
199
+ const isAllowed =
200
+ rule === "schema" ? getObjectEntries(tableRule).some(([_, value]) => value) : tableRule[rule];
201
+ if (!isAllowed) {
189
202
  throw {
190
203
  stack: ["getValidatedRequestRule()"],
191
204
  message: `Invalid or disallowed command: ${tableName}.${command}`,
@@ -0,0 +1,73 @@
1
+ import { getObjectEntries, includes, type DBSchemaTable } from "prostgles-types";
2
+ import type { AuthClientRequest } from "../Auth/AuthTypes";
3
+ import { getErrorAsObject } from "../DboBuilder/dboBuilderUtils";
4
+ import type { TableHandler } from "../DboBuilder/TableHandler/TableHandler";
5
+ import { TABLE_METHODS } from "../Prostgles";
6
+ import type { ParsedTableRule, PermissionScope, PublishParser } from "./PublishParser";
7
+ import { getAllowedTableMethods } from "prostgles-types";
8
+
9
+ export const getDBSchemaTable = async (
10
+ publishParser: PublishParser,
11
+ tableHandler: TableHandler,
12
+ parsedTableRule: ParsedTableRule,
13
+ clientReq: AuthClientRequest,
14
+ scope: PermissionScope | undefined,
15
+ ): Promise<DBSchemaTable> => {
16
+ const tableName = tableHandler.name;
17
+
18
+ if (getObjectEntries(parsedTableRule).every(([_ruleName, ruleOptions]) => !ruleOptions)) {
19
+ throw new Error("At least one of the rules must be defined for " + tableName);
20
+ }
21
+ const info = await tableHandler.getInfo(undefined, undefined, undefined, parsedTableRule, {
22
+ ...clientReq,
23
+ isRemoteRequest: {},
24
+ });
25
+ const columns = await tableHandler.getColumns(undefined, undefined, undefined, parsedTableRule, {
26
+ ...clientReq,
27
+ isRemoteRequest: {},
28
+ });
29
+ const allowedCommands = getAllowedTableMethods(info);
30
+ for (const method of allowedCommands) {
31
+ if (method === "getInfo" || method === "getColumns") {
32
+ continue;
33
+ }
34
+ try {
35
+ publishParser.validateRequestRule(
36
+ {
37
+ tableName,
38
+ command: method,
39
+ clientReq,
40
+ },
41
+ parsedTableRule,
42
+ scope,
43
+ );
44
+ } catch (e) {
45
+ console.error(`${tableName}.${method}`, e);
46
+ throw {
47
+ ...getErrorAsObject(e),
48
+ publishPath: `publish.${tableName}.${method}`,
49
+ };
50
+ }
51
+ /** Crucial in ensuring the published client tableHandler methods work without issues */
52
+ if (publishParser.prostgles.opts.testRulesOnConnect && includes(TABLE_METHODS, method)) {
53
+ await tableHandler.dboBuilder.dboMap.get(tableName)?.[method](
54
+ //@ts-expect-error
55
+ method === "insertMany" ? [] : {},
56
+ {},
57
+ undefined,
58
+ parsedTableRule,
59
+ {
60
+ ...clientReq,
61
+ isRemoteRequest: {},
62
+ testRule: true,
63
+ },
64
+ );
65
+ }
66
+ }
67
+
68
+ return {
69
+ ...info,
70
+ name: tableHandler.name,
71
+ columns,
72
+ } satisfies DBSchemaTable;
73
+ };
@@ -1,16 +1,10 @@
1
- import type {
2
- DBSchemaTable,
3
- TableInfo,
4
- TableSchemaErrors,
5
- TableSchemaForClient,
6
- } from "prostgles-types";
7
- import { getKeys, includes, isEmpty, isObject, pickKeys, type AnyObject } from "prostgles-types";
1
+ import type { DBSchemaTable, TableSchemaErrors } from "prostgles-types";
2
+ import { isEmpty, isObject } from "prostgles-types";
8
3
  import type { AuthClientRequest, AuthResultWithSID } from "../Auth/AuthTypes";
9
- import { getErrorAsObject } from "../DboBuilder/DboBuilder";
10
4
  import type { TableHandler } from "../DboBuilder/TableHandler/TableHandler";
11
- import { TABLE_METHODS } from "../Prostgles";
12
5
  import type { PublishParser } from "./PublishParser";
13
6
  import { type PermissionScope, type PublishObject } from "./PublishParser";
7
+ import { getDBSchemaTable } from "./getDBSchemaTable";
14
8
 
15
9
  type Args = AuthClientRequest & {
16
10
  userData: AuthResultWithSID | undefined;
@@ -22,13 +16,13 @@ export async function getSchemaFromPublish(
22
16
  { userData, ...clientReq }: Args,
23
17
  scope: PermissionScope | undefined,
24
18
  ): Promise<{
25
- schema: TableSchemaForClient;
26
19
  tables: DBSchemaTable[];
27
20
  tableSchemaErrors: TableSchemaErrors;
28
21
  }> {
29
- const schema: TableSchemaForClient = {};
30
22
  const tableSchemaErrors: TableSchemaErrors = {};
31
- let tables: DBSchemaTable[] = [];
23
+ const tables: DBSchemaTable[] = [];
24
+
25
+ const txKey = !this.prostgles.opts.transactions ? "" : "tx";
32
26
 
33
27
  try {
34
28
  /* Publish tables and views based on socket */
@@ -37,156 +31,71 @@ export async function getSchemaFromPublish(
37
31
  if (clientInfo === "new-session-redirect") {
38
32
  throw "new-session-redirect";
39
33
  }
40
- let _publish: PublishObject | undefined;
34
+ let publish: PublishObject | undefined;
41
35
  try {
42
- _publish = await this.getPublishAsObject(clientReq, clientInfo);
36
+ publish = await this.getPublishObject(clientReq, clientInfo);
43
37
  } catch (err) {
44
38
  console.error("Error within then Publish function ", err);
45
39
  throw err;
46
40
  }
47
41
 
48
- if (_publish && Object.keys(_publish).length) {
49
- let txKey = "tx";
50
- if (!this.prostgles.opts.transactions) txKey = "";
51
- if (typeof this.prostgles.opts.transactions === "string")
52
- txKey = this.prostgles.opts.transactions;
53
-
54
- const tableNames = Object.keys(_publish).filter((k) => !txKey || txKey !== k);
42
+ if (!publish || !Object.keys(publish).length) {
43
+ return { tables, tableSchemaErrors };
44
+ }
45
+ const tableNames = Object.keys(publish).filter((k) => !txKey || txKey !== k);
55
46
 
56
- const fileTableName = this.prostgles.fileManager?.tableName;
57
- if (
58
- fileTableName &&
59
- this.dbo[fileTableName]?.is_media &&
60
- !tableNames.includes(fileTableName)
61
- ) {
62
- const isReferenced = this.prostgles.dboBuilder.tablesOrViews?.some((t) =>
63
- t.columns.some((c) => c.references?.some((r) => r.ftable === fileTableName)),
64
- );
65
- if (isReferenced) {
66
- tableNames.unshift(fileTableName);
67
- }
47
+ /**
48
+ * Add file table to the list of published tables if it's referenced by other published tables.
49
+ * Access to the file table is controlled through the publish rules of the tables referencing it.
50
+ */
51
+ const fileTableName = this.prostgles.fileManager?.tableName;
52
+ if (fileTableName && this.dbo[fileTableName]?.is_media && !tableNames.includes(fileTableName)) {
53
+ const isReferenced = this.prostgles.dboBuilder.tablesOrViews?.some((t) =>
54
+ t.columns.some((c) => c.references?.some((r) => r.ftable === fileTableName)),
55
+ );
56
+ if (isReferenced) {
57
+ tableNames.unshift(fileTableName);
68
58
  }
69
- await Promise.all(
70
- tableNames.map(async (tableName) => {
71
- const { canSubscribe, tablesOrViews } = this.prostgles.dboBuilder;
72
- if (!this.dbo[tableName]) {
73
- const errMsg = [
74
- `Table ${tableName} does not exist`,
75
- `Expecting one of: ${JSON.stringify(tablesOrViews?.map((tov) => tov.name))}`,
76
- ].join("\n");
77
- throw errMsg;
78
- }
79
-
80
- const parsedTableRule = await this.getTableRules(
81
- { clientReq, tableName },
82
- clientInfo,
83
- scope,
84
- );
85
-
86
- if (!parsedTableRule || isEmpty(parsedTableRule)) return;
87
- if (!isObject(parsedTableRule)) {
88
- throw `Invalid tableRules for table ${tableName}. Expecting an object`;
89
- }
90
-
91
- schema[tableName] = {};
92
- const tableSchema = schema[tableName];
93
- const methods = getKeys(parsedTableRule).filter(
94
- (m) => canSubscribe || !includes(SUBSCRIBE_METHODS, m),
95
- );
96
- let tableInfo: TableInfo | undefined;
97
- let tableColumns: DBSchemaTable["columns"] | undefined;
98
-
99
- await Promise.all(
100
- methods
101
- .filter((m) => m !== "select")
102
- .map(async (method) => {
103
- if (method === "sync") {
104
- /* Pass sync info */
105
- tableSchema[method] = parsedTableRule[method];
106
- } else if (includes(getKeys(parsedTableRule), method) && parsedTableRule[method]) {
107
- //@ts-ignore
108
- tableSchema[method] =
109
- method === "insert" ?
110
- pickKeys(parsedTableRule[method], ["allowedNestedInserts"])
111
- : ({} as AnyObject);
59
+ }
112
60
 
113
- /* Test for issues with the common table CRUD methods () */
114
- if (includes(TABLE_METHODS, method)) {
115
- try {
116
- this.validateRequestRule(
117
- {
118
- tableName,
119
- command: method,
120
- clientReq,
121
- },
122
- parsedTableRule,
123
- scope,
124
- );
125
- if (this.prostgles.opts.testRulesOnConnect) {
126
- await (this.dbo[tableName] as TableHandler)[method](
127
- {},
128
- {},
129
- undefined,
130
- parsedTableRule,
131
- {
132
- ...clientReq,
133
- isRemoteRequest: {},
134
- testRule: true,
135
- },
136
- );
137
- }
138
- } catch (e) {
139
- console.error(`${tableName}.${method}`, e);
140
- tableSchemaErrors[tableName] ??= {};
141
- tableSchemaErrors[tableName][method] = {
142
- error: "Internal publish error. Check server logs",
143
- };
61
+ await Promise.all(
62
+ tableNames.map(async (tableName) => {
63
+ const { tablesOrViews } = this.prostgles.dboBuilder;
64
+ const tableHandler = this.dbo[tableName];
65
+ if (!tableHandler) {
66
+ const errMsg = [
67
+ `Table ${tableName} does not exist`,
68
+ `Expecting one of: ${JSON.stringify(tablesOrViews?.map((tov) => tov.name))}`,
69
+ ].join("\n");
70
+ throw errMsg;
71
+ }
144
72
 
145
- throw {
146
- ...getErrorAsObject(e),
147
- publish_path: `publish.${tableName}.${method}`,
148
- };
149
- }
150
- }
73
+ const parsedTableRule = await this.getTableRules(
74
+ { clientReq, tableName },
75
+ clientInfo,
76
+ scope,
77
+ );
151
78
 
152
- if (method === "getInfo" || method === "getColumns") {
153
- this.validateRequestRule(
154
- { tableName, command: method, clientReq },
155
- parsedTableRule,
156
- scope,
157
- );
158
- const res = await (this.dbo[tableName] as TableHandler)[method](
159
- undefined,
160
- undefined,
161
- undefined,
162
- parsedTableRule,
163
- { ...clientReq, isRemoteRequest: {} },
164
- );
165
- if (method === "getInfo") {
166
- tableInfo = res as TableInfo;
167
- } else {
168
- tableColumns = res as DBSchemaTable["columns"];
169
- }
170
- }
171
- }
172
- }),
173
- );
79
+ if (!parsedTableRule || isEmpty(parsedTableRule)) return;
80
+ if (!isObject(parsedTableRule)) {
81
+ throw `Invalid tableRules for table ${tableName}. Expecting an object`;
82
+ }
174
83
 
175
- if (tableInfo && tableColumns) {
176
- tables.push({
177
- name: tableName,
178
- info: tableInfo,
179
- columns: tableColumns,
180
- });
181
- }
182
- }),
183
- );
184
- }
84
+ const tableSchema = await getDBSchemaTable(
85
+ this,
86
+ tableHandler,
87
+ parsedTableRule,
88
+ clientReq,
89
+ scope,
90
+ );
91
+ tables.push(tableSchema);
92
+ }),
93
+ );
185
94
  } catch (error) {
186
95
  console.error("Publish error", error);
187
96
  throw error;
188
97
  }
189
98
 
190
- tables = tables.sort((a, b) => a.name.localeCompare(b.name));
191
- return { schema, tables, tableSchemaErrors };
99
+ // tables = tables.sort((a, b) => a.name.localeCompare(b.name));
100
+ return { tables, tableSchemaErrors };
192
101
  }