prostgles-server 4.2.624 → 4.2.625

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 (135) hide show
  1. package/dist/Audit/AuditTable.d.ts +2 -1
  2. package/dist/Audit/AuditTable.d.ts.map +1 -1
  3. package/dist/Audit/AuditTable.js +3 -2
  4. package/dist/Audit/AuditTable.js.map +1 -1
  5. package/dist/Audit/getAuditTableRules.d.ts +7 -0
  6. package/dist/Audit/getAuditTableRules.d.ts.map +1 -0
  7. package/dist/Audit/getAuditTableRules.js +191 -0
  8. package/dist/Audit/getAuditTableRules.js.map +1 -0
  9. package/dist/Audit/getAuditTriggerConfig.d.ts.map +1 -1
  10. package/dist/Audit/getAuditTriggerConfig.js +14 -1
  11. package/dist/Audit/getAuditTriggerConfig.js.map +1 -1
  12. package/dist/DBSchemaBuilder/getDBGeneratedSchema.d.ts.map +1 -1
  13. package/dist/DBSchemaBuilder/getDBGeneratedSchema.js +1 -2
  14. package/dist/DBSchemaBuilder/getDBGeneratedSchema.js.map +1 -1
  15. package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts +10 -5
  16. package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
  17. package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +90 -71
  18. package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
  19. package/dist/DboBuilder/QueryBuilder/getJoinQuery.d.ts.map +1 -1
  20. package/dist/DboBuilder/QueryBuilder/getJoinQuery.js +3 -2
  21. package/dist/DboBuilder/QueryBuilder/getJoinQuery.js.map +1 -1
  22. package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts +2 -2
  23. package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts.map +1 -1
  24. package/dist/DboBuilder/QueryBuilder/getNewQuery.js +53 -116
  25. package/dist/DboBuilder/QueryBuilder/getNewQuery.js.map +1 -1
  26. package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts +18 -0
  27. package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts.map +1 -0
  28. package/dist/DboBuilder/QueryBuilder/getQuerySource.js +29 -0
  29. package/dist/DboBuilder/QueryBuilder/getQuerySource.js.map +1 -0
  30. package/dist/DboBuilder/QueryBuilder/getSelectQuery.d.ts.map +1 -1
  31. package/dist/DboBuilder/QueryBuilder/getSelectQuery.js +6 -2
  32. package/dist/DboBuilder/QueryBuilder/getSelectQuery.js.map +1 -1
  33. package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts +13 -0
  34. package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts.map +1 -0
  35. package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js +57 -0
  36. package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js.map +1 -0
  37. package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
  38. package/dist/DboBuilder/TableHandler/TableHandler.js +2 -1
  39. package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
  40. package/dist/DboBuilder/TableHandler/delete.d.ts.map +1 -1
  41. package/dist/DboBuilder/TableHandler/delete.js +2 -1
  42. package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
  43. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts.map +1 -1
  44. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +2 -1
  45. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js.map +1 -1
  46. package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
  47. package/dist/DboBuilder/TableHandler/update.js +2 -1
  48. package/dist/DboBuilder/TableHandler/update.js.map +1 -1
  49. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +6 -16
  50. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  51. package/dist/DboBuilder/ViewHandler/ViewHandler.js +2 -7
  52. package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
  53. package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
  54. package/dist/DboBuilder/ViewHandler/find.js +1 -1
  55. package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
  56. package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts +1 -1
  57. package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts.map +1 -1
  58. package/dist/DboBuilder/ViewHandler/getExistsCondition.js +24 -13
  59. package/dist/DboBuilder/ViewHandler/getExistsCondition.js.map +1 -1
  60. package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts +4 -1
  61. package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts.map +1 -1
  62. package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js +20 -14
  63. package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js.map +1 -1
  64. package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts +7 -3
  65. package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts.map +1 -1
  66. package/dist/DboBuilder/ViewHandler/prepareWhere.js +30 -23
  67. package/dist/DboBuilder/ViewHandler/prepareWhere.js.map +1 -1
  68. package/dist/DboBuilder/getCondition.d.ts +2 -1
  69. package/dist/DboBuilder/getCondition.d.ts.map +1 -1
  70. package/dist/DboBuilder/getCondition.js +9 -8
  71. package/dist/DboBuilder/getCondition.js.map +1 -1
  72. package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
  73. package/dist/DboBuilder/getSubscribeRelatedTables.js +3 -2
  74. package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
  75. package/dist/DboBuilder/parseUpdateRules.d.ts.map +1 -1
  76. package/dist/DboBuilder/parseUpdateRules.js +3 -2
  77. package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
  78. package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.d.ts +2 -2
  79. package/dist/Prostgles.d.ts.map +1 -1
  80. package/dist/Prostgles.js +2 -0
  81. package/dist/Prostgles.js.map +1 -1
  82. package/dist/ProstglesContext.spec.js +25 -0
  83. package/dist/ProstglesContext.spec.js.map +1 -1
  84. package/dist/PubSubManager/PubSubManager.d.ts +1 -1
  85. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  86. package/dist/PublishParser/PublishParser.js +15 -4
  87. package/dist/PublishParser/PublishParser.js.map +1 -1
  88. package/dist/PublishParser/applyScopeToTableRules.d.ts +0 -1
  89. package/dist/PublishParser/applyScopeToTableRules.d.ts.map +1 -1
  90. package/dist/PublishParser/applyScopeToTableRules.js +3 -7
  91. package/dist/PublishParser/applyScopeToTableRules.js.map +1 -1
  92. package/dist/PublishParser/getPublishedTableNames.d.ts.map +1 -1
  93. package/dist/PublishParser/getPublishedTableNames.js +16 -0
  94. package/dist/PublishParser/getPublishedTableNames.js.map +1 -1
  95. package/dist/PublishParser/publishTypesAndUtils.d.ts +0 -4
  96. package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
  97. package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
  98. package/dist/TableConfig/getColumnSQLDefinitionQuery.d.ts.map +1 -1
  99. package/dist/TableConfig/getColumnSQLDefinitionQuery.js +1 -2
  100. package/dist/TableConfig/getColumnSQLDefinitionQuery.js.map +1 -1
  101. package/dist/index.d.ts +1 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +2 -1
  104. package/dist/index.js.map +1 -1
  105. package/lib/Audit/AuditTable.ts +4 -3
  106. package/lib/Audit/getAuditTableRules.ts +288 -0
  107. package/lib/Audit/getAuditTriggerConfig.ts +14 -1
  108. package/lib/DBSchemaBuilder/getDBGeneratedSchema.ts +1 -2
  109. package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +118 -90
  110. package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +3 -2
  111. package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +111 -194
  112. package/lib/DboBuilder/QueryBuilder/getQuerySource.ts +55 -0
  113. package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +8 -2
  114. package/lib/DboBuilder/QueryBuilder/parseJoinSelect.ts +73 -0
  115. package/lib/DboBuilder/TableHandler/TableHandler.ts +3 -6
  116. package/lib/DboBuilder/TableHandler/delete.ts +2 -1
  117. package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +2 -1
  118. package/lib/DboBuilder/TableHandler/update.ts +2 -1
  119. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +6 -12
  120. package/lib/DboBuilder/ViewHandler/find.ts +0 -1
  121. package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +35 -28
  122. package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +22 -14
  123. package/lib/DboBuilder/ViewHandler/prepareWhere.ts +48 -27
  124. package/lib/DboBuilder/getCondition.ts +11 -10
  125. package/lib/DboBuilder/getSubscribeRelatedTables.ts +3 -2
  126. package/lib/DboBuilder/parseUpdateRules.ts +3 -2
  127. package/lib/Prostgles.ts +1 -0
  128. package/lib/ProstglesContext.spec.ts +30 -0
  129. package/lib/PublishParser/PublishParser.ts +33 -8
  130. package/lib/PublishParser/applyScopeToTableRules.ts +1 -7
  131. package/lib/PublishParser/getPublishedTableNames.ts +22 -0
  132. package/lib/PublishParser/publishTypesAndUtils.ts +0 -5
  133. package/lib/TableConfig/getColumnSQLDefinitionQuery.ts +8 -2
  134. package/lib/index.ts +1 -0
  135. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
- import type { AnyObject, EXISTS_KEY, FieldFilter } from "prostgles-types";
2
- import { EXISTS_KEYS, asName } from "prostgles-types";
3
- import type { LocalParams, ExistsFilterConfig } from "../DboBuilder";
4
- import type { ViewHandler } from "./ViewHandler";
1
+ import type { EXISTS_KEY } from "prostgles-types";
2
+ import { EXISTS_KEYS } from "prostgles-types";
5
3
  import type { ParsedTableRule } from "../../PublishParser/PublishParser";
6
- import type { TableHandler } from "../TableHandler/TableHandler";
7
- import { getTableJoinQuery } from "./getTableJoinQuery";
4
+ import type { ExistsFilterConfig, LocalParams } from "../DboBuilder";
5
+ import { getQuerySourceSQL } from "../QueryBuilder/getQuerySource";
6
+ import { getTableJoinAlias, getTableJoinQuery } from "./getTableJoinQuery";
7
+ import type { ViewHandler } from "./ViewHandler";
8
+ import { prepareWhere } from "./prepareWhere";
8
9
 
9
10
  export async function getExistsCondition(
10
11
  this: ViewHandler,
@@ -25,17 +26,22 @@ export async function getExistsCondition(
25
26
  };
26
27
  }
27
28
 
28
- let t2Rules: ParsedTableRule | undefined = undefined,
29
- forcedFilter: AnyObject | undefined,
30
- filterFields: FieldFilter | undefined;
31
-
32
29
  /* Check if allowed to view data - forcedFilters will bypass this check through isForcedFilterBypass */
33
30
  if (localParams?.isRemoteRequest && !localParams.clientReq) {
34
31
  throw "Unexpected: localParams isRemoteRequest and missing clientReq";
35
32
  }
33
+
34
+ let targetTableRules: ParsedTableRule | undefined = undefined;
36
35
  const targetTable = eConfig.isJoined ? eConfig.parsedPath.at(-1)!.table : eConfig.targetTable;
37
- if (localParams?.clientReq && this.dboBuilder.publishParser) {
38
- t2Rules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr(
36
+ const tableHandler = this.dboBuilder.dboMap.get(targetTable);
37
+ if (!tableHandler) {
38
+ throw `Table handler for ${targetTable} not found`;
39
+ }
40
+ if (localParams?.clientReq) {
41
+ if (!this.dboBuilder.publishParser) {
42
+ throw "Unexpected: missing publishParser";
43
+ }
44
+ targetTableRules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr(
39
45
  {
40
46
  tableName: targetTable,
41
47
  command: "find",
@@ -44,27 +50,27 @@ export async function getExistsCondition(
44
50
  localParams.scope,
45
51
  );
46
52
 
47
- if (!t2Rules.select) throw "Disallowed";
48
- ({ forcedFilter, filterFields } = t2Rules.select);
53
+ if (!targetTableRules.select) throw "Disallowed";
49
54
  }
50
55
 
51
- const tableHandler = this.dboBuilder.dbo[targetTable] as TableHandler;
52
- const finalWhere = (
53
- await tableHandler.prepareWhere({
54
- select: undefined,
55
- filter: targetTableFilter,
56
- forcedFilter,
57
- filterFields,
58
- addWhere: false,
59
- tableAlias: undefined,
60
- localParams,
61
- tableRule: t2Rules,
62
- })
63
- ).where;
56
+ const targetAlias =
57
+ eConfig.isJoined ? getTableJoinAlias(targetTable, eConfig.parsedPath.length - 1) : undefined;
58
+ const whereOpts = await prepareWhere(tableHandler, {
59
+ select: undefined,
60
+ selectParams: {},
61
+ filter: targetTableFilter,
62
+ forcedFilter: targetTableRules?.select?.forcedFilter,
63
+ filterFields: targetTableRules?.select?.filterFields,
64
+ tableRule: targetTableRules,
65
+ addWhere: false,
66
+ tableAlias: targetAlias,
67
+ localParams,
68
+ });
69
+ const { source: targetSource, where: finalWhere } = whereOpts;
64
70
 
65
71
  let innerQuery = [
66
72
  `SELECT 1`,
67
- `FROM ${asName(targetTable)}`,
73
+ `FROM ${getQuerySourceSQL(targetSource)}`,
68
74
  `${finalWhere ? `WHERE ${finalWhere}` : ""}`,
69
75
  ].join("\n");
70
76
 
@@ -74,6 +80,7 @@ export async function getExistsCondition(
74
80
  rootTableAlias: rootTableAlias ?? rootTable,
75
81
  type: "EXISTS",
76
82
  finalWhere,
83
+ finalTableExpression: targetSource.expression,
77
84
  });
78
85
  innerQuery = query;
79
86
  }
@@ -1,10 +1,12 @@
1
1
  import { asName } from "prostgles-types";
2
+ import type { PGIdentifier } from "../DboBuilder";
2
3
  import type { ParsedJoinPath } from "./parseJoinPath";
3
4
 
4
5
  type getTableJoinsArgs = {
5
6
  rootTableAlias: string;
6
7
  type: "INNER" | "LEFT" | "EXISTS";
7
8
  finalWhere?: string;
9
+ finalTableExpression?: string;
8
10
  path: ParsedJoinPath[];
9
11
  };
10
12
  export const getTableJoinQuery = ({
@@ -12,14 +14,14 @@ export const getTableJoinQuery = ({
12
14
  type,
13
15
  rootTableAlias,
14
16
  finalWhere,
17
+ finalTableExpression,
15
18
  }: getTableJoinsArgs): { targetAlias: string; query: string } => {
16
19
  const [firstPath] = path;
17
20
  if (!firstPath) {
18
21
  throw `Cannot create join query for empty path`;
19
22
  }
20
- const aliasSufix = "jd";
21
23
  const getTableAlias = (table: string, pathIndex: number) =>
22
- asName(`${aliasSufix}_${pathIndex}_${table}`);
24
+ getTableJoinAlias(table, pathIndex).escaped;
23
25
 
24
26
  const query = path
25
27
  .map(({ table, on }, i) => {
@@ -45,19 +47,19 @@ export const getTableJoinQuery = ({
45
47
  */
46
48
  const whereJoinCondition =
47
49
  isLast && isExists ?
48
- `WHERE (${getJoinOnCondition({
49
- on: firstPath.on,
50
- leftAlias: rootTableAlias,
51
- rightAlias: getTableAlias(firstPath.table, 0),
52
- })})`
50
+ `WHERE (${[
51
+ getJoinOnCondition({
52
+ on: firstPath.on,
53
+ leftAlias: rootTableAlias,
54
+ rightAlias: getTableAlias(firstPath.table, 0),
55
+ }),
56
+ finalWhere,
57
+ ]
58
+ .filter(Boolean)
59
+ .join(") AND (")})`
53
60
  : "";
54
61
 
55
- const tableSelect =
56
- isExists && isLast ?
57
- [`(`, ` SELECT *`, ` FROM ${tableName}`, finalWhere ? ` WHERE ${finalWhere}` : "", `)`]
58
- .filter((v) => v)
59
- .join("\n")
60
- : tableName;
62
+ const tableSelect = isLast ? (finalTableExpression ?? tableName) : tableName;
61
63
  if (isExists && isFirst) {
62
64
  return [`SELECT 1`, `FROM ${tableSelect} ${tableAlias}`, whereJoinCondition]
63
65
  .filter((v) => v)
@@ -76,6 +78,12 @@ export const getTableJoinQuery = ({
76
78
  };
77
79
  };
78
80
 
81
+ export const getTableJoinAlias = (table: string, pathIndex: number): PGIdentifier => {
82
+ const prefix = "jd";
83
+ const raw = `${prefix}_${pathIndex}_${table}`;
84
+ return { raw, escaped: asName(raw) };
85
+ };
86
+
79
87
  type GetJoinOnConditionArgs = {
80
88
  on: Record<string, string>[];
81
89
  leftAlias: string;
@@ -95,7 +103,7 @@ export const getJoinOnConditions = ({
95
103
  .map(([leftCol, rightCol]) => {
96
104
  return `${leftAlias}.${getLeftColName(leftCol)} = ${rightAlias}.${getRightColName(rightCol)}`;
97
105
  })
98
- .join(" AND ")
106
+ .join(" AND "),
99
107
  );
100
108
  };
101
109
 
@@ -1,9 +1,10 @@
1
- import type { AnyObject, FieldFilter } from "prostgles-types/dist";
1
+ import type { AnyObject, FieldFilter, SelectParams } from "prostgles-types/dist";
2
2
  import { getKeys, isDefined, isObject } from "prostgles-types/dist";
3
3
  import type { ParsedTableRule } from "../../PublishParser/PublishParser";
4
4
  import type { ExistsFilterConfig, Filter, LocalParams, PGIdentifier } from "../DboBuilder";
5
5
  import { getCondition } from "../getCondition";
6
6
  import { type SelectItemValidated } from "../QueryBuilder/QueryBuilder";
7
+ import { getQuerySource, type QuerySource } from "../QueryBuilder/getQuerySource";
7
8
  import type { ViewHandler } from "./ViewHandler";
8
9
 
9
10
  export type PrepareWhereParams = {
@@ -16,46 +17,61 @@ export type PrepareWhereParams = {
16
17
  localParams: LocalParams | undefined;
17
18
  tableRule: ParsedTableRule | undefined;
18
19
  isHaving?: boolean;
20
+ selectParams?: SelectParams;
19
21
  };
20
22
 
21
- export async function prepareWhere(
22
- this: ViewHandler,
23
- params: PrepareWhereParams,
24
- ): Promise<{
23
+ export type WhereOptions = {
25
24
  columnsUsed: string[];
26
25
  condition: string;
27
26
  where: string;
28
27
  filter: AnyObject;
29
28
  exists: ExistsFilterConfig[];
30
- }> {
31
- const {
29
+ source: QuerySource;
30
+ };
31
+
32
+ export const prepareWhere = async (
33
+ viewHandler: ViewHandler,
34
+ {
32
35
  filter,
33
36
  select,
34
37
  forcedFilter,
35
- filterFields: ff,
36
38
  addWhere: addKeywords = true,
37
39
  tableAlias,
38
40
  localParams,
39
41
  tableRule,
40
- } = params;
41
- const { $and: $and_key, $or: $or_key } = this.dboBuilder.prostgles.keywords;
42
+ /* Local update allow all. TODO: tidy all calls */
43
+ filterFields = !tableRule ? "*" : undefined,
44
+ isHaving,
45
+ selectParams,
46
+ }: PrepareWhereParams,
47
+ ): Promise<WhereOptions> => {
48
+ const { $and: $and_key, $or: $or_key } = viewHandler.dboBuilder.prostgles.keywords;
49
+
50
+ if (localParams?.isRemoteRequest && !tableRule) {
51
+ throw "Unexpected: localParams isRemoteRequest and missing tableRule";
52
+ }
42
53
 
43
- let filterFields = ff;
44
- /* Local update allow all. TODO -> FIX THIS */
45
- if (!ff && !tableRule) filterFields = "*";
54
+ const source = await getQuerySource(
55
+ viewHandler,
56
+ selectParams ? tableRule : undefined,
57
+ filter ?? {},
58
+ selectParams ?? {},
59
+ tableAlias,
60
+ );
46
61
 
47
62
  const exists: ExistsFilterConfig[] = [];
48
63
 
49
64
  type FilterItemResult = { condition: string; columnsUsed: string[] };
50
65
  const parseFullFilter = async (
51
- f: any,
66
+ fullFilter: any,
52
67
  parentFilter: AnyObject | null = null,
53
68
  isForcedFilterBypass: boolean,
54
69
  ): Promise<FilterItemResult | undefined> => {
55
- if (!f) throw "Invalid/missing group filter provided";
56
- if (!isObject(f)) throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(f);
70
+ if (!fullFilter) throw "Invalid/missing group filter provided";
71
+ if (!isObject(fullFilter))
72
+ throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(fullFilter);
57
73
 
58
- const keys = getKeys(f);
74
+ const keys = getKeys(fullFilter);
59
75
  if (!keys.length) {
60
76
  return;
61
77
  }
@@ -66,8 +82,8 @@ export async function prepareWhere(
66
82
  throw "group filter ($and/$or) can only be placed at the root or within another group filter";
67
83
  }
68
84
 
69
- const { [$and_key]: $and, [$or_key]: $or } = f,
70
- group: AnyObject[] | undefined = $and || $or;
85
+ const { [$and_key]: $and, [$or_key]: $or } = fullFilter;
86
+ const group = ($and || $or) as AnyObject[] | undefined;
71
87
 
72
88
  if (group && group.length) {
73
89
  const operand = $and ? " AND " : " OR ";
@@ -82,20 +98,24 @@ export async function prepareWhere(
82
98
  if (conditionItems.length) {
83
99
  const conditions = conditionItems.map((c) => c.condition);
84
100
  const columnsUsed = conditionItems.map((c) => c.columnsUsed).flat();
85
- if (conditions.length === 1) return { columnsUsed, condition: conditions.join(operand) };
86
- else return { columnsUsed, condition: ` ( ${conditions.sort().join(operand)} ) ` };
101
+ if (conditions.length === 1) {
102
+ return { columnsUsed, condition: conditions.join(operand) };
103
+ }
104
+ return { columnsUsed, condition: ` ( ${conditions.sort().join(operand)} ) ` };
87
105
  }
88
106
  } else if (!group) {
89
107
  /** forcedFilters do not get checked against publish and are treated as server-side requests */
90
- const itemInfo = await getCondition.bind(this)({
91
- filter: { ...f },
108
+ const itemInfo = await getCondition.bind(viewHandler)({
109
+ filter: { ...fullFilter },
92
110
  select,
93
111
  allowed_colnames:
94
- isForcedFilterBypass ? this.column_names.slice(0) : this.parseFieldFilter(filterFields),
95
- tableAlias,
112
+ isForcedFilterBypass ?
113
+ viewHandler.column_names.slice(0)
114
+ : viewHandler.parseFieldFilter(filterFields),
115
+ tableAlias: source.alias,
96
116
  localParams: isForcedFilterBypass ? undefined : localParams,
97
117
  tableRules: isForcedFilterBypass ? undefined : tableRule,
98
- isHaving: params.isHaving,
118
+ isHaving,
99
119
  });
100
120
  exists.push(...itemInfo.exists);
101
121
  return {
@@ -135,5 +155,6 @@ export async function prepareWhere(
135
155
  where: combinedConditions || "",
136
156
  filter: finalFilter,
137
157
  exists,
158
+ source,
138
159
  };
139
- }
160
+ };
@@ -1,4 +1,4 @@
1
- import { pickKeys } from "prostgles-types";
1
+ import { pickKeys, type AnyObject } from "prostgles-types";
2
2
  import { parseFilterItem } from "../Filtering/Filtering";
3
3
  import type { ParsedTableRule } from "../PublishParser/PublishParser";
4
4
  import type { ExistsFilterConfig, LocalParams, PGIdentifier } from "./DboBuilder";
@@ -9,6 +9,7 @@ import type { ViewHandler } from "./ViewHandler/ViewHandler";
9
9
  import { getExistsCondition } from "./ViewHandler/getExistsCondition";
10
10
  import { getExistsFilters } from "./ViewHandler/getExistsFilters";
11
11
  import { parseComplexFilter } from "./ViewHandler/parseComplexFilter";
12
+ import { isArray } from "../utils/utils";
12
13
 
13
14
  const FILTER_FUNCS = FUNCTIONS.filter((f) => f.canBeUsedForFilter);
14
15
 
@@ -21,7 +22,7 @@ const FILTER_FUNCS = FUNCTIONS.filter((f) => f.canBeUsedForFilter);
21
22
  export async function getCondition(
22
23
  this: ViewHandler,
23
24
  params: {
24
- filter: any;
25
+ filter: AnyObject;
25
26
  select: SelectItemValidated[] | undefined;
26
27
  allowed_colnames: string[];
27
28
  tableAlias?: PGIdentifier;
@@ -44,21 +45,21 @@ export async function getCondition(
44
45
 
45
46
  const existsConfigs = getExistsFilters(filter, this);
46
47
 
47
- const funcConds: string[] = [];
48
+ const functionConditions: string[] = [];
48
49
  const funcFilter = FILTER_FUNCS.filter((f) => f.name in filter);
49
50
 
50
51
  funcFilter.map((f) => {
51
52
  const funcArgs = filter[f.name];
52
- if (!Array.isArray(funcArgs)) {
53
+ if (!isArray(funcArgs)) {
53
54
  throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify(pickKeys(filter, [f.name]))} `;
54
55
  }
55
56
  const fields = this.parseFieldFilter(f.getFields(funcArgs), true, allowed_colnames);
56
57
 
57
- const dissallowedCols = fields.filter((fname) => !allowed_colnames.includes(fname));
58
- if (dissallowedCols.length) {
59
- throw `Invalid/disallowed columns found in function filter: ${dissallowedCols}`;
58
+ const disallowedCols = fields.filter((fname) => !allowed_colnames.includes(fname));
59
+ if (disallowedCols.length) {
60
+ throw `Invalid/disallowed columns found in function filter: ${disallowedCols}`;
60
61
  }
61
- funcConds.push(
62
+ functionConditions.push(
62
63
  f.getQuery({
63
64
  args: funcArgs,
64
65
  allColumns: this.columns,
@@ -84,7 +85,7 @@ export async function getCondition(
84
85
  const p = this.getValidatedRules(tableRules, localParams);
85
86
  const computedFields = p.allColumns.filter((c) => c.type === "computed");
86
87
  const computedColConditions: string[] = [];
87
- Object.keys(filter || {}).map((key) => {
88
+ Object.keys(filter).map((key) => {
88
89
  const compCol = computedFields.find((cf) => cf.name === key);
89
90
  if (compCol) {
90
91
  if (!p.select) throw new Error("Computed column filter requires p.select.fields");
@@ -231,7 +232,7 @@ export async function getCondition(
231
232
  let templates: string[] = q?.condition ? [q.condition] : [];
232
233
 
233
234
  if (existsCond) templates.push(existsCond);
234
- templates = templates.concat(funcConds);
235
+ templates = templates.concat(functionConditions);
235
236
  templates = templates.concat(computedColConditions);
236
237
  templates = templates.concat(complexFilters);
237
238
 
@@ -8,6 +8,7 @@ import type { TableHandler } from "./TableHandler/TableHandler";
8
8
  import type { ViewHandler } from "./ViewHandler/ViewHandler";
9
9
  import { getViewRelatedTables } from "./ViewRelatedTables/getViewRelatedTables";
10
10
  import type { AddTriggerParams } from "../PubSubManager/addTrigger";
11
+ import { prepareWhere } from "./ViewHandler/prepareWhere";
11
12
 
12
13
  type Args = {
13
14
  selectParams: Omit<SubscribeParams, "throttle">;
@@ -66,9 +67,9 @@ export async function getSubscribeRelatedTables(
66
67
  isEmpty(targetTableFilter) ? reversedJoinFilter : (
67
68
  { $and: [targetTableFilter, reversedJoinFilter] }
68
69
  );
69
- const joinConditionInfo = await relatedTableOrViewHandler.prepareWhere({
70
- select: undefined,
70
+ const joinConditionInfo = await prepareWhere(relatedTableOrViewHandler, {
71
71
  filter,
72
+ select: undefined,
72
73
  addWhere: false,
73
74
  localParams: undefined,
74
75
  tableRule: undefined,
@@ -9,6 +9,7 @@ import { type ParsedTableRule } from "../PublishParser/PublishParser";
9
9
  import type { Filter, LocalParams } from "./DboBuilder";
10
10
  import { prepareNewData } from "./TableHandler/DataValidator";
11
11
  import type { TableHandler } from "./TableHandler/TableHandler";
12
+ import { prepareWhere } from "./ViewHandler/prepareWhere";
12
13
 
13
14
  /**
14
15
  * 1) Check if publish is valid
@@ -57,7 +58,7 @@ export async function parseUpdateRules(
57
58
  throw ` Invalid update rule fo r ${this.name}. fields missing `;
58
59
  }
59
60
  finalUpdateFilter = (
60
- await this.prepareWhere({
61
+ await prepareWhere(this, {
61
62
  select: undefined,
62
63
  filter,
63
64
  forcedFilter,
@@ -77,7 +78,7 @@ export async function parseUpdateRules(
77
78
  /**
78
79
  * Validated filter and fields
79
80
  */
80
- const condition = await this.prepareWhere({
81
+ const condition = await prepareWhere(this, {
81
82
  select: undefined,
82
83
  filterFields: this.column_names,
83
84
  filter: dfRule.filter,
package/lib/Prostgles.ts CHANGED
@@ -320,6 +320,7 @@ export class Prostgles {
320
320
  this.dboBuilder = await DboBuilder.create(this);
321
321
  }
322
322
  this.dbo = this.dboBuilder.dbo;
323
+ if (this.publishParser) this.initPublishParser();
323
324
  await this.opts.onLog?.({
324
325
  type: "debug",
325
326
  command: "refreshDBO.end",
@@ -2,6 +2,7 @@ import assert from "node:assert";
2
2
  import { describe, test } from "node:test";
3
3
  import type { DboBuilder } from "./DboBuilder/DboBuilder";
4
4
  import { Prostgles } from "./Prostgles";
5
+ import type { PublishParser } from "./PublishParser/PublishParser";
5
6
 
6
7
  void describe("Prostgles context", async () => {
7
8
  await test("recreates context and runs cleanups in reverse order", async () => {
@@ -47,6 +48,35 @@ void describe("Prostgles context", async () => {
47
48
  assert.equal(prostgles.context, undefined);
48
49
  });
49
50
 
51
+ await test("recreates the publish parser with the rebuilt DBO", async () => {
52
+ const prostgles = new Prostgles({
53
+ dbConnection: "postgres://unused",
54
+ onReady: () => {},
55
+ });
56
+ prostgles.db = {} as typeof prostgles.db;
57
+ const rebuiltDbo = {};
58
+ const dboBuilder = {
59
+ build: () => {
60
+ dboBuilder.dbo = rebuiltDbo;
61
+ return Promise.resolve();
62
+ },
63
+ dbo: {},
64
+ sql: {},
65
+ tables: [],
66
+ };
67
+ prostgles.dboBuilder = dboBuilder as unknown as DboBuilder;
68
+
69
+ // PublishParser captures the DBO on construction, so it must be recreated after a rebuild.
70
+ const initialPublishParser = {} as PublishParser;
71
+ prostgles.publishParser = initialPublishParser;
72
+
73
+ await prostgles.rebuildDBO();
74
+
75
+ assert.equal(prostgles.dbo, rebuiltDbo);
76
+ assert.notEqual(prostgles.publishParser, initialPublishParser);
77
+ assert.equal(prostgles.publishParser.dbo, prostgles.dbo);
78
+ });
79
+
50
80
  await test("cleans partially-created context after an error", async () => {
51
81
  const events: string[] = [];
52
82
  const prostgles = new Prostgles({
@@ -6,6 +6,7 @@ import {
6
6
  } from "prostgles-types";
7
7
  import { getClientRequestIPsInfo } from "../Auth/AuthHandler";
8
8
  import type { AuthClientRequest, AuthResultWithSID, SessionUser } from "../Auth/AuthTypes";
9
+ import { getAuditTableRules } from "../Audit/getAuditTableRules";
9
10
  import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
10
11
  import type { DB, DBHandlerServer, Prostgles } from "../Prostgles";
11
12
  import { getClientHandlers } from "../WebsocketAPI/getClientHandlers";
@@ -305,16 +306,40 @@ export class PublishParser {
305
306
  if (!tableHandler) {
306
307
  throw "INTERNAL ERROR: table handler not found for " + tableName;
307
308
  }
308
- const publishRulesExcludingFileTable = await this.getParsedPublishTable({
309
- clientReq,
310
- tableName,
311
- clientInfo,
312
- resolvedPublishObject: overriddenPublish,
313
- });
309
+ const audit = this.prostgles.resolvedAuditConfig;
310
+ const isAuditTable = audit?.tableName === tableName;
311
+ const resolvedPublishObject =
312
+ overriddenPublish ??
313
+ (isAuditTable && clientReq ?
314
+ await this.getPublishObjectForUser(clientReq, clientInfo)
315
+ : undefined);
316
+ const publishRulesExcludingInferredTables =
317
+ await this.getParsedPublishTable({
318
+ clientReq,
319
+ tableName,
320
+ clientInfo,
321
+ resolvedPublishObject,
322
+ });
323
+ if (audit && isAuditTable) {
324
+ const auditTableRules = await getAuditTableRules.bind(this)(
325
+ audit,
326
+ publishRulesExcludingInferredTables,
327
+ clientReq,
328
+ clientInfo,
329
+ scope,
330
+ resolvedPublishObject,
331
+ );
332
+ return applyScopeToTableRules(
333
+ tableName,
334
+ tableHandler,
335
+ parsePublishTableRule(auditTableRules),
336
+ scope,
337
+ );
338
+ }
314
339
  if (this.dbo[tableName]?.is_media) {
315
340
  const { rules: fileTableRules } = await getFileTableRules.bind(this)(
316
341
  tableName,
317
- publishRulesExcludingFileTable,
342
+ publishRulesExcludingInferredTables,
318
343
  clientReq,
319
344
  clientInfo,
320
345
  scope,
@@ -331,7 +356,7 @@ export class PublishParser {
331
356
  return applyScopeToTableRules(
332
357
  tableName,
333
358
  tableHandler,
334
- parsePublishTableRule(publishRulesExcludingFileTable),
359
+ parsePublishTableRule(publishRulesExcludingInferredTables),
335
360
  scope,
336
361
  );
337
362
  }
@@ -1,4 +1,4 @@
1
- import { getObjectEntries, isDefined, isEmpty } from "prostgles-types";
1
+ import { fromEntries, getObjectEntries, isDefined, isEmpty } from "prostgles-types";
2
2
  import type { TableHandler } from "../DboBuilder/TableHandler/TableHandler";
3
3
  import { type ParsedTableRule, type PermissionScope } from "./PublishParser";
4
4
  export const applyScopeToTableRules = (
@@ -68,9 +68,3 @@ export const applyScopeToTableRules = (
68
68
  ) as ParsedTableRule;
69
69
  return result;
70
70
  };
71
-
72
- export const fromEntries = <K extends string | number | symbol, V>(
73
- entries: readonly (readonly [K, V])[],
74
- ): Record<K, V> => {
75
- return Object.fromEntries(entries) as Record<K, V>;
76
- };
@@ -1,3 +1,4 @@
1
+ import { isObject } from "prostgles-types";
1
2
  import type { PublishParser } from "./PublishParser";
2
3
  import { type PublishObject } from "./PublishParser";
3
4
 
@@ -30,5 +31,26 @@ export const getPublishedTableNames = (
30
31
  tableNames.unshift(fileTableName);
31
32
  }
32
33
  }
34
+
35
+ const audit = publishParserInstance.prostgles.resolvedAuditConfig;
36
+ const publishedFileTableName =
37
+ fileTableName && tableNames.includes(fileTableName) ?
38
+ fileTableName
39
+ : undefined;
40
+ if (
41
+ audit &&
42
+ !tableNames.includes(audit.tableName) &&
43
+ Object.keys(audit.tables).some((tableName) => {
44
+ const rule = publishObject[tableName];
45
+ return (
46
+ tableName === publishedFileTableName ||
47
+ rule === "*" ||
48
+ rule === true ||
49
+ (isObject(rule) && Boolean(rule.select))
50
+ );
51
+ })
52
+ ) {
53
+ tableNames.unshift(audit.tableName);
54
+ }
33
55
  return tableNames;
34
56
  };
@@ -228,11 +228,6 @@ export type SelectRule<Cols extends AnyObject = AnyObject, S extends DBSchema |
228
228
  * */
229
229
  filterFields?: FieldFilter<Cols>;
230
230
 
231
- /**
232
- * Validation logic to check/update data for each request
233
- */
234
- validate?(args: SelectRequestData): SelectRequestData | Promise<SelectRequestData>;
235
-
236
231
  subscribeThrottle?: number;
237
232
 
238
233
  disableMethods?: Partial<Record<"sync" | "subscribe", 1>>;
@@ -1,8 +1,14 @@
1
1
  import type pgPromise from "pg-promise";
2
- import { asName, getObjectEntries, isObject, pickKeys, type JSONB } from "prostgles-types";
2
+ import {
3
+ asName,
4
+ fromEntries,
5
+ getObjectEntries,
6
+ isObject,
7
+ pickKeys,
8
+ type JSONB,
9
+ } from "prostgles-types";
3
10
  import { VALIDATE_SCHEMA_FUNCNAME } from "../JSONBSchemaValidation/validateJSONBSchemaSQL";
4
11
  import type { DB } from "../Prostgles";
5
- import { fromEntries } from "../PublishParser/applyScopeToTableRules";
6
12
  import { asValue } from "../PubSubManager/PubSubManagerUtils";
7
13
  import type { BaseColumnTypes, ColumnConfig } from "./TableConfigTypes";
8
14
 
package/lib/index.ts CHANGED
@@ -56,6 +56,7 @@ export type { FileTableRow } from "./StorageClient/getFileTableConfig";
56
56
  export { defineJoin };
57
57
  export {
58
58
  AUDIT_TABLE_COLUMN_DEFINITIONS,
59
+ AUDIT_TABLE_COLUMN_NAMES,
59
60
  AUDIT_TABLE_COLUMNS,
60
61
  type AuditTableRow,
61
62
  } from "./Audit/AuditTable";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.624",
3
+ "version": "4.2.625",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",