prostgles-server 4.0.57 → 4.0.59

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 (221) hide show
  1. package/dist/DboBuilder/getColumns.d.ts.map +1 -1
  2. package/dist/DboBuilder/getColumns.js +1 -13
  3. package/dist/DboBuilder/getColumns.js.map +1 -1
  4. package/dist/DboBuilder/runSQL.js +2 -2
  5. package/dist/DboBuilder/runSQL.js.map +1 -1
  6. package/dist/Prostgles.d.ts.map +1 -1
  7. package/dist/PubSubManager/PubSubManager.d.ts +1 -1
  8. package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
  9. package/dist/PubSubManager/PubSubManager.js +14 -1
  10. package/dist/PubSubManager/PubSubManager.js.map +1 -1
  11. package/lib/DboBuilder/getColumns.ts +1 -18
  12. package/lib/DboBuilder/runSQL.ts +2 -2
  13. package/lib/Prostgles.ts +3 -3
  14. package/lib/PubSubManager/PubSubManager.ts +14 -1
  15. package/package.json +2 -2
  16. package/tests/client/PID.txt +1 -1
  17. package/tests/client/package.json +2 -2
  18. package/tests/client/tsconfig.json +2 -1
  19. package/tests/isomorphic_queries.ts +11 -9
  20. package/tests/server/DBoGenerated.d.ts +1 -1
  21. package/tests/server/dboTypeCheck.ts +3 -3
  22. package/tests/server/index.ts +7 -6
  23. package/tests/server/package-lock.json +1 -1
  24. package/tests/server/package.json +3 -3
  25. package/tests/server/publishTypeCheck.ts +1 -1
  26. package/tests/server/tsconfig.json +3 -2
  27. package/tests/test.sh +2 -0
  28. package/dist/FileManager.d.ts +0 -143
  29. package/dist/FileManager.d.ts.map +0 -1
  30. package/dist/FileManager.js +0 -646
  31. package/dist/FileManager.js.map +0 -1
  32. package/dist/TableConfig.d.ts +0 -267
  33. package/dist/TableConfig.d.ts.map +0 -1
  34. package/dist/TableConfig.js +0 -463
  35. package/dist/TableConfig.js.map +0 -1
  36. package/dist/validation.d.ts +0 -126
  37. package/dist/validation.d.ts.map +0 -1
  38. package/dist/validation.js +0 -405
  39. package/dist/validation.js.map +0 -1
  40. package/lib/AuthHandler.d.ts +0 -187
  41. package/lib/AuthHandler.d.ts.map +0 -1
  42. package/lib/AuthHandler.js +0 -478
  43. package/lib/DBEventsManager.d.ts +0 -38
  44. package/lib/DBEventsManager.d.ts.map +0 -1
  45. package/lib/DBEventsManager.js +0 -140
  46. package/lib/DBSchemaBuilder.d.ts +0 -13
  47. package/lib/DBSchemaBuilder.d.ts.map +0 -1
  48. package/lib/DBSchemaBuilder.js +0 -145
  49. package/lib/DboBuilder/QueryBuilder/Functions.d.ts +0 -64
  50. package/lib/DboBuilder/QueryBuilder/Functions.d.ts.map +0 -1
  51. package/lib/DboBuilder/QueryBuilder/Functions.js +0 -984
  52. package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts +0 -73
  53. package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +0 -1
  54. package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +0 -335
  55. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.d.ts +0 -8
  56. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +0 -1
  57. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.js +0 -227
  58. package/lib/DboBuilder/TableHandler.d.ts +0 -37
  59. package/lib/DboBuilder/TableHandler.d.ts.map +0 -1
  60. package/lib/DboBuilder/TableHandler.js +0 -213
  61. package/lib/DboBuilder/ViewHandler.d.ts +0 -119
  62. package/lib/DboBuilder/ViewHandler.d.ts.map +0 -1
  63. package/lib/DboBuilder/ViewHandler.js +0 -1023
  64. package/lib/DboBuilder/delete.d.ts +0 -6
  65. package/lib/DboBuilder/delete.d.ts.map +0 -1
  66. package/lib/DboBuilder/delete.js +0 -128
  67. package/lib/DboBuilder/find.d.ts +0 -8
  68. package/lib/DboBuilder/find.d.ts.map +0 -1
  69. package/lib/DboBuilder/find.js +0 -91
  70. package/lib/DboBuilder/getColumns.d.ts +0 -12
  71. package/lib/DboBuilder/getColumns.d.ts.map +0 -1
  72. package/lib/DboBuilder/getColumns.js +0 -92
  73. package/lib/DboBuilder/getCondition.d.ts +0 -22
  74. package/lib/DboBuilder/getCondition.d.ts.map +0 -1
  75. package/lib/DboBuilder/getCondition.js +0 -236
  76. package/lib/DboBuilder/getSubscribeRelatedTables.d.ts +0 -20
  77. package/lib/DboBuilder/getSubscribeRelatedTables.d.ts.map +0 -1
  78. package/lib/DboBuilder/getSubscribeRelatedTables.js +0 -152
  79. package/lib/DboBuilder/getTablesForSchemaPostgresSQL.d.ts +0 -3
  80. package/lib/DboBuilder/getTablesForSchemaPostgresSQL.d.ts.map +0 -1
  81. package/lib/DboBuilder/getTablesForSchemaPostgresSQL.js +0 -207
  82. package/lib/DboBuilder/insert.d.ts +0 -6
  83. package/lib/DboBuilder/insert.d.ts.map +0 -1
  84. package/lib/DboBuilder/insert.js +0 -180
  85. package/lib/DboBuilder/insertDataParse.d.ts +0 -12
  86. package/lib/DboBuilder/insertDataParse.d.ts.map +0 -1
  87. package/lib/DboBuilder/insertDataParse.js +0 -253
  88. package/lib/DboBuilder/parseUpdateRules.d.ts +0 -18
  89. package/lib/DboBuilder/parseUpdateRules.d.ts.map +0 -1
  90. package/lib/DboBuilder/parseUpdateRules.js +0 -123
  91. package/lib/DboBuilder/runSQL.d.ts +0 -7
  92. package/lib/DboBuilder/runSQL.d.ts.map +0 -1
  93. package/lib/DboBuilder/runSQL.js +0 -135
  94. package/lib/DboBuilder/subscribe.d.ts +0 -20
  95. package/lib/DboBuilder/subscribe.d.ts.map +0 -1
  96. package/lib/DboBuilder/subscribe.js +0 -90
  97. package/lib/DboBuilder/update.d.ts +0 -6
  98. package/lib/DboBuilder/update.d.ts.map +0 -1
  99. package/lib/DboBuilder/update.js +0 -151
  100. package/lib/DboBuilder/uploadFile.d.ts +0 -7
  101. package/lib/DboBuilder/uploadFile.d.ts.map +0 -1
  102. package/lib/DboBuilder/uploadFile.js +0 -53
  103. package/lib/DboBuilder.d.ts +0 -306
  104. package/lib/DboBuilder.d.ts.map +0 -1
  105. package/lib/DboBuilder.js +0 -745
  106. package/lib/Event_Trigger_Tags.d.ts +0 -4
  107. package/lib/Event_Trigger_Tags.d.ts.map +0 -1
  108. package/lib/Event_Trigger_Tags.js +0 -116
  109. package/lib/FileManager/FileManager.d.ts +0 -135
  110. package/lib/FileManager/FileManager.d.ts.map +0 -1
  111. package/lib/FileManager/FileManager.js +0 -303
  112. package/lib/FileManager/initFileManager.d.ts +0 -4
  113. package/lib/FileManager/initFileManager.d.ts.map +0 -1
  114. package/lib/FileManager/initFileManager.js +0 -231
  115. package/lib/FileManager/parseFile.d.ts +0 -15
  116. package/lib/FileManager/parseFile.d.ts.map +0 -1
  117. package/lib/FileManager/parseFile.js +0 -58
  118. package/lib/FileManager/upload.d.ts +0 -6
  119. package/lib/FileManager/upload.d.ts.map +0 -1
  120. package/lib/FileManager/upload.js +0 -98
  121. package/lib/FileManager/uploadStream.d.ts +0 -5
  122. package/lib/FileManager/uploadStream.d.ts.map +0 -1
  123. package/lib/FileManager/uploadStream.js +0 -92
  124. package/lib/Filtering.d.ts +0 -15
  125. package/lib/Filtering.d.ts.map +0 -1
  126. package/lib/Filtering.js +0 -336
  127. package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts +0 -4
  128. package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +0 -1
  129. package/lib/JSONBValidation/validate_jsonb_schema_sql.js +0 -500
  130. package/lib/JSONBValidation/validation.d.ts +0 -9
  131. package/lib/JSONBValidation/validation.d.ts.map +0 -1
  132. package/lib/JSONBValidation/validation.js +0 -131
  133. package/lib/PostgresNotifListenManager.d.ts +0 -28
  134. package/lib/PostgresNotifListenManager.d.ts.map +0 -1
  135. package/lib/PostgresNotifListenManager.js +0 -134
  136. package/lib/Prostgles.d.ts +0 -289
  137. package/lib/Prostgles.d.ts.map +0 -1
  138. package/lib/Prostgles.js +0 -685
  139. package/lib/PubSubManager/PubSubManager.d.ts +0 -175
  140. package/lib/PubSubManager/PubSubManager.d.ts.map +0 -1
  141. package/lib/PubSubManager/PubSubManager.js +0 -452
  142. package/lib/PubSubManager/addSub.d.ts +0 -8
  143. package/lib/PubSubManager/addSub.d.ts.map +0 -1
  144. package/lib/PubSubManager/addSub.js +0 -166
  145. package/lib/PubSubManager/addSync.d.ts +0 -8
  146. package/lib/PubSubManager/addSync.d.ts.map +0 -1
  147. package/lib/PubSubManager/addSync.js +0 -109
  148. package/lib/PubSubManager/getInitQuery.d.ts +0 -9
  149. package/lib/PubSubManager/getInitQuery.d.ts.map +0 -1
  150. package/lib/PubSubManager/getInitQuery.js +0 -552
  151. package/lib/PubSubManager/initPubSubManager.d.ts +0 -3
  152. package/lib/PubSubManager/initPubSubManager.d.ts.map +0 -1
  153. package/lib/PubSubManager/initPubSubManager.js +0 -116
  154. package/lib/PubSubManager/notifListener.d.ts +0 -5
  155. package/lib/PubSubManager/notifListener.d.ts.map +0 -1
  156. package/lib/PubSubManager/notifListener.js +0 -100
  157. package/lib/PubSubManager/pushSubData.d.ts +0 -3
  158. package/lib/PubSubManager/pushSubData.d.ts.map +0 -1
  159. package/lib/PubSubManager/pushSubData.js +0 -51
  160. package/lib/PublishParser.d.ts +0 -284
  161. package/lib/PublishParser.d.ts.map +0 -1
  162. package/lib/PublishParser.js +0 -421
  163. package/lib/SchemaWatch.d.ts +0 -13
  164. package/lib/SchemaWatch.d.ts.map +0 -1
  165. package/lib/SchemaWatch.js +0 -35
  166. package/lib/SyncReplication.d.ts +0 -34
  167. package/lib/SyncReplication.d.ts.map +0 -1
  168. package/lib/SyncReplication.js +0 -412
  169. package/lib/TableConfig/TableConfig.d.ts +0 -284
  170. package/lib/TableConfig/TableConfig.d.ts.map +0 -1
  171. package/lib/TableConfig/TableConfig.js +0 -437
  172. package/lib/TableConfig/getColumnDefinitionQuery.d.ts +0 -27
  173. package/lib/TableConfig/getColumnDefinitionQuery.d.ts.map +0 -1
  174. package/lib/TableConfig/getColumnDefinitionQuery.js +0 -87
  175. package/lib/TableConfig/getConstraintDefinitionQueries.d.ts +0 -34
  176. package/lib/TableConfig/getConstraintDefinitionQueries.d.ts.map +0 -1
  177. package/lib/TableConfig/getConstraintDefinitionQueries.js +0 -65
  178. package/lib/TableConfig/getFutureTableSchema.d.ts +0 -15
  179. package/lib/TableConfig/getFutureTableSchema.d.ts.map +0 -1
  180. package/lib/TableConfig/getFutureTableSchema.js +0 -43
  181. package/lib/TableConfig/getTableColumnQueries.d.ts +0 -16
  182. package/lib/TableConfig/getTableColumnQueries.d.ts.map +0 -1
  183. package/lib/TableConfig/getTableColumnQueries.js +0 -107
  184. package/lib/index.d.ts +0 -5
  185. package/lib/index.d.ts.map +0 -1
  186. package/lib/index.js +0 -7
  187. package/lib/shortestPath.d.ts +0 -10
  188. package/lib/shortestPath.d.ts.map +0 -1
  189. package/lib/shortestPath.js +0 -111
  190. package/lib/utils.d.ts +0 -3
  191. package/lib/utils.d.ts.map +0 -1
  192. package/lib/utils.js +0 -12
  193. package/tests/client/index.d.ts +0 -2
  194. package/tests/client/index.d.ts.map +0 -1
  195. package/tests/client/index.js +0 -80
  196. package/tests/client/index.js.map +0 -1
  197. package/tests/client_only_queries.d.ts +0 -4
  198. package/tests/client_only_queries.d.ts.map +0 -1
  199. package/tests/client_only_queries.js +0 -282
  200. package/tests/config_test/DBoGenerated.d.ts +0 -388
  201. package/tests/config_test/index.js +0 -174
  202. package/tests/config_test/index.js.map +0 -1
  203. package/tests/isomorphic_queries.d.ts +0 -9
  204. package/tests/isomorphic_queries.d.ts.map +0 -1
  205. package/tests/isomorphic_queries.js +0 -773
  206. package/tests/manual_test/DBoGenerated.d.ts +0 -398
  207. package/tests/manual_test/index.d.ts +0 -2
  208. package/tests/manual_test/index.d.ts.map +0 -1
  209. package/tests/manual_test/index.js +0 -65
  210. package/tests/server/dboTypeCheck.d.ts +0 -2
  211. package/tests/server/dboTypeCheck.d.ts.map +0 -1
  212. package/tests/server/dboTypeCheck.js +0 -27
  213. package/tests/server/index.d.ts +0 -2
  214. package/tests/server/index.d.ts.map +0 -1
  215. package/tests/server/index.js +0 -507
  216. package/tests/server/publishTypeCheck.d.ts +0 -2
  217. package/tests/server/publishTypeCheck.d.ts.map +0 -1
  218. package/tests/server/publishTypeCheck.js +0 -130
  219. package/tests/server_only_queries.d.ts +0 -2
  220. package/tests/server_only_queries.d.ts.map +0 -1
  221. package/tests/server_only_queries.js +0 -19
@@ -1,1023 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ViewHandler = void 0;
4
- const getCondition_1 = require("./getCondition");
5
- const prostgles_types_1 = require("prostgles-types");
6
- const DboBuilder_1 = require("../DboBuilder");
7
- const PubSubManager_1 = require("../PubSubManager/PubSubManager");
8
- const QueryBuilder_1 = require("./QueryBuilder/QueryBuilder");
9
- const Functions_1 = require("./QueryBuilder/Functions");
10
- const getColumns_1 = require("./getColumns");
11
- const subscribe_1 = require("./subscribe");
12
- const find_1 = require("./find");
13
- class ColSet {
14
- opts;
15
- constructor(columns, tableName) {
16
- this.opts = { columns, tableName, colNames: columns.map(c => c.name) };
17
- }
18
- async getRow(data, allowedCols, dbTx, validate) {
19
- const badCol = allowedCols.find(c => !this.opts.colNames.includes(c));
20
- if (!allowedCols || badCol) {
21
- throw "Missing or unexpected columns: " + badCol;
22
- }
23
- if ((0, prostgles_types_1.isEmpty)(data))
24
- throw "No data";
25
- let row = (0, prostgles_types_1.pickKeys)(data, allowedCols);
26
- if (validate) {
27
- row = await validate(row, dbTx);
28
- }
29
- const rowKeys = Object.keys(row);
30
- return rowKeys.map(key => {
31
- const col = this.opts.columns.find(c => c.name === key);
32
- if (!col)
33
- throw "Unexpected missing col name";
34
- /**
35
- * Add conversion functions for PostGIS data
36
- */
37
- let escapedVal = "";
38
- if (["geometry", "geography"].includes(col.udt_name) && (0, prostgles_types_1.isObject)(row[key])) {
39
- const basicFunc = (args) => {
40
- return args.map(arg => (0, PubSubManager_1.asValue)(arg)).join(", ");
41
- };
42
- const convertionFuncs = [
43
- ...[
44
- "ST_GeomFromText",
45
- "ST_Point",
46
- "ST_MakePoint",
47
- "ST_MakePointM",
48
- "ST_PointFromText",
49
- "ST_GeomFromEWKT",
50
- "ST_GeomFromGeoJSON"
51
- ].map(name => ({
52
- name,
53
- getQuery: () => `${name}(${basicFunc(funcArgs)})`
54
- })),
55
- {
56
- name: "to_timestamp",
57
- getQuery: (args) => `to_timestamp(${(0, PubSubManager_1.asValue)(args[0])}::BIGINT/1000.0)::timestamp`
58
- }
59
- ];
60
- const dataKeys = Object.keys(row[key]);
61
- const funcName = dataKeys[0];
62
- const func = convertionFuncs.find(f => f.name === funcName);
63
- const funcArgs = row[key]?.[funcName];
64
- if (dataKeys.length !== 1 || !func || !Array.isArray(funcArgs)) {
65
- throw `Expecting only one function key (${convertionFuncs.join(", ")}) \nwith an array of arguments \n within column (${key}) data but got: ${JSON.stringify(row[key])} \nExample: { geo_col: { ST_GeomFromText: ["POINT(-71.064544 42.28787)", 4326] } }`;
66
- }
67
- escapedVal = func.getQuery(funcArgs);
68
- }
69
- else {
70
- /** Prevent pg-promise formatting jsonb */
71
- const colIsJSON = ["json", "jsonb"].includes(col.data_type);
72
- escapedVal = DboBuilder_1.pgp.as.format(colIsJSON ? "$1:json" : "$1", [row[key]]);
73
- }
74
- /**
75
- * Cast to type to avoid array errors (they do not cast automatically)
76
- */
77
- escapedVal += `::${col.udt_name}`;
78
- return {
79
- escapedCol: (0, prostgles_types_1.asName)(key),
80
- escapedVal,
81
- };
82
- });
83
- }
84
- async getInsertQuery(data, allowedCols, dbTx, validate) {
85
- const res = (await Promise.all((Array.isArray(data) ? data : [data]).map(async (d) => {
86
- const rowParts = await this.getRow(d, allowedCols, dbTx, validate);
87
- const select = rowParts.map(r => r.escapedCol).join(", "), values = rowParts.map(r => r.escapedVal).join(", ");
88
- return `INSERT INTO ${(0, prostgles_types_1.asName)(this.opts.tableName)} (${select}) VALUES (${values})`;
89
- }))).join(";\n") + " ";
90
- return res;
91
- }
92
- async getUpdateQuery(data, allowedCols, dbTx, validate) {
93
- const res = (await Promise.all((Array.isArray(data) ? data : [data]).map(async (d) => {
94
- const rowParts = await this.getRow(d, allowedCols, dbTx, validate);
95
- return `UPDATE ${(0, prostgles_types_1.asName)(this.opts.tableName)} SET ` + rowParts.map(r => `${r.escapedCol} = ${r.escapedVal} `).join(",\n");
96
- }))).join(";\n") + " ";
97
- return res;
98
- }
99
- }
100
- class ViewHandler {
101
- db;
102
- name;
103
- escapedName;
104
- columns;
105
- columnsForTypes;
106
- column_names;
107
- tableOrViewInfo; // TableOrViewInfo;
108
- colSet;
109
- tsColumnDefs = [];
110
- joins;
111
- joinGraph;
112
- joinPaths;
113
- dboBuilder;
114
- t;
115
- dbTX;
116
- is_view = true;
117
- filterDef = "";
118
- // pubSubManager: PubSubManager;
119
- is_media = false;
120
- constructor(db, tableOrViewInfo, dboBuilder, t, dbTX, joinPaths) {
121
- if (!db || !tableOrViewInfo)
122
- throw "";
123
- this.db = db;
124
- this.t = t;
125
- this.dbTX = dbTX;
126
- this.joinPaths = joinPaths;
127
- this.tableOrViewInfo = tableOrViewInfo;
128
- this.name = tableOrViewInfo.name;
129
- this.escapedName = (0, prostgles_types_1.asName)(this.name);
130
- this.columns = tableOrViewInfo.columns;
131
- /* cols are sorted by name to reduce .d.ts schema rewrites */
132
- this.columnsForTypes = tableOrViewInfo.columns.slice(0).sort((a, b) => a.name.localeCompare(b.name));
133
- this.column_names = tableOrViewInfo.columns.map(c => c.name);
134
- this.dboBuilder = dboBuilder;
135
- this.joins = this.dboBuilder.joins ?? [];
136
- this.colSet = new ColSet(this.columns, this.name);
137
- this.columnsForTypes.map(({ name, udt_name, is_nullable }) => {
138
- this.tsColumnDefs.push(`${(0, DboBuilder_1.escapeTSNames)(name)}?: ${(0, DboBuilder_1.postgresToTsType)(udt_name)} ${is_nullable ? " | null " : ""};`);
139
- });
140
- }
141
- getRowHashSelect(allowedFields, alias, tableAlias) {
142
- let allowed_cols = this.column_names;
143
- if (allowedFields)
144
- allowed_cols = this.parseFieldFilter(allowedFields);
145
- return "md5(" +
146
- allowed_cols
147
- /* CTID not available in AFTER trigger */
148
- // .concat(this.is_view? [] : ["ctid"])
149
- .sort()
150
- .map(f => (tableAlias ? ((0, prostgles_types_1.asName)(tableAlias) + ".") : "") + (0, prostgles_types_1.asName)(f))
151
- .map(f => `md5(coalesce(${f}::text, 'dd'))`)
152
- .join(" || ") +
153
- `)` + (alias ? ` as ${(0, prostgles_types_1.asName)(alias)}` : "");
154
- }
155
- async validateViewRules(args) {
156
- const { fields, filterFields, returningFields, forcedFilter, dynamicFields, rule, } = args;
157
- /* Safely test publish rules */
158
- if (fields) {
159
- try {
160
- const _fields = this.parseFieldFilter(fields);
161
- if (this.is_media && rule === "insert" && !_fields.includes("id")) {
162
- throw "Must allow id insert for media table";
163
- }
164
- }
165
- catch (e) {
166
- throw ` issue with publish.${this.name}.${rule}.fields: \nVALUE: ` + JSON.stringify(fields, null, 2) + "\nERROR: " + JSON.stringify(e, null, 2);
167
- }
168
- }
169
- if (filterFields) {
170
- try {
171
- this.parseFieldFilter(filterFields);
172
- }
173
- catch (e) {
174
- throw ` issue with publish.${this.name}.${rule}.filterFields: \nVALUE: ` + JSON.stringify(filterFields, null, 2) + "\nERROR: " + JSON.stringify(e, null, 2);
175
- }
176
- }
177
- if (returningFields) {
178
- try {
179
- this.parseFieldFilter(returningFields);
180
- }
181
- catch (e) {
182
- throw ` issue with publish.${this.name}.${rule}.returningFields: \nVALUE: ` + JSON.stringify(returningFields, null, 2) + "\nERROR: " + JSON.stringify(e, null, 2);
183
- }
184
- }
185
- if (forcedFilter) {
186
- try {
187
- await this.find(forcedFilter, { limit: 0 });
188
- }
189
- catch (e) {
190
- throw ` issue with publish.${this.name}.${rule}.forcedFilter: \nVALUE: ` + JSON.stringify(forcedFilter, null, 2) + "\nERROR: " + JSON.stringify(e, null, 2);
191
- }
192
- }
193
- if (dynamicFields) {
194
- for await (const dfieldRule of dynamicFields) {
195
- try {
196
- const { fields, filter } = dfieldRule;
197
- this.parseFieldFilter(fields);
198
- await this.find(filter, { limit: 0 });
199
- }
200
- catch (e) {
201
- throw ` issue with publish.${this.name}.${rule}.dynamicFields: \nVALUE: ` + JSON.stringify(dfieldRule, null, 2) + "\nERROR: " + JSON.stringify(e, null, 2);
202
- }
203
- }
204
- }
205
- return true;
206
- }
207
- getShortestJoin(table1, table2, startAlias, isInner = false) {
208
- // let searchedTables = [], result;
209
- // while (!result && searchedTables.length <= this.joins.length * 2){
210
- // }
211
- const getJoinCondition = (on, leftTable, rightTable) => {
212
- return on.map(cond => Object.keys(cond).map(lKey => `${leftTable}.${lKey} = ${rightTable}.${cond[lKey]}`).join("\nAND ")).join(" OR ");
213
- };
214
- // let toOne = true;
215
- const query = this.joins.map(({ tables, on, type }, i) => {
216
- if (type.split("-")[1] === "many") {
217
- // toOne = false;
218
- }
219
- const tl = `tl${startAlias + i}`, tr = `tr${startAlias + i}`;
220
- return `FROM ${tables[0]} ${tl} ${isInner ? "INNER" : "LEFT"} JOIN ${tables[1]} ${tr} ON ${getJoinCondition(on, tl, tr)}`;
221
- }).join("\n");
222
- return { query, toOne: false };
223
- }
224
- getJoins(source, target, path, checkTableConfig) {
225
- let paths = [];
226
- if (!this.joinPaths)
227
- throw `${source} - ${target} Join info missing or dissallowed`;
228
- if (path && !path.length)
229
- throw `Empty join path ( $path ) specified for ${source} <-> ${target}`;
230
- /* Find the join path between tables */
231
- if (checkTableConfig) {
232
- const tableConfigJoinInfo = this.dboBuilder?.prostgles?.tableConfigurator?.getJoinInfo(source, target);
233
- if (tableConfigJoinInfo)
234
- return tableConfigJoinInfo;
235
- }
236
- let jp;
237
- if (!path) {
238
- jp = this.joinPaths.find(j => j.t1 === source && j.t2 === target);
239
- }
240
- else {
241
- jp = {
242
- t1: source,
243
- t2: target,
244
- path
245
- };
246
- }
247
- /* Self join */
248
- if (source === target) {
249
- const tableHandler = this.dboBuilder.tablesOrViews?.find(t => t.name === source);
250
- if (!tableHandler)
251
- throw `Table not found for joining ${source}`;
252
- const fcols = tableHandler.columns.filter(c => c.references?.some(({ ftable }) => ftable === this.name));
253
- if (fcols.length) {
254
- throw "Self referencing not supported yet";
255
- // return {
256
- // paths: [{
257
- // source,
258
- // target,
259
- // table: target,
260
- // on: fcols.map(fc => fc.references!.some(({ fcols }) => fcols.map(fcol => [fc.name, fcol])))
261
- // }],
262
- // expectOne: false
263
- // }
264
- }
265
- }
266
- if (!jp || !this.joinPaths.find(j => path ? j.path.join() === path.join() : j.t1 === source && j.t2 === target)) {
267
- throw `Joining ${source} <-...-> ${target} dissallowed or missing`;
268
- }
269
- /* Make the join chain info excluding root table */
270
- paths = (path || jp.path).slice(1).map((t2, i, arr) => {
271
- const t1 = i === 0 ? source : arr[i - 1];
272
- this.joins ??= this.dboBuilder.joins;
273
- /* Get join options */
274
- const jo = this.joins.find(j => j.tables.includes(t1) && j.tables.includes(t2));
275
- if (!jo)
276
- throw `Joining ${t1} <-> ${t2} dissallowed or missing`;
277
- const on = [];
278
- jo.on.map(cond => {
279
- const condArr = [];
280
- (0, prostgles_types_1.getKeys)(cond).map(leftKey => {
281
- const rightKey = cond[leftKey];
282
- /* Left table is joining on keys */
283
- if (jo.tables[0] === t1) {
284
- condArr.push([leftKey, rightKey]);
285
- /* Left table is joining on values */
286
- }
287
- else {
288
- condArr.push([rightKey, leftKey]);
289
- }
290
- });
291
- on.push(condArr);
292
- });
293
- return {
294
- source,
295
- target,
296
- table: t2,
297
- on
298
- };
299
- });
300
- const expectOne = false;
301
- // paths.map(({ source, target, on }, i) => {
302
- // if(expectOne && on.length === 1){
303
- // const sourceCol = on[0][1];
304
- // const targetCol = on[0][0];
305
- // const sCol = this.dboBuilder.dbo[source].columns.find(c => c.name === sourceCol)
306
- // const tCol = this.dboBuilder.dbo[target].columns.find(c => c.name === targetCol)
307
- // console.log({ sourceCol, targetCol, sCol, source, tCol, target, on})
308
- // expectOne = sCol.is_pkey && tCol.is_pkey
309
- // }
310
- // })
311
- return {
312
- paths,
313
- expectOne
314
- };
315
- }
316
- checkFilter(filter) {
317
- if (filter === null || filter && !(0, prostgles_types_1.isObject)(filter))
318
- throw `invalid filter -> ${JSON.stringify(filter)} \nExpecting: undefined | {} | { field_name: "value" } | { field: { $gt: 22 } } ... `;
319
- }
320
- async getInfo(lang, param2, param3, tableRules, localParams) {
321
- const p = this.getValidatedRules(tableRules, localParams);
322
- if (!p.getInfo)
323
- throw "Not allowed";
324
- let has_media = undefined;
325
- const mediaTable = this.dboBuilder.prostgles?.opts?.fileTable?.tableName;
326
- if (!this.is_media && mediaTable) {
327
- const joinConf = this.dboBuilder.prostgles?.opts?.fileTable?.referencedTables?.[this.name];
328
- if (joinConf) {
329
- has_media = typeof joinConf === "string" ? joinConf : "one";
330
- }
331
- else {
332
- const jp = this.dboBuilder.joinPaths.find(jp => jp.t1 === this.name && jp.t2 === mediaTable);
333
- if (jp && jp.path.length <= 3) {
334
- if (jp.path.length <= 2) {
335
- has_media = "one";
336
- }
337
- else {
338
- await Promise.all(jp.path.map(async (tableName) => {
339
- const pkeyFcols = this?.dboBuilder?.dbo?.[tableName]?.columns?.filter(c => c.is_pkey).map(c => c.name);
340
- const cols = this?.dboBuilder?.dbo?.[tableName]?.columns?.filter(c => c?.references?.some(({ ftable }) => jp.path.includes(ftable)));
341
- if (cols && cols.length && has_media !== "many") {
342
- if (cols.some(c => !pkeyFcols?.includes(c.name))) {
343
- has_media = "many";
344
- }
345
- else {
346
- has_media = "one";
347
- }
348
- }
349
- }));
350
- }
351
- }
352
- }
353
- }
354
- return {
355
- oid: this.tableOrViewInfo.oid,
356
- comment: this.tableOrViewInfo.comment,
357
- info: this.dboBuilder.prostgles?.tableConfigurator?.getTableInfo({ tableName: this.name, lang }),
358
- is_media: this.is_media,
359
- is_view: this.is_view,
360
- has_media,
361
- media_table_name: mediaTable,
362
- dynamicRules: {
363
- update: Boolean(tableRules?.update?.dynamicFields?.length)
364
- }
365
- };
366
- }
367
- // TODO: fix renamed table trigger problem
368
- getColumns = getColumns_1.getColumns.bind(this);
369
- getValidatedRules(tableRules, localParams) {
370
- if (localParams?.socket && !tableRules) {
371
- throw "INTERNAL ERROR: Unexpected case -> localParams && !tableRules";
372
- }
373
- /* Computed fields are allowed only if select is allowed */
374
- const allColumns = this.column_names.slice(0).map(fieldName => ({
375
- type: "column",
376
- name: fieldName,
377
- getQuery: ({ tableAlias }) => (0, QueryBuilder_1.asNameAlias)(fieldName, tableAlias),
378
- selected: false
379
- })).concat(Functions_1.COMPUTED_FIELDS.map(c => ({
380
- type: c.type,
381
- name: c.name,
382
- getQuery: ({ tableAlias, allowedFields }) => c.getQuery({
383
- allowedFields,
384
- ctidField: undefined,
385
- allColumns: this.columns,
386
- /* CTID not available in AFTER trigger */
387
- // ctidField: this.is_view? undefined : "ctid",
388
- tableAlias
389
- }),
390
- selected: false
391
- })));
392
- if (tableRules) {
393
- if ((0, prostgles_types_1.isEmpty)(tableRules))
394
- throw "INTERNAL ERROR: Unexpected case -> Empty table rules for " + this.name;
395
- const throwFieldsErr = (command, fieldType = "fields") => {
396
- throw `Invalid publish.${this.name}.${command} rule -> ${fieldType} setting is missing.\nPlease specify allowed ${fieldType} in this format: "*" | { col_name: false } | { col1: true, col2: true }`;
397
- }, getFirstSpecified = (...fieldParams) => {
398
- const firstValid = fieldParams.find(fp => fp !== undefined);
399
- return this.parseFieldFilter(firstValid);
400
- };
401
- const res = {
402
- allColumns,
403
- getColumns: tableRules?.getColumns ?? true,
404
- getInfo: tableRules?.getColumns ?? true,
405
- };
406
- /* SELECT */
407
- if (tableRules.select) {
408
- if (!tableRules.select.fields)
409
- return throwFieldsErr("select");
410
- let maxLimit = null;
411
- if (tableRules.select.maxLimit !== undefined && tableRules.select.maxLimit !== maxLimit) {
412
- const ml = tableRules.select.maxLimit;
413
- if (ml !== null && (!Number.isInteger(ml) || ml < 0))
414
- throw ` Invalid publish.${this.name}.select.maxLimit -> expecting a positive integer OR null but got ` + ml;
415
- maxLimit = ml;
416
- }
417
- const fields = this.parseFieldFilter(tableRules.select.fields);
418
- res.select = {
419
- fields,
420
- orderByFields: tableRules.select.orderByFields ? this.parseFieldFilter(tableRules.select.orderByFields) : fields,
421
- forcedFilter: { ...tableRules.select.forcedFilter },
422
- filterFields: this.parseFieldFilter(tableRules.select.filterFields),
423
- maxLimit
424
- };
425
- }
426
- /* UPDATE */
427
- if (tableRules.update) {
428
- if (!tableRules.update.fields)
429
- return throwFieldsErr("update");
430
- res.update = {
431
- fields: this.parseFieldFilter(tableRules.update.fields),
432
- forcedData: { ...tableRules.update.forcedData },
433
- forcedFilter: { ...tableRules.update.forcedFilter },
434
- returningFields: getFirstSpecified(tableRules.update?.returningFields, tableRules?.select?.fields, tableRules.update.fields),
435
- filterFields: this.parseFieldFilter(tableRules.update.filterFields)
436
- };
437
- }
438
- /* INSERT */
439
- if (tableRules.insert) {
440
- if (!tableRules.insert.fields)
441
- return throwFieldsErr("insert");
442
- res.insert = {
443
- fields: this.parseFieldFilter(tableRules.insert.fields),
444
- forcedData: { ...tableRules.insert.forcedData },
445
- returningFields: getFirstSpecified(tableRules.insert.returningFields, tableRules?.select?.fields, tableRules.insert.fields)
446
- };
447
- }
448
- /* DELETE */
449
- if (tableRules.delete) {
450
- if (!tableRules.delete.filterFields)
451
- return throwFieldsErr("delete", "filterFields");
452
- res.delete = {
453
- forcedFilter: { ...tableRules.delete.forcedFilter },
454
- filterFields: this.parseFieldFilter(tableRules.delete.filterFields),
455
- returningFields: getFirstSpecified(tableRules.delete.returningFields, tableRules?.select?.fields, tableRules.delete.filterFields)
456
- };
457
- }
458
- if (!tableRules.select && !tableRules.update && !tableRules.delete && !tableRules.insert) {
459
- if ([null, false].includes(tableRules.getInfo))
460
- res.getInfo = false;
461
- if ([null, false].includes(tableRules.getColumns))
462
- res.getColumns = false;
463
- }
464
- return res;
465
- }
466
- else {
467
- const all_cols = this.column_names.slice(0);
468
- return {
469
- allColumns,
470
- getColumns: true,
471
- getInfo: true,
472
- select: {
473
- fields: all_cols,
474
- filterFields: all_cols,
475
- orderByFields: all_cols,
476
- forcedFilter: {},
477
- maxLimit: null,
478
- },
479
- update: {
480
- fields: all_cols,
481
- filterFields: all_cols,
482
- forcedFilter: {},
483
- forcedData: {},
484
- returningFields: all_cols
485
- },
486
- insert: {
487
- fields: all_cols,
488
- forcedData: {},
489
- returningFields: all_cols
490
- },
491
- delete: {
492
- filterFields: all_cols,
493
- forcedFilter: {},
494
- returningFields: all_cols
495
- }
496
- };
497
- }
498
- }
499
- find = find_1.find.bind(this);
500
- findOne(filter, selectParams, param3_unused, table_rules, localParams) {
501
- try {
502
- const { select = "*", orderBy, offset = 0 } = selectParams || {};
503
- if (selectParams) {
504
- const good_params = ["select", "orderBy", "offset"];
505
- const bad_params = Object.keys(selectParams).filter(k => !good_params.includes(k));
506
- if (bad_params && bad_params.length)
507
- throw "Invalid params: " + bad_params.join(", ") + " \n Expecting: " + good_params.join(", ");
508
- }
509
- return this.find(filter, { select, orderBy, limit: 1, offset, returnType: "row" }, undefined, table_rules, localParams);
510
- }
511
- catch (e) {
512
- if (localParams && localParams.testRule)
513
- throw e;
514
- throw (0, DboBuilder_1.parseError)(e, `Issue with dbo.${this.name}.findOne()`);
515
- }
516
- }
517
- async subscribe(filter, params, localFuncs, table_rules, localParams) {
518
- //@ts-ignore
519
- return subscribe_1.subscribe.bind(this)(filter, params, localFuncs, table_rules, localParams);
520
- }
521
- subscribeOne(filter, params = {}, localFunc, table_rules, localParams) {
522
- //@ts-ignore
523
- const func = localParams ? undefined : (rows) => localFunc(rows[0]);
524
- //@ts-ignore
525
- return this.subscribe(filter, { ...params, limit: 2 }, func, table_rules, localParams);
526
- }
527
- async count(filter, param2_unused, param3_unused, table_rules, localParams) {
528
- filter = filter || {};
529
- try {
530
- return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
531
- .then(async (_allowed) => {
532
- const { filterFields, forcedFilter } = table_rules?.select || {};
533
- const where = (await this.prepareWhere({ filter, forcedFilter, filterFields, addKeywords: true, localParams, tableRule: table_rules })).where;
534
- const query = "SELECT COUNT(*) FROM " + this.escapedName + " " + where;
535
- return (this.t || this.db).one(query, { _psqlWS_tableName: this.name }).then(({ count }) => +count);
536
- });
537
- }
538
- catch (e) {
539
- if (localParams && localParams.testRule)
540
- throw e;
541
- throw (0, DboBuilder_1.parseError)(e, `dbo.${this.name}.count()`);
542
- }
543
- }
544
- async size(filter, selectParams, param3_unused, table_rules, localParams) {
545
- filter = filter || {};
546
- try {
547
- return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
548
- .then(async (_allowed) => {
549
- const q = await this.find(filter, { ...selectParams, limit: selectParams?.limit ?? Number.MAX_SAFE_INTEGER }, undefined, table_rules, { ...localParams, returnQuery: "noRLS" });
550
- const query = (0, DboBuilder_1.withUserRLS)(localParams, `
551
- SELECT sum(pg_column_size((prgl_size_query.*))) as size
552
- FROM (
553
- ${q}
554
- ) prgl_size_query
555
- `);
556
- return (this.t || this.db).one(query, { _psqlWS_tableName: this.name }).then(({ size }) => size || '0');
557
- });
558
- }
559
- catch (e) {
560
- if (localParams && localParams.testRule)
561
- throw e;
562
- throw (0, DboBuilder_1.parseError)(e, `dbo.${this.name}.size()`);
563
- }
564
- }
565
- getAllowedSelectFields(selectParams = "*", allowed_cols, allow_empty = true) {
566
- const all_columns = this.column_names.slice(0);
567
- let allowedFields = all_columns.slice(0), resultFields = [];
568
- if (selectParams) {
569
- resultFields = this.parseFieldFilter(selectParams, allow_empty);
570
- }
571
- if (allowed_cols) {
572
- allowedFields = this.parseFieldFilter(allowed_cols, allow_empty);
573
- }
574
- let col_names = (resultFields || []).filter(f => !allowedFields || allowedFields.includes(f));
575
- /* Maintain allowed cols order */
576
- if (selectParams === "*" && allowedFields && allowedFields.length) {
577
- col_names = allowedFields;
578
- }
579
- return col_names;
580
- }
581
- /**
582
- * Parses group or simple filter
583
- */
584
- async prepareWhere(params) {
585
- const { filter, select, forcedFilter, filterFields: ff, addKeywords = true, tableAlias, localParams, tableRule } = params;
586
- const { $and: $and_key, $or: $or_key } = this.dboBuilder.prostgles.keywords;
587
- let filterFields = ff;
588
- /* Local update allow all. TODO -> FIX THIS */
589
- if (!ff && !tableRule)
590
- filterFields = "*";
591
- const exists = [];
592
- const parseFullFilter = async (f, parentFilter = null, isForcedFilterBypass) => {
593
- if (!f)
594
- throw "Invalid/missing group filter provided";
595
- let result = "";
596
- const keys = (0, prostgles_types_1.getKeys)(f);
597
- if (!keys.length) {
598
- return result;
599
- }
600
- if ((keys.includes($and_key) || keys.includes($or_key))) {
601
- if (keys.length > 1)
602
- throw `\ngroup filter must contain only one array property. e.g.: { ${$and_key}: [...] } OR { ${$or_key}: [...] } `;
603
- if (parentFilter && Object.keys(parentFilter).includes(""))
604
- throw "group filter ($and/$or) can only be placed at the root or within another group filter";
605
- }
606
- const { [$and_key]: $and, [$or_key]: $or } = f, group = $and || $or;
607
- if (group && group.length) {
608
- const operand = $and ? " AND " : " OR ";
609
- const conditions = (await Promise.all(group.map(async (gf) => await parseFullFilter(gf, group, isForcedFilterBypass)))).filter(c => c);
610
- if (conditions?.length) {
611
- if (conditions.length === 1)
612
- return conditions.join(operand);
613
- else
614
- return ` ( ${conditions.sort().join(operand)} ) `;
615
- }
616
- }
617
- else if (!group) {
618
- /** forcedFilters do not get checked against publish and are treated as server-side requests */
619
- const cond = await this.getCondition({
620
- filter: { ...f },
621
- select,
622
- allowed_colnames: isForcedFilterBypass ? this.column_names.slice(0) : this.parseFieldFilter(filterFields),
623
- tableAlias,
624
- localParams: isForcedFilterBypass ? undefined : localParams,
625
- tableRules: isForcedFilterBypass ? undefined : tableRule
626
- });
627
- result = cond.condition;
628
- exists.push(...cond.exists);
629
- }
630
- return result;
631
- };
632
- if (!(0, DboBuilder_1.isPlainObject)(filter))
633
- throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(filter);
634
- /* A forced filter condition will not check if the existsJoined filter tables have been published */
635
- const forcedFilterCond = forcedFilter ? await parseFullFilter(forcedFilter, null, true) : undefined;
636
- const filterCond = await parseFullFilter(filter, null, false);
637
- let cond = [
638
- forcedFilterCond, filterCond
639
- ].filter(c => c).join(" AND ");
640
- const finalFilter = forcedFilter ? {
641
- [$and_key]: [forcedFilter, filter].filter(prostgles_types_1.isDefined)
642
- } : { ...filter };
643
- if (cond && addKeywords)
644
- cond = "WHERE " + cond;
645
- return { where: cond || "", filter: finalFilter, exists };
646
- }
647
- async prepareExistCondition(eConfig, localParams) {
648
- let res = "";
649
- const thisTable = this.name;
650
- const isNotExists = ["$notExists", "$notExistsJoined"].includes(eConfig.existType);
651
- const { f2, tables, isJoined } = eConfig;
652
- const t2 = tables.at(-1);
653
- tables.forEach(t => {
654
- if (!this.dboBuilder.dbo[t])
655
- throw { stack: ["prepareExistCondition()"], message: `Invalid or dissallowed table: ${t}` };
656
- });
657
- /* Nested $exists not allowed ??! */
658
- if (f2 && Object.keys(f2).find(fk => prostgles_types_1.EXISTS_KEYS.includes(fk))) {
659
- throw { stack: ["prepareExistCondition()"], message: "Nested exists dissallowed" };
660
- }
661
- const makeTableChain = (finalFilter) => {
662
- let joinPaths = [];
663
- let expectOne = true;
664
- tables.map((t2, depth) => {
665
- const t1 = (depth ? tables[depth - 1] : thisTable);
666
- let exactPaths = [t1, t2];
667
- if (!depth && eConfig.shortestJoin)
668
- exactPaths = undefined;
669
- const jinf = this.getJoins(t1, t2, exactPaths, true);
670
- expectOne = Boolean(expectOne && jinf.expectOne);
671
- joinPaths = joinPaths.concat(jinf.paths);
672
- });
673
- const r = makeJoin({ paths: joinPaths, expectOne }, 0);
674
- return r;
675
- function makeJoin(joinInfo, ji) {
676
- const { paths } = joinInfo;
677
- const jp = paths[ji];
678
- if (!jp)
679
- throw "jp undef";
680
- // let prevTable = ji? paths[ji - 1].table : jp.source;
681
- const table = jp.table;
682
- const tableAlias = (0, prostgles_types_1.asName)(ji < paths.length - 1 ? `jd${ji}` : table);
683
- const prevTableAlias = (0, prostgles_types_1.asName)(ji ? `jd${ji - 1}` : thisTable);
684
- const cond = `${jp.on.map(c => {
685
- return c.map(([c1, c2]) => `${prevTableAlias}.${(0, prostgles_types_1.asName)(c1)} = ${tableAlias}.${(0, prostgles_types_1.asName)(c2)}`).join(" AND ");
686
- }).join("\n OR ")}`;
687
- let j = `SELECT 1 \n` +
688
- `FROM ${(0, prostgles_types_1.asName)(table)} ${tableAlias} \n` +
689
- `WHERE (${cond}) \n`; //
690
- if (ji === paths.length - 1 &&
691
- finalFilter) {
692
- j += `AND ${finalFilter} \n`;
693
- }
694
- const indent = (a, _b) => a;
695
- if (ji < paths.length - 1) {
696
- j += `AND ${makeJoin(joinInfo, ji + 1)} \n`;
697
- }
698
- j = indent(j, ji + 1);
699
- const res = `${isNotExists ? " NOT " : " "} EXISTS ( \n` +
700
- j +
701
- `) \n`;
702
- return indent(res, ji);
703
- }
704
- };
705
- let finalWhere = "";
706
- let t2Rules = undefined, forcedFilter, filterFields, tableAlias;
707
- /* Check if allowed to view data - forcedFilters will bypass this check through isForcedFilterBypass */
708
- if (localParams?.isRemoteRequest && (!localParams?.socket && !localParams?.httpReq))
709
- throw "Unexpected: localParams isRemoteRequest and missing socket/httpReq: ";
710
- if (localParams && (localParams.socket || localParams.httpReq) && this.dboBuilder.publishParser) {
711
- t2Rules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr({ tableName: t2, command: "find", localParams });
712
- if (!t2Rules || !t2Rules.select)
713
- throw "Dissallowed";
714
- ({ forcedFilter, filterFields } = t2Rules.select);
715
- }
716
- finalWhere = (await this.dboBuilder.dbo[t2].prepareWhere({
717
- filter: f2,
718
- forcedFilter,
719
- filterFields,
720
- addKeywords: false,
721
- tableAlias,
722
- localParams,
723
- tableRule: t2Rules
724
- })).where;
725
- if (!isJoined) {
726
- res = `${isNotExists ? " NOT " : " "} EXISTS (SELECT 1 \nFROM ${(0, prostgles_types_1.asName)(t2)} \n${finalWhere ? `WHERE ${finalWhere}` : ""}) `;
727
- }
728
- else {
729
- res = makeTableChain(finalWhere);
730
- }
731
- return res;
732
- }
733
- getCondition = getCondition_1.getCondition.bind(this);
734
- /* This relates only to SELECT */
735
- prepareSortItems(orderBy, allowed_cols, tableAlias, select) {
736
- const throwErr = () => {
737
- throw "\nInvalid orderBy option -> " + JSON.stringify(orderBy) +
738
- "Expecting: \
739
- { key2: false, key1: true } \
740
- { key1: 1, key2: -1 } \
741
- [{ key1: true }, { key2: false }] \
742
- [{ key: 'colName', asc: true, nulls: 'first', nullEmpty: true }]";
743
- }, parseOrderObj = (orderBy, expectOne = false) => {
744
- if (!(0, DboBuilder_1.isPlainObject)(orderBy))
745
- return throwErr();
746
- const keys = Object.keys(orderBy);
747
- if (keys.length && keys.find(k => ["key", "asc", "nulls", "nullEmpty"].includes(k))) {
748
- const { key, asc, nulls, nullEmpty = false } = orderBy;
749
- if (!["string"].includes(typeof key) ||
750
- !["boolean"].includes(typeof asc) ||
751
- !["first", "last", undefined, null].includes(nulls) ||
752
- !["boolean"].includes(typeof nullEmpty)) {
753
- throw `Invalid orderBy option (${JSON.stringify(orderBy, null, 2)}) \n
754
- Expecting { key: string, asc?: boolean, nulls?: 'first' | 'last' | null | undefined, nullEmpty?: boolean } `;
755
- }
756
- return [{ key, asc, nulls, nullEmpty }];
757
- }
758
- if (expectOne && keys.length > 1) {
759
- throw "\nInvalid orderBy " + JSON.stringify(orderBy) +
760
- "\nEach orderBy array element cannot have more than one key";
761
- }
762
- /* { key2: true, key1: false } */
763
- if (!Object.values(orderBy).find(v => ![true, false].includes(v))) {
764
- return keys.map(key => ({ key, asc: Boolean(orderBy[key]) }));
765
- /* { key2: -1, key1: 1 } */
766
- }
767
- else if (!Object.values(orderBy).find(v => ![-1, 1].includes(v))) {
768
- return keys.map(key => ({ key, asc: orderBy[key] === 1 }));
769
- /* { key2: "asc", key1: "desc" } */
770
- }
771
- else if (!Object.values(orderBy).find(v => !["asc", "desc"].includes(v))) {
772
- return keys.map(key => ({ key, asc: orderBy[key] === "asc" }));
773
- }
774
- else
775
- return throwErr();
776
- };
777
- if (!orderBy)
778
- return [];
779
- let _ob = [];
780
- if ((0, DboBuilder_1.isPlainObject)(orderBy)) {
781
- _ob = parseOrderObj(orderBy);
782
- }
783
- else if (typeof orderBy === "string") {
784
- /* string */
785
- _ob = [{ key: orderBy, asc: true }];
786
- }
787
- else if (Array.isArray(orderBy)) {
788
- /* Order by is formed of a list of ascending field names */
789
- const _orderBy = orderBy;
790
- if (_orderBy && !_orderBy.find(v => typeof v !== "string")) {
791
- /* [string] */
792
- _ob = _orderBy.map(key => ({ key, asc: true }));
793
- }
794
- else if (_orderBy.find(v => (0, prostgles_types_1.isObject)(v) && !(0, prostgles_types_1.isEmpty)(v))) {
795
- _ob = _orderBy.map(v => parseOrderObj(v, true)[0]);
796
- }
797
- else
798
- return throwErr();
799
- }
800
- else
801
- return throwErr();
802
- if (!_ob || !_ob.length)
803
- return [];
804
- const validatedAggAliases = select.filter(s => s.type !== "joinedColumn" &&
805
- (!s.fields.length || s.fields.every(f => allowed_cols.includes(f)))).map(s => s.alias);
806
- const bad_param = _ob.find(({ key }) => !(validatedAggAliases || []).includes(key) &&
807
- !allowed_cols.includes(key));
808
- if (!bad_param) {
809
- const selectedAliases = select.filter(s => s.selected).map(s => s.alias);
810
- // return (excludeOrder? "" : " ORDER BY ") + (_ob.map(({ key, asc, nulls, nullEmpty = false }) => {
811
- return _ob.map(({ key, asc, nulls, nullEmpty = false }) => {
812
- /* Order by column index when possible to bypass name collision when ordering by a computed column.
813
- (Postgres will sort by existing columns wheundefined possible)
814
- */
815
- const orderType = asc ? " ASC " : " DESC ";
816
- const index = selectedAliases.indexOf(key) + 1;
817
- const nullOrder = nulls ? ` NULLS ${nulls === "first" ? " FIRST " : " LAST "}` : "";
818
- let colKey = (index > 0 && !nullEmpty) ? index : [tableAlias, key].filter(prostgles_types_1.isDefined).map(prostgles_types_1.asName).join(".");
819
- if (nullEmpty) {
820
- colKey = `nullif(trim(${colKey}::text), '')`;
821
- }
822
- const res = `${colKey} ${orderType} ${nullOrder}`;
823
- if (typeof colKey === "number") {
824
- return {
825
- asc,
826
- fieldPosition: colKey
827
- };
828
- }
829
- return {
830
- fieldQuery: colKey,
831
- asc,
832
- };
833
- });
834
- }
835
- else {
836
- throw "Invalid/disallowed orderBy fields or params: " + bad_param.key;
837
- }
838
- }
839
- /* This relates only to SELECT */
840
- prepareLimitQuery(limit = 1000, p) {
841
- if (limit !== undefined && limit !== null && !Number.isInteger(limit)) {
842
- throw "Unexpected LIMIT. Must be null or an integer";
843
- }
844
- let _limit = limit;
845
- // if(_limit === undefined && p.select.maxLimit === null){
846
- // _limit = 1000;
847
- /* If no limit then set as the lesser of (100, maxLimit) */
848
- // } else
849
- if (_limit !== null && !Number.isInteger(_limit) && p.select.maxLimit !== null) {
850
- _limit = [100, p.select.maxLimit].filter(Number.isInteger).sort((a, b) => a - b)[0];
851
- }
852
- else {
853
- /* If a limit higher than maxLimit specified throw error */
854
- if (Number.isInteger(p.select.maxLimit) && _limit > p.select.maxLimit) {
855
- throw `Unexpected LIMIT ${_limit}. Must be less than the published maxLimit: ` + p.select.maxLimit;
856
- }
857
- }
858
- return _limit;
859
- }
860
- /* This relates only to SELECT */
861
- prepareOffsetQuery(offset) {
862
- if (Number.isInteger(offset)) {
863
- return offset;
864
- }
865
- return 0;
866
- }
867
- intersectColumns(allowedFields, dissallowedFields, fixIssues = false) {
868
- let result = [];
869
- if (allowedFields) {
870
- result = this.parseFieldFilter(allowedFields);
871
- }
872
- if (dissallowedFields) {
873
- const _dissalowed = this.parseFieldFilter(dissallowedFields);
874
- if (!fixIssues) {
875
- throw `dissallowed/invalid field found for ${this.name}: `;
876
- }
877
- result = result.filter(key => !_dissalowed.includes(key));
878
- }
879
- return result;
880
- }
881
- /**
882
- * Prepare and validate field object:
883
- * @example ({ item_id: 1 }, { user_id: 32 }) => { item_id: 1, user_id: 32 }
884
- * OR
885
- * ({ a: 1 }, { b: 32 }, ["c", "d"]) => throw "a field is not allowed"
886
- * @param {Object} obj - initial data
887
- * @param {Object} forcedData - set/override property
888
- * @param {string[]} allowed_cols - allowed columns (excluding forcedData) from table rules
889
- */
890
- prepareFieldValues(obj = {}, forcedData = {}, allowed_cols, fixIssues = false) {
891
- const column_names = this.column_names.slice(0);
892
- if (!column_names || !column_names.length)
893
- throw "table column_names mising";
894
- let _allowed_cols = column_names.slice(0);
895
- const _obj = { ...obj };
896
- if (allowed_cols) {
897
- _allowed_cols = this.parseFieldFilter(allowed_cols, false);
898
- }
899
- let final_filter = { ..._obj };
900
- const filter_keys = Object.keys(final_filter);
901
- if (fixIssues && filter_keys.length) {
902
- final_filter = {};
903
- filter_keys
904
- .filter(col => _allowed_cols.includes(col))
905
- .map(col => {
906
- final_filter[col] = _obj[col];
907
- });
908
- }
909
- /* If has keys check against allowed_cols */
910
- if (final_filter && Object.keys(final_filter).length && _allowed_cols) {
911
- validateObj(final_filter, _allowed_cols);
912
- }
913
- if (forcedData && Object.keys(forcedData).length) {
914
- final_filter = { ...final_filter, ...forcedData };
915
- }
916
- validateObj(final_filter, column_names.slice(0));
917
- return final_filter;
918
- }
919
- parseFieldFilter(fieldParams = "*", allow_empty = true, allowed_cols) {
920
- return ViewHandler._parseFieldFilter(fieldParams, allow_empty, allowed_cols || this.column_names.slice(0));
921
- }
922
- /**
923
- * Filter string array
924
- * @param {FieldFilter} fieldParams - { col1: 0, col2: 0 } | { col1: true, col2: true } | "*" | ["key1", "key2"] | []
925
- * @param {boolean} allow_empty - allow empty select. defaults to true
926
- */
927
- static _parseFieldFilter(fieldParams = "*", allow_empty = true, all_cols) {
928
- if (!all_cols)
929
- throw "all_cols missing";
930
- const all_fields = all_cols; // || this.column_names.slice(0);
931
- let colNames = [];
932
- const initialParams = JSON.stringify(fieldParams);
933
- if (fieldParams) {
934
- /*
935
- "field1, field2, field4" | "*"
936
- */
937
- if (typeof fieldParams === "string") {
938
- fieldParams = fieldParams.split(",").map(k => k.trim());
939
- }
940
- /* string[] */
941
- if (Array.isArray(fieldParams) && !fieldParams.find(f => typeof f !== "string")) {
942
- /*
943
- ["*"]
944
- */
945
- if (fieldParams[0] === "*") {
946
- return all_fields.slice(0);
947
- /*
948
- [""]
949
- */
950
- }
951
- else if (fieldParams[0] === "") {
952
- if (allow_empty) {
953
- return [""];
954
- }
955
- else {
956
- throw "Empty value not allowed";
957
- }
958
- /*
959
- ["field1", "field2", "field3"]
960
- */
961
- }
962
- else {
963
- colNames = fieldParams.slice(0);
964
- }
965
- /*
966
- { field1: true, field2: true } = only field1 and field2
967
- { field1: false, field2: false } = all fields except field1 and field2
968
- */
969
- }
970
- else if ((0, DboBuilder_1.isPlainObject)(fieldParams)) {
971
- if (!(0, prostgles_types_1.getKeys)(fieldParams).length) {
972
- return []; //all_fields.slice(0) as typeof all_fields;
973
- }
974
- const keys = (0, prostgles_types_1.getKeys)(fieldParams);
975
- if (keys[0] === "") {
976
- if (allow_empty) {
977
- return [""];
978
- }
979
- else {
980
- throw "Empty value not allowed";
981
- }
982
- }
983
- validate(keys);
984
- keys.forEach(key => {
985
- const allowedVals = [true, false, 0, 1];
986
- if (!allowedVals.includes(fieldParams[key]))
987
- throw `Invalid field selection value for: { ${key}: ${fieldParams[key]} }. \n Allowed values: ${allowedVals.join(" OR ")}`;
988
- });
989
- const allowed = keys.filter(key => fieldParams[key]), disallowed = keys.filter(key => !fieldParams[key]);
990
- if (disallowed && disallowed.length) {
991
- return all_fields.filter(col => !disallowed.includes(col));
992
- }
993
- else {
994
- return [...allowed];
995
- }
996
- }
997
- else {
998
- throw " Unrecognised field filter.\nExpecting any of: string | string[] | { [field]: boolean } \n Received -> " + initialParams;
999
- }
1000
- validate(colNames);
1001
- }
1002
- return colNames;
1003
- function validate(cols) {
1004
- const bad_keys = cols.filter(col => !all_fields.includes(col));
1005
- if (bad_keys && bad_keys.length) {
1006
- throw "\nUnrecognised or illegal fields: " + bad_keys.join(", ");
1007
- }
1008
- }
1009
- }
1010
- }
1011
- exports.ViewHandler = ViewHandler;
1012
- /**
1013
- * Throw error if illegal keys found in object
1014
- */
1015
- function validateObj(obj, allowedKeys) {
1016
- if (obj && Object.keys(obj).length) {
1017
- const invalid_keys = Object.keys(obj).filter(k => !allowedKeys.includes(k));
1018
- if (invalid_keys.length) {
1019
- throw "Invalid/Illegal fields found: " + invalid_keys.join(", ");
1020
- }
1021
- }
1022
- return obj;
1023
- }