prostgles-server 4.2.556 → 4.2.558

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 (46) hide show
  1. package/dist/DboBuilder/TableHandler/DataValidator.d.ts +1 -1
  2. package/dist/DboBuilder/TableHandler/DataValidator.d.ts.map +1 -1
  3. package/dist/DboBuilder/TableHandler/DataValidator.js +8 -6
  4. package/dist/DboBuilder/TableHandler/DataValidator.js.map +1 -1
  5. package/dist/DboBuilder/TableHandler/TableHandler.d.ts +2 -0
  6. package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
  7. package/dist/DboBuilder/TableHandler/TableHandler.js +2 -0
  8. package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
  9. package/dist/DboBuilder/TableHandler/insert/getInsertQuery.d.ts +16 -0
  10. package/dist/DboBuilder/TableHandler/insert/getInsertQuery.d.ts.map +1 -0
  11. package/dist/DboBuilder/TableHandler/insert/getInsertQuery.js +81 -0
  12. package/dist/DboBuilder/TableHandler/insert/getInsertQuery.js.map +1 -0
  13. package/dist/DboBuilder/TableHandler/insert/insert.d.ts +4 -0
  14. package/dist/DboBuilder/TableHandler/insert/insert.d.ts.map +1 -1
  15. package/dist/DboBuilder/TableHandler/insert/insert.js +29 -84
  16. package/dist/DboBuilder/TableHandler/insert/insert.js.map +1 -1
  17. package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.d.ts +16 -3
  18. package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.d.ts.map +1 -1
  19. package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.js +32 -21
  20. package/dist/DboBuilder/TableHandler/insert/insertNestedRecords.js.map +1 -1
  21. package/dist/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.d.ts.map +1 -1
  22. package/dist/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.js +2 -2
  23. package/dist/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.js.map +1 -1
  24. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts +1 -1
  25. package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts.map +1 -1
  26. package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
  27. package/dist/DboBuilder/TableHandler/update.js +1 -0
  28. package/dist/DboBuilder/TableHandler/update.js.map +1 -1
  29. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +1 -1
  30. package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
  31. package/dist/DboBuilder/ViewHandler/ViewHandler.js +8 -8
  32. package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
  33. package/dist/DboBuilder/parseUpdateRules.d.ts.map +1 -1
  34. package/dist/DboBuilder/parseUpdateRules.js +1 -0
  35. package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
  36. package/lib/DboBuilder/TableHandler/DataValidator.ts +10 -6
  37. package/lib/DboBuilder/TableHandler/TableHandler.ts +4 -0
  38. package/lib/DboBuilder/TableHandler/insert/getInsertQuery.ts +117 -0
  39. package/lib/DboBuilder/TableHandler/insert/insert.ts +35 -105
  40. package/lib/DboBuilder/TableHandler/insert/insertNestedRecords.ts +41 -26
  41. package/lib/DboBuilder/TableHandler/insert/insertRowWithNestedRecords.ts +6 -8
  42. package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +1 -1
  43. package/lib/DboBuilder/TableHandler/update.ts +1 -0
  44. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +6 -7
  45. package/lib/DboBuilder/parseUpdateRules.ts +1 -0
  46. package/package.json +2 -2
@@ -1,20 +1,17 @@
1
1
  import type { AnyObject, InsertParams } from "prostgles-types";
2
- import {
3
- asName,
4
- getJSONBSchemaValidationError,
5
- getSerialisableError,
6
- isObject,
7
- } from "prostgles-types";
8
- import type { ParsedTableRule, ValidateRowBasic } from "../../../PublishParser/PublishParser";
2
+ import { getJSONBSchemaValidationError, getSerialisableError, isObject } from "prostgles-types";
3
+ import type { ParsedTableRule } from "../../../PublishParser/PublishParser";
4
+ import { isArray } from "../../../utils/utils";
9
5
  import type { LocalParams } from "../../DboBuilder";
10
6
  import { getSerializedClientErrorFromPGError, withUserRLS } from "../../DboBuilder";
11
- import { prepareNewData } from "../DataValidator";
7
+ import { getReturnTypeQuery } from "../../ViewHandler/getReturnTypeQuery";
12
8
  import type { TableHandler } from "../TableHandler";
13
9
  import { insertTest } from "../insertTest";
14
10
  import { runInsertUpdateQuery } from "../runInsertUpdateQuery";
11
+ import { getInsertQuery } from "./getInsertQuery";
15
12
  import { insertNestedRecords } from "./insertNestedRecords";
16
- import { getReturnTypeQuery } from "../../ViewHandler/getReturnTypeQuery";
17
- import { isArray } from "../../../utils/utils";
13
+
14
+ export type InsertedRowWithInfo = { row: AnyObject; columnsAddedFromBeforeHooks: string[] };
18
15
 
19
16
  export async function insert(
20
17
  this: TableHandler,
@@ -27,13 +24,11 @@ export async function insert(
27
24
  const ACTION = "insert";
28
25
  const start = Date.now();
29
26
  try {
30
- const { removeDisallowedFields = false } = insertParams ?? {};
31
27
  const { nestedInsert } = localParams ?? {};
32
28
 
33
29
  const rule = tableRules?.[ACTION];
34
- const { validate, allowedNestedInserts, requiredNestedInserts } = rule ?? {};
30
+ const { allowedNestedInserts, requiredNestedInserts, validate } = rule ?? {};
35
31
 
36
- const finalDBtx = this.getTransaction(localParams);
37
32
  /** Post validate and checkFilter require a transaction dbo handler because they need the action result */
38
33
  if (
39
34
  this.shouldWrapInTx(
@@ -96,7 +91,7 @@ export async function insert(
96
91
  const tx = transaction?.t || this.db;
97
92
 
98
93
  const successCallbacks: (() => void)[] = [];
99
- const preValidatedRows = await Promise.all(
94
+ const preValidatedRows: InsertedRowWithInfo[] = await Promise.all(
100
95
  rows.map(async (nonValidated) => {
101
96
  const { preValidate, validate } = rule ?? {};
102
97
  const { tableConfigurator } = this.dboBuilder.prostgles;
@@ -131,7 +126,7 @@ export async function insert(
131
126
  });
132
127
  }
133
128
 
134
- return row;
129
+ return { row, columnsAddedFromBeforeHooks: beforeResult.columnsAdded };
135
130
  }),
136
131
  );
137
132
  const preValidatedRowOrRows = isMultiInsert ? preValidatedRows : preValidatedRows[0]!;
@@ -146,103 +141,35 @@ export async function insert(
146
141
  tableRules,
147
142
  localParams,
148
143
  });
149
- const { data, insertResult } = mediaOrNestedInsert;
150
- if ("insertResult" in mediaOrNestedInsert) {
151
- return insertResult;
144
+ if (mediaOrNestedInsert.type === "nestedInserts") {
145
+ return mediaOrNestedInsert.insertResult;
152
146
  }
153
-
154
- const getInsertQuery = async (_rows: AnyObject[]) => {
155
- const validatedData = _rows.map((_row) => {
156
- const row = { ..._row };
157
-
158
- if (!isObject(row)) {
159
- throw (
160
- "\nInvalid insert data provided. Expected an object but received: " +
161
- JSON.stringify(row)
162
- );
163
- }
164
-
165
- const { data: validatedRow, allowedCols } = prepareNewData({
166
- row,
167
- forcedData,
168
- allowedFields: fields,
169
- tableRules,
170
- removeDisallowedFields,
171
- tableConfigurator: this.dboBuilder.prostgles.tableConfigurator,
172
- tableHandler: this,
173
- });
174
- return { validatedRow, allowedCols };
175
- });
176
-
177
- const validatedRows = validatedData.map((d) => d.validatedRow);
178
- const allowedCols = Array.from(new Set(validatedData.flatMap((d) => d.allowedCols)));
179
- const dbTx = finalDBtx?.dbTX || this.dboBuilder.dbo;
180
- const validationOptions = {
181
- validate: validate as ValidateRowBasic,
182
- localParams,
183
- };
184
-
185
- const query = (
186
- await this.dataValidator.parse({
187
- command: "insert",
188
- rows: validatedRows,
189
- allowedCols,
190
- dbTx,
191
- validationOptions,
192
- tx,
193
- })
194
- ).getQuery();
195
- const { onConflict } = insertParams ?? {};
196
- let conflict_query = "";
197
- if (onConflict) {
198
- const onConflictAction = typeof onConflict === "string" ? onConflict : onConflict.action;
199
- const onConflictColumns =
200
- typeof onConflict === "string" ? undefined : onConflict.conflictColumns;
201
- if (onConflictAction === "DoNothing") {
202
- conflict_query = " ON CONFLICT DO NOTHING ";
203
- } else {
204
- const firstRowKeys = Object.keys(validatedData[0]?.validatedRow ?? {});
205
- const pkeyNames = this.columns.filter((c) => c.is_pkey).map((c) => c.name);
206
- const conflictColumns =
207
- onConflictColumns ??
208
- this.tableOrViewInfo.uniqueColumnGroups?.find((colGroup) => {
209
- if (!firstRowKeys.length)
210
- throw "Cannot determine conflict columns for onConflict DoUpdate";
211
- return colGroup.some((col) => {
212
- return firstRowKeys.includes(col);
213
- });
214
- }) ??
215
- pkeyNames;
216
-
217
- /**
218
- * Table might have multiple constraint types in which case it is mandatory to specify the conflict columns.
219
- * */
220
- if (!conflictColumns.length) {
221
- throw "Cannot on conflict DoUpdate. No conflict columns could be determined. Please specify conflictColumns in onConflict param.";
222
- }
223
-
224
- const nonConflictColumns = allowedCols
225
- .filter((c) => !conflictColumns.includes(c))
226
- .map((v) => asName(v));
227
-
228
- if (nonConflictColumns.length === 0) {
229
- throw "No non conflict columns to update for onConflict=DoUpdate";
230
- }
231
- conflict_query = ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${nonConflictColumns.map((k) => `${k} = EXCLUDED.${k}`).join(", ")}`;
232
- }
233
- }
234
- return query + conflict_query;
235
- };
147
+ const { data } = mediaOrNestedInsert;
236
148
 
237
149
  let query = "";
238
- if (Array.isArray(data)) {
150
+ const commonArgs = {
151
+ fields,
152
+ forcedData,
153
+ tableHandler: this,
154
+ insertParams,
155
+ localParams,
156
+ tableRules,
157
+ validate,
158
+ };
159
+ if (isArray(data)) {
239
160
  if (!data.length) {
240
161
  throw "Empty insert. Provide data";
241
162
  }
242
163
 
243
- query = await getInsertQuery(data);
164
+ query = await getInsertQuery({
165
+ ...commonArgs,
166
+ rows: data,
167
+ });
244
168
  } else {
245
- query = await getInsertQuery([data ?? {}]);
169
+ query = await getInsertQuery({
170
+ ...commonArgs,
171
+ rows: [data],
172
+ });
246
173
  }
247
174
 
248
175
  const queryWithoutUserRLS = query;
@@ -270,7 +197,10 @@ export async function insert(
270
197
  queryWithoutUserRLS,
271
198
  tableHandler: this,
272
199
  returningFields,
273
- data: preValidatedRowOrRows,
200
+ data:
201
+ isArray(preValidatedRowOrRows) ?
202
+ preValidatedRowOrRows.map((d) => d.row)
203
+ : preValidatedRowOrRows.row,
274
204
  fields,
275
205
  params: insertParams,
276
206
  command: "insert",
@@ -5,9 +5,13 @@ import type { LocalParams } from "../../DboBuilder";
5
5
  import type { TableHandler } from "../TableHandler";
6
6
  import { getReferenceColumnInserts } from "./getReferenceColumnInserts";
7
7
  import { insertRowWithNestedRecords } from "./insertRowWithNestedRecords";
8
+ import { isArray } from "../../../utils/utils";
9
+ import type { InsertedRowWithInfo } from "./insert";
10
+
11
+ type MaybeArray<T> = T | T[];
8
12
 
9
13
  type InsertNestedRecordsArgs = {
10
- data: AnyObject | AnyObject[];
14
+ data: MaybeArray<InsertedRowWithInfo>;
11
15
  insertParams?: InsertParams;
12
16
  tableRules: ParsedTableRule | undefined;
13
17
  localParams: LocalParams | undefined;
@@ -19,10 +23,7 @@ type InsertNestedRecordsArgs = {
19
23
  export async function insertNestedRecords(
20
24
  this: TableHandler,
21
25
  { data, insertParams, tableRules, localParams }: InsertNestedRecordsArgs,
22
- ): Promise<{
23
- data?: AnyObject | AnyObject[];
24
- insertResult?: AnyObject | AnyObject[];
25
- }> {
26
+ ) {
26
27
  const MEDIA_COL_NAMES = ["data", "name"];
27
28
 
28
29
  const getExtraKeys = (row: AnyObject) =>
@@ -36,7 +37,7 @@ export async function insertNestedRecords(
36
37
  !Array.isArray(row[fieldName]) &&
37
38
  row[fieldName] !== undefined
38
39
  ) {
39
- throw new Error("Invalid/Dissalowed field in data: " + fieldName);
40
+ throw new Error("Invalid/Disallowed field in data: " + fieldName);
40
41
  } else if (!this.dboBuilder.dbo[fieldName]) {
41
42
  return false;
42
43
  }
@@ -53,13 +54,14 @@ export async function insertNestedRecords(
53
54
  * If true then will do the full insert within this function
54
55
  * Nested insert is not allowed for the file table
55
56
  * */
56
- const isMultiInsert = Array.isArray(data);
57
- const insertedRows = (isMultiInsert ? data : [data]) as AnyObject[];
58
- const insertedRowsWithNestedData = insertedRows.map((row) => {
57
+ const isMultiInsert = isArray(data);
58
+ const insertedRows = isMultiInsert ? data : [data];
59
+ const insertedRowsWithNestedData = insertedRows.map((rowWithInfo) => {
60
+ const row = { ...rowWithInfo.row };
59
61
  const extraKeys = this.is_media ? [] : getExtraKeys(row);
60
62
  const colInserts = this.is_media ? [] : getReferenceColumnInserts(this, row);
61
63
  return {
62
- row,
64
+ ...rowWithInfo,
63
65
  hasNestedData: !!(extraKeys.length || colInserts.length),
64
66
  extraKeys,
65
67
  colInserts,
@@ -67,29 +69,35 @@ export async function insertNestedRecords(
67
69
  });
68
70
  const hasNestedInserts = insertedRowsWithNestedData.some((d) => d.hasNestedData);
69
71
 
72
+ const rowOrRows =
73
+ isMultiInsert ?
74
+ insertedRowsWithNestedData.map((d) => d.row)
75
+ : insertedRowsWithNestedData[0]!.row;
70
76
  /**
71
77
  * Make sure nested insert uses a transaction
72
78
  */
73
- const { dbTX, t } = this.getTransaction(localParams) ?? {};
74
- if (hasNestedInserts && (!dbTX || !t)) {
79
+ const transaction = this.getTransaction(localParams);
80
+ if (hasNestedInserts && !transaction) {
75
81
  return {
76
- insertResult: await this.dboBuilder.getTX((dbTX, _t) =>
77
- (dbTX[this.name] as TableHandler).insert(data, insertParams, undefined, tableRules, {
82
+ type: "nestedInserts" as const,
83
+ insertResult: (await this.dboBuilder.getTX((dbTX, _t) =>
84
+ (dbTX[this.name] as TableHandler).insert(rowOrRows, insertParams, undefined, tableRules, {
78
85
  tx: { dbTX, t: _t },
79
86
  ...localParams,
80
87
  }),
81
- ),
88
+ )) as MaybeArray<AnyObject>,
82
89
  };
83
90
  }
91
+ const { dbTX } = transaction ?? {};
84
92
  const { onConflict } = insertParams || {};
85
93
  const rootOnConflict = isObject(onConflict) ? onConflict.action : onConflict;
86
94
 
87
- const _data: (AnyObject | undefined)[] = [];
88
- for (const { row, colInserts, extraKeys } of insertedRowsWithNestedData) {
89
- if (hasNestedInserts) {
90
- if (!dbTX) {
91
- throw new Error("dbTX missing for nested insert");
92
- }
95
+ if (hasNestedInserts) {
96
+ if (!dbTX) {
97
+ throw new Error("dbTX missing for nested insert");
98
+ }
99
+ const insertResult: (AnyObject | undefined)[] = [];
100
+ for (const { row, colInserts, extraKeys } of insertedRowsWithNestedData) {
93
101
  const nestedInsertResult = await insertRowWithNestedRecords.bind(this)(
94
102
  {
95
103
  row,
@@ -104,14 +112,21 @@ export async function insertNestedRecords(
104
112
  insertParams,
105
113
  },
106
114
  );
107
- _data.push(nestedInsertResult);
108
- } else {
109
- _data.push(row);
115
+ insertResult.push(nestedInsertResult);
110
116
  }
117
+
118
+ return {
119
+ type: "nestedInserts" as const,
120
+ insertResult: isMultiInsert ? insertResult : insertResult[0],
121
+ };
111
122
  }
112
123
 
124
+ const _data = insertedRowsWithNestedData.map(({ row, columnsAddedFromBeforeHooks }) => ({
125
+ row,
126
+ columnsAddedFromBeforeHooks,
127
+ }));
128
+
113
129
  const result = isMultiInsert ? _data : _data[0];
114
- const res = hasNestedInserts ? { insertResult: result } : { data: result };
115
130
 
116
- return res;
131
+ return { type: "normal" as const, data: result };
117
132
  }
@@ -36,9 +36,9 @@ export async function insertRowWithNestedRecords(
36
36
  /* Ensure we're using the same transaction */
37
37
  const tableHandler = this.tx ? this : (dbTX[this.name] as TableHandler);
38
38
 
39
- const omitedKeys = extraKeys.concat(colInserts.map((c) => c.insertedFieldName));
39
+ const omittedKeys = extraKeys.concat(colInserts.map((c) => c.insertedFieldName));
40
40
 
41
- const rootData: AnyObject = omitKeys(row, omitedKeys);
41
+ const rootData: AnyObject = omitKeys(row, omittedKeys);
42
42
 
43
43
  let insertedChildren: AnyObject[];
44
44
  let targetTableRules: ParsedTableRule;
@@ -193,12 +193,10 @@ export async function insertRowWithNestedRecords(
193
193
  }
194
194
 
195
195
  /* We expect tbl2 to have only 2 columns (media_id and foreign_id) */
196
- if (
197
- !(
198
- cols2.filter((c) => c.references?.[0]?.ftable === fileTable).length === 1 &&
199
- cols2.filter((c) => c.references?.[0]?.ftable === tableHandler.name).length === 1
200
- )
201
- ) {
196
+ if (!(
197
+ cols2.filter((c) => c.references?.[0]?.ftable === fileTable).length === 1 &&
198
+ cols2.filter((c) => c.references?.[0]?.ftable === tableHandler.name).length === 1
199
+ )) {
202
200
  console.log({
203
201
  tbl1,
204
202
  tbl2,
@@ -27,7 +27,7 @@ type RunInsertUpdateQueryArgs = {
27
27
  nestedInsertsResultsObj: Record<string, any>;
28
28
  params: UpdateParams | undefined;
29
29
  rule: UpdateRule | undefined;
30
- data: Record<string, any>;
30
+ data: AnyObject;
31
31
  }
32
32
  );
33
33
 
@@ -87,6 +87,7 @@ export async function update(
87
87
  removeDisallowedFields,
88
88
  tableConfigurator: this.dboBuilder.prostgles.tableConfigurator,
89
89
  tableHandler: this,
90
+ columnsAddedFromBeforeHooks: beforeResult.columnsAdded,
90
91
  });
91
92
 
92
93
  const updateFilter = await this.prepareWhere({
@@ -337,13 +337,12 @@ export class ViewHandler {
337
337
  /**
338
338
  * Throw error if illegal keys found in object
339
339
  */
340
- export const validateObj = <T extends Record<string, any>>(obj: T, allowedKeys: string[]): T => {
341
- if (Object.keys(obj).length) {
342
- const invalid_keys = Object.keys(obj).filter((k) => !allowedKeys.includes(k));
343
- if (invalid_keys.length) {
344
- throw "Invalid/Illegal fields found: " + invalid_keys.join(", ");
340
+ export const validateKeys = <T extends Record<string, any>>(obj: T, allowedKeys: string[]) => {
341
+ const keys = Object.keys(obj);
342
+ if (keys.length) {
343
+ const invalidKeys = keys.filter((k) => !allowedKeys.includes(k));
344
+ if (invalidKeys.length) {
345
+ throw "Invalid/Illegal fields found: " + invalidKeys.join(", ");
345
346
  }
346
347
  }
347
-
348
- return obj;
349
348
  };
@@ -153,6 +153,7 @@ export async function parseUpdateRules(
153
153
  removeDisallowedFields: false,
154
154
  tableConfigurator: this.dboBuilder.prostgles.tableConfigurator,
155
155
  tableHandler: this,
156
+ columnsAddedFromBeforeHooks: [],
156
157
  });
157
158
  let updateValidate: ValidateRowBasic | undefined;
158
159
  if (validate) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.556",
3
+ "version": "4.2.558",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,7 +57,7 @@
57
57
  "pg": "^8.21.0",
58
58
  "pg-cursor": "^2.21.0",
59
59
  "pg-promise": "^12.7.0",
60
- "prostgles-types": "^4.0.264"
60
+ "prostgles-types": "^4.0.265"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@eslint/js": "^9.22.0",