@dwtechs/antity-pgsql 0.15.2 → 0.17.0

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.
package/README.md CHANGED
@@ -22,24 +22,14 @@
22
22
  - 🚚 Shipped as EcmaScrypt module
23
23
  - 📝 Written in Typescript
24
24
 
25
-
26
- ## Support
27
-
28
- - node: 22
29
-
30
- This is the oldest targeted versions. The library should work properly on older versions of Node.js but we do not support it officially.
31
-
32
-
33
25
  ## Installation
34
26
 
35
27
  ```bash
36
28
  $ npm i @dwtechs/antity-pgsql
37
29
  ```
38
30
 
39
-
40
31
  ## Usage
41
32
 
42
-
43
33
  ```javascript
44
34
 
45
35
  import { SQLEntity } from "@dwtechs/antity-pgsql";
@@ -140,6 +130,8 @@ router.get("/:id/history", ..., entity.getHistory);
140
130
 
141
131
  type Operation = "SELECT" | "INSERT" | "UPDATE";
142
132
 
133
+ type Row = Record<string, string | number | boolean | Date | number[]>;
134
+
143
135
  type MatchMode =
144
136
  "startsWith" |
145
137
  "endsWith" |
@@ -149,6 +141,7 @@ type MatchMode =
149
141
  "notEquals" |
150
142
  "between" |
151
143
  "in" |
144
+ "notIn" |
152
145
  "lt" |
153
146
  "lte" |
154
147
  "gt" |
@@ -171,6 +164,21 @@ type Filter = {
171
164
  operator?: string; // 'and' | 'or' - Used when multiple filters apply to the same property
172
165
  }
173
166
 
167
+ type PGClient = {
168
+ query(text: string, values?: unknown[]): Promise<PGResponse>;
169
+ };
170
+
171
+ type PGResponse = {
172
+ rows: Record<string, unknown>[];
173
+ rowCount: number | null;
174
+ total?: number;
175
+ };
176
+
177
+ type SelectResponse = {
178
+ rows: Record<string, unknown>[];
179
+ total?: number;
180
+ };
181
+
174
182
  type ExpressMiddleware = (req: Request, res: Response, next: NextFunction) => void;
175
183
  type ExpressMiddlewareAsync = (req: Request, res: Response, next: NextFunction) => Promise<void>;
176
184
  type SubstackTuple = [ExpressMiddleware, ExpressMiddleware, ExpressMiddlewareAsync];
@@ -206,32 +214,28 @@ class SQLEntity {
206
214
  args: (Filter["value"])[];
207
215
  };
208
216
  update: (
209
- rows: Record<string, unknown>[],
210
- consumerId?: number | string,
211
- consumerName?: string) => {
217
+ rows: Row[],
218
+ consumer?: { id?: number | string, nickname?: string }) => {
212
219
  query: string;
213
220
  args: unknown[];
214
221
  };
215
222
  archive: (
216
- rows: Record<string, unknown>[],
217
- consumerId?: number | string,
218
- consumerName?: string) => {
223
+ rows: Row[],
224
+ consumer?: { id?: number | string, nickname?: string }) => {
219
225
  query: string;
220
226
  args: unknown[];
221
227
  };
222
228
  insert: (
223
- rows: Record<string, unknown>[],
224
- consumerId?: number | string,
225
- consumerName?: string,
229
+ rows: Row[],
230
+ consumer?: { id?: number | string, nickname?: string },
226
231
  rtn?: string) => {
227
232
  query: string;
228
233
  args: unknown[];
229
234
  };
230
235
  upsert: (
231
- rows: Record<string, unknown>[],
236
+ rows: Row[],
232
237
  conflictTarget: string | string[],
233
- consumerId?: number | string,
234
- consumerName?: string,
238
+ consumer?: { id?: number | string, nickname?: string },
235
239
  rtn?: string) => {
236
240
  query: string;
237
241
  args: unknown[];
@@ -266,7 +270,7 @@ function filter(
266
270
  function execute(
267
271
  query: string,
268
272
  args: (string | number | boolean | Date | number[])[],
269
- client: any,
273
+ client: PGClient | null,
270
274
  ): Promise<PGResponse>;
271
275
 
272
276
 
@@ -307,10 +311,10 @@ Using substacks simplifies your route definitions and ensures consistent data pr
307
311
  ### Query Methods
308
312
 
309
313
  - **query.select()**: Generates a SELECT query. When the `rows` parameter is provided (not null), pagination is automatically enabled and the query includes `COUNT(*) OVER () AS total` to return the total number of rows. The total count is extracted from results and returned separately from the row data.
310
- - **query.insert()**: Generates an INSERT query. Accepts an array of objects with properties matching the entity definition. Optionally appends `consumerId` and `consumerName` for history tracking. Supports `RETURNING` clause via the `rtn` parameter.
311
- - **query.update()**: Generates an UPDATE query using CASE statements. Accepts an array of objects with `id` property. Optionally appends `consumerId` and `consumerName` for history tracking.
312
- - **query.upsert()**: Generates an INSERT ... ON CONFLICT ... DO UPDATE query. (See [Upsert](#upsert-insert-or-update) section below.) Accepts an array of objects and a `conflictTarget` (single column name or array of column names) that defines uniqueness. If a conflict occurs on the specified column(s), the row is updated; otherwise, it is inserted. Properties are automatically included if they have both INSERT and UPDATE operations. Optionally appends `consumerId` and `consumerName` for history tracking. Supports `RETURNING` clause via the `rtn` parameter.
313
- - **query.archive()**: Generates a simplified `UPDATE ... SET archived = true WHERE id IN (...)` query. Accepts an array of objects with `id` property. Optionally appends `consumerId` and `consumerName` for history tracking. Does not require an `archived` field in the rows — it is set directly in the SQL.
314
+ - **query.insert()**: Generates an INSERT query. Accepts an array of `Row` objects with properties matching the entity definition. Consumer fields are appended directly to the query arguments — row objects are **not mutated**. Optionally appends `consumer.id` as `creatorid` and `consumer.nickname` as `name` for audit tracking. Supports `RETURNING` clause via the `rtn` parameter.
315
+ - **query.update()**: Generates an UPDATE query using CASE statements. Accepts an array of `Row` objects with `id` property. Optionally appends `consumer.id` as `updaterid` and `consumer.nickname` as `name` for audit tracking.
316
+ - **query.upsert()**: Generates an INSERT ... ON CONFLICT ... DO UPDATE query. (See [Upsert](#upsert-insert-or-update) section below.) Accepts an array of `Row` objects and a `conflictTarget` (single column name or array of column names) that defines uniqueness. If a conflict occurs on the specified column(s), the row is updated; otherwise, it is inserted. Properties are automatically included if they have both INSERT and UPDATE operations. Consumer fields are appended directly to the query arguments — row objects are **not mutated**. Optionally appends `consumer.id` as `creatorid` and `consumer.nickname` as `name` for audit tracking. Supports `RETURNING` clause via the `rtn` parameter.
317
+ - **query.archive()**: Generates a simplified `UPDATE ... SET archived = true WHERE id IN (...)` query. Accepts an array of `Row` objects with `id` property. Optionally appends `consumer.id` as `updaterid` and `consumer.nickname` as `name` for audit tracking. Does not require an `archived` field in the rows — it is set directly in the SQL.
314
318
  - **sync()**: Atomically synchronises the table with the provided rows inside a single PostgreSQL transaction. Missing rows are inserted, existing rows are updated, and rows absent from the list are deleted. Accepts optional `idField` (default `'id'`) and `filters` to restrict the scope of managed rows. Stores the result in `res.locals.rows` and a summary `{ inserted, updated, deleted }` in `res.locals.sync`.
315
319
  - **delete()**: Deletes rows by their IDs. Expects `req.body.rows` to be an array of objects with `id` property: `[{id: 1}, {id: 2}]`
316
320
  - **deleteArchive()**: Deletes archived rows that were archived before a specific date using a PostgreSQL SECURITY DEFINER function. Expects `req.body.date` to be a Date object.
@@ -372,7 +376,7 @@ res.locals.sync // { inserted: 1, updated: 1, deleted: 1 }
372
376
  - **Atomic**: All insert / update / delete operations are wrapped in a single transaction.
373
377
  - **Filter scope**: When `filters` are provided, only rows matching the filter are considered "managed". Rows outside the filter are never touched.
374
378
  - **Property selection**: Insert uses `INSERT` properties; update uses `UPDATE` properties — same as the standalone `add` and `update` middlewares.
375
- - **Consumer tracking**: `consumerId` and `consumerName` from `res.locals` are forwarded to inserts and updates for history tracking.
379
+ - **Consumer tracking**: `consumer.id` and `consumer.nickname` from `res.locals.consumer` are forwarded to inserts as `creatorid`/`name` and to updates as `updaterid`/`name` for audit tracking.
376
380
 
377
381
  ### Upsert (Insert or Update)
378
382
 
@@ -432,18 +436,17 @@ router.post('/users/upsert', ...entity.upsertArraySubstack);
432
436
  const { query, args } = entity.query.upsert(
433
437
  [{ id: 1, name: 'John', email: 'john@example.com' }],
434
438
  'id',
435
- 1, // consumerId (optional)
436
- 'admin', // consumerName (optional)
439
+ { id: 1, nickname: 'admin' }, // consumer (optional)
437
440
  'RETURNING id' // return clause (optional)
438
441
  );
439
442
  // Generates:
440
- // INSERT INTO public.users (name, email, "consumerId", "consumerName")
443
+ // INSERT INTO public.users (name, email, creatorid, name)
441
444
  // VALUES ($1, $2, $3, $4)
442
445
  // ON CONFLICT (id) DO UPDATE SET
443
446
  // name = EXCLUDED.name,
444
447
  // email = EXCLUDED.email,
445
- // "consumerId" = EXCLUDED."consumerId",
446
- // "consumerName" = EXCLUDED."consumerName"
448
+ // creatorid = EXCLUDED.creatorid,
449
+ // name = EXCLUDED.name
447
450
  // RETURNING id
448
451
  ```
449
452
 
@@ -538,7 +541,8 @@ List of possible match modes :
538
541
  | notContains | | string | Whether the value does not contain filter value |
539
542
  | equals | | string \| number | Whether the value equals the filter value |
540
543
  | notEquals | | string \| number | Whether the value does not equal the filter value |
541
- | in | | string[] \| number[] | Whether the value contains the filter value |
544
+ | in | | string[] \| number[] | Whether the value is included in the list |
545
+ | notIn | | string[] \| number[] | Whether the value is not included in the list |
542
546
  | lt | | string \| number | Whether the value is less than the filter value |
543
547
  | lte | | string \| number | Whether the value is less than or equals to the filter value |
544
548
  | gt | | string \| number | Whether the value is greater than the filter value |
@@ -557,8 +561,8 @@ List of compatible match modes for each property types
557
561
 
558
562
  | Name | Match modes |
559
563
  | :---------- | :---------------------- |
560
- | string | startsWith,<br>contains,<br>endsWith,<br>notContains,<br>equals,<br>notEquals,<br>lt,<br>lte,<br>gt,<br>gte |
561
- | number | equals,<br>notEquals,<br>lt,<br>lte,<br>gt,<br>gte |
564
+ | string | startsWith,<br>contains,<br>endsWith,<br>notContains,<br>equals,<br>notEquals,<br>in,<br>notIn,<br>lt,<br>lte,<br>gt,<br>gte |
565
+ | number | equals,<br>notEquals,<br>in,<br>notIn,<br>lt,<br>lte,<br>gt,<br>gte |
562
566
  | date | is,<br>isNot,<br>before,<br>after |
563
567
  | boolean | is,<br>isNot |
564
568
  | string[] | in |
@@ -612,21 +616,25 @@ Any of these can be passed into the options object for each function.
612
616
  | isTypeChecked | boolean | Type is checked during validation | false
613
617
  | isFilterable | boolean | property is filterable in a SELECT operation | true
614
618
  | operations | Operation[] | Property is used for the DML operations only | ["SELECT", "INSERT", "UPDATE"]
615
- | sanitizer | ((v:any) => any) \| null | Custom sanitizer function if sanitize is true | null
616
- | normalizer | ((v:any) => any) \| null | Custom Normalizer function if normalize is true | null
617
- | validator | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | validator function if validate is true | null
619
+ | sanitizer | ((v: unknown) => unknown) \| null | Custom sanitizer function if sanitize is true | null
620
+ | normalizer | ((v: unknown) => unknown) \| null | Custom Normalizer function if normalize is true | null
621
+ | validator | ((v: unknown) => unknown) \| null | validator function if validate is true | null
618
622
 
619
623
 
620
624
  * *Min and max parameters are not used for boolean type*
621
625
  * *TypeCheck Parameter is not used for boolean, string and array types*
622
626
 
627
+ ## Support
628
+
629
+ | Environment | Version |
630
+ | :---------- | :-----: |
631
+ | Node.js | >= 22 |
623
632
 
624
633
  ## Contributors
625
634
 
626
635
  Antity.js is still in development and we would be glad to get all the help you can provide.
627
636
  To contribute please read **[contributor.md](https://github.com/DWTechs/Antity.js/blob/main/contributor.md)** for detailed installation guide.
628
637
 
629
-
630
638
  ## Stack
631
639
 
632
640
  | Purpose | Choice | Motivation |
@@ -27,7 +27,6 @@ https://github.com/DWTechs/Antity-pgsql.js
27
27
  import { Entity, Property as BaseProperty } from "@dwtechs/antity";
28
28
  import type { Type, Method } from "@dwtechs/antity";
29
29
  import type { Request, Response, NextFunction } from 'express';
30
- import type { Pool, PoolClient } from 'pg';
31
30
 
32
31
  export type Operation = "SELECT" | "INSERT" | "UPDATE";
33
32
  export type Sort = "ASC" | "DESC";
@@ -75,9 +74,20 @@ export type Geometry = {
75
74
  maxLat: number;
76
75
  };
77
76
  };
77
+ export type Row = Record<string, Filter["value"]>;
78
+
79
+ export type PGClient = {
80
+ query(text: string, values?: unknown[]): Promise<PGResponse>;
81
+ };
82
+
83
+ export type SelectResponse = {
84
+ rows: Record<string, unknown>[];
85
+ total?: number;
86
+ };
87
+
78
88
  export type PGResponse = {
79
89
  rows: Record<string, unknown>[];
80
- rowCount: number;
90
+ rowCount: number | null;
81
91
  total?: number;
82
92
  command?: string;
83
93
  oid?: number;
@@ -132,27 +142,24 @@ export declare class SQLEntity extends Entity {
132
142
  };
133
143
 
134
144
  update: (
135
- rows: Record<string, unknown>[],
136
- consumerId?: number | string,
137
- consumerName?: string
145
+ rows: Row[],
146
+ consumer?: { id?: number | string, nickname?: string }
138
147
  ) => {
139
148
  query: string;
140
149
  args: unknown[];
141
150
  };
142
151
 
143
152
  archive: (
144
- rows: Record<string, unknown>[],
145
- consumerId?: number | string,
146
- consumerName?: string
153
+ rows: Row[],
154
+ consumer?: { id?: number | string, nickname?: string }
147
155
  ) => {
148
156
  query: string;
149
157
  args: unknown[];
150
158
  };
151
159
 
152
160
  insert: (
153
- rows: Record<string, unknown>[],
154
- consumerId?: number | string,
155
- consumerName?: string,
161
+ rows: Row[],
162
+ consumer?: { id?: number | string, nickname?: string },
156
163
  rtn?: string
157
164
  ) => {
158
165
  query: string;
@@ -160,10 +167,9 @@ export declare class SQLEntity extends Entity {
160
167
  };
161
168
 
162
169
  upsert: (
163
- rows: Record<string, unknown>[],
170
+ rows: Row[],
164
171
  conflictTarget: string | string[],
165
- consumerId?: number | string,
166
- consumerName?: string,
172
+ consumer?: { id?: number | string, nickname?: string },
167
173
  rtn?: string
168
174
  ) => {
169
175
  query: string;
@@ -202,6 +208,6 @@ export declare function filter(
202
208
  export declare function execute(
203
209
  query: string,
204
210
  args: (string | number | boolean | Date | number[])[],
205
- client: Pool | PoolClient | null
211
+ client: PGClient | null
206
212
  ): Promise<PGResponse>;
207
213
 
@@ -43,15 +43,15 @@ var pool = new Pool({
43
43
  const LOGS_PREFIX = '[Antity-PGSQL] ';
44
44
 
45
45
  function start(query, args) {
46
- const a = JSON.stringify(args);
47
- const q = query.replace(/[\n\r]+/g, "").replace(/\s{2,}/g, " ");
48
- log.debug(`${LOGS_PREFIX}Pgsql: { Query : '${q}', Args : '${a}' }`);
46
+ log.debug(() => {
47
+ const a = JSON.stringify(args);
48
+ const q = query.replace(/[\n\r]+/g, "").replace(/\s{2,}/g, " ");
49
+ return `${LOGS_PREFIX}Pgsql: { Query : '${q}', Args : '${a}' }`;
50
+ });
49
51
  return Date.now();
50
52
  }
51
53
  function end(res, time) {
52
- const r = JSON.stringify(res);
53
- const t = Date.now() - time;
54
- log.debug(`Pgsql response in ${t}ms : ${r}`);
54
+ log.debug(() => `Pgsql response in ${Date.now() - time}ms : ${JSON.stringify(res)}`);
55
55
  }
56
56
  var perf = {
57
57
  start,
@@ -305,19 +305,20 @@ class Insert {
305
305
  if (consumerId !== undefined && consumerName !== undefined) {
306
306
  propsToUse.push("consumerId", "consumerName");
307
307
  nbProps += 2;
308
- cols += `, "consumerId", "consumerName"`;
308
+ cols += `, creatorid, name`;
309
309
  }
310
310
  let query = `INSERT INTO ${quoteIfUppercase(schema)}.${quoteIfUppercase(table)} (${cols}) VALUES `;
311
311
  const args = [];
312
312
  let i = 0;
313
313
  for (const row of rows) {
314
- if (consumerId !== undefined && consumerName !== undefined) {
315
- row.consumerId = consumerId;
316
- row.consumerName = consumerName;
317
- }
318
314
  query += `${$i(nbProps, i)}, `;
319
315
  for (const prop of propsToUse) {
320
- args.push(row[prop]);
316
+ if (prop === "consumerId")
317
+ args.push(consumerId);
318
+ else if (prop === "consumerName")
319
+ args.push(consumerName);
320
+ else
321
+ args.push(row[prop]);
321
322
  }
322
323
  i += nbProps;
323
324
  }
@@ -356,7 +357,7 @@ class Update {
356
357
  const propsToUse = [...this._props];
357
358
  if (consumerId !== undefined && consumerName !== undefined)
358
359
  propsToUse.push("consumerId", "consumerName");
359
- log.debug(`${LOGS_PREFIX}Update query input rows: ${JSON.stringify(rows, null, 2)}`);
360
+ log.debug(() => `${LOGS_PREFIX}Update query input rows: ${JSON.stringify(rows, null, 2)}`);
360
361
  const l = rows.length;
361
362
  const args = rows.map(row => row.id);
362
363
  let query = `UPDATE ${quoteIfUppercase(schema)}.${quoteIfUppercase(table)} SET `;
@@ -364,13 +365,14 @@ class Update {
364
365
  for (const p of propsToUse) {
365
366
  if (rows[0][p] === undefined)
366
367
  continue;
367
- query += `${quoteIfUppercase(p)} = CASE `;
368
+ const colName = p === "consumerId" ? "updaterid" : p === "consumerName" ? "name" : quoteIfUppercase(p);
369
+ query += `${colName} = CASE `;
368
370
  for (let j = 0; j < l; j++) {
369
371
  const row = rows[j];
370
372
  query += `WHEN id = $${j + 1} THEN $${i++} `;
371
373
  args.push(row[p]);
372
374
  }
373
- query += `ELSE ${quoteIfUppercase(p)} END, `;
375
+ query += `ELSE ${colName} END, `;
374
376
  }
375
377
  query = `${query.slice(0, -2)} WHERE id IN ${$i(l, 0)}`;
376
378
  return { query, args };
@@ -411,9 +413,9 @@ class Upsert {
411
413
  let cols = this._cols;
412
414
  if (consumerId !== undefined && consumerName !== undefined) {
413
415
  propsToUse.push("consumerId", "consumerName");
414
- quotedPropsToUse.push(`"consumerId"`, `"consumerName"`);
416
+ quotedPropsToUse.push(`creatorid`, `name`);
415
417
  nbProps += 2;
416
- cols += `, "consumerId", "consumerName"`;
418
+ cols += `, creatorid, name`;
417
419
  }
418
420
  const conflictColumns = Array.isArray(conflictTarget)
419
421
  ? conflictTarget.map(col => quoteIfUppercase(col)).join(", ")
@@ -422,14 +424,13 @@ class Upsert {
422
424
  const args = [];
423
425
  let i = 0;
424
426
  for (const row of rows) {
425
- if (consumerId !== undefined && consumerName !== undefined) {
426
- row.consumerId = consumerId;
427
- row.consumerName = consumerName;
428
- }
429
427
  query += `${$i(nbProps, i)}, `;
430
- for (const prop of propsToUse) {
428
+ for (const prop of this._props) {
431
429
  args.push(row[prop]);
432
430
  }
431
+ if (consumerId !== undefined && consumerName !== undefined) {
432
+ args.push(consumerId, consumerName);
433
+ }
433
434
  i += nbProps;
434
435
  }
435
436
  query = query.slice(0, -2);
@@ -466,12 +467,12 @@ var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _argu
466
467
  };
467
468
  class Archive {
468
469
  query(schema, table, rows, consumerId, consumerName) {
469
- log.debug(`${LOGS_PREFIX}Archive query input rows: ${JSON.stringify(rows, null, 2)}`);
470
+ log.debug(() => `${LOGS_PREFIX}Archive query input rows: ${JSON.stringify(rows, null, 2)}`);
470
471
  const l = rows.length;
471
472
  const args = rows.map(row => row.id);
472
473
  let query = `UPDATE ${quoteIfUppercase(schema)}.${quoteIfUppercase(table)} SET archived = true`;
473
474
  if (consumerId !== undefined && consumerName !== undefined) {
474
- query += `, ${quoteIfUppercase("consumerId")} = $${l + 1}, ${quoteIfUppercase("consumerName")} = $${l + 2}`;
475
+ query += `, updaterid = $${l + 1}, name = $${l + 2}`;
475
476
  args.push(consumerId, consumerName);
476
477
  }
477
478
  query += ` WHERE id IN ${$i(l, 0)}`;
@@ -587,12 +588,12 @@ function cleanFilters(filters, properties) {
587
588
  if (filters.hasOwnProperty(k)) {
588
589
  const prop = properties.find(p => p.key === k);
589
590
  if (!prop) {
590
- log.warn(`${LOGS_PREFIX}Filters: skipping unknown property: ${k}`);
591
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping unknown property: ${k}`);
591
592
  delete filters[k];
592
593
  continue;
593
594
  }
594
595
  if (!prop.isFilterable) {
595
- log.warn(`${LOGS_PREFIX}Filters: skipping unfilterable property: ${k}`);
596
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping unfilterable property: ${k}`);
596
597
  delete filters[k];
597
598
  continue;
598
599
  }
@@ -602,7 +603,7 @@ function cleanFilters(filters, properties) {
602
603
  const validFilters = filterArray.filter((f) => {
603
604
  const { matchMode: matchMode$1 } = f;
604
605
  if (!matchMode$1 || !matchMode(type$1, matchMode$1)) {
605
- log.warn(`${LOGS_PREFIX}Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
606
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
606
607
  return false;
607
608
  }
608
609
  return true;
@@ -617,9 +618,8 @@ function cleanFilters(filters, properties) {
617
618
  }
618
619
 
619
620
  function logSummary(name, table, properties) {
620
- const summary = generateSummary(name, table, properties);
621
621
  log.info(`${LOGS_PREFIX}Entity "${name}" created successfully`);
622
- log.info(`${LOGS_PREFIX}Entity Summary:\n${summary}`);
622
+ log.info(() => `${LOGS_PREFIX}Entity Summary:\n${generateSummary(name, table, properties)}`);
623
623
  }
624
624
  function generateSummary(name, table, properties) {
625
625
  const lines = [];
@@ -702,20 +702,20 @@ class SQLEntity extends Entity {
702
702
  select: (first = 0, rows = null, sortField = null, sortOrder = null, filters = null) => {
703
703
  return this.sel.query(this.schema, this.table, first, rows, sortField, sortOrder, filters);
704
704
  },
705
- update: (rows, consumerId, consumerName) => {
706
- return this.upd.query(this.schema, this.table, rows, consumerId, consumerName);
705
+ update: (rows, consumer) => {
706
+ return this.upd.query(this.schema, this.table, rows, consumer === null || consumer === void 0 ? void 0 : consumer.id, consumer === null || consumer === void 0 ? void 0 : consumer.nickname);
707
707
  },
708
- insert: (rows, consumerId, consumerName, rtn = "") => {
709
- return this.ins.query(this.schema, this.table, rows, consumerId, consumerName, rtn);
708
+ insert: (rows, consumer, rtn = "") => {
709
+ return this.ins.query(this.schema, this.table, rows, consumer === null || consumer === void 0 ? void 0 : consumer.id, consumer === null || consumer === void 0 ? void 0 : consumer.nickname, rtn);
710
710
  },
711
- upsert: (rows, conflictTarget, consumerId, consumerName, rtn = "") => {
712
- return this.ups.query(this.schema, this.table, rows, conflictTarget, consumerId, consumerName, rtn);
711
+ upsert: (rows, conflictTarget, consumer, rtn = "") => {
712
+ return this.ups.query(this.schema, this.table, rows, conflictTarget, consumer === null || consumer === void 0 ? void 0 : consumer.id, consumer === null || consumer === void 0 ? void 0 : consumer.nickname, rtn);
713
713
  },
714
714
  delete: (ids) => {
715
715
  return queryById(this.schema, this.table, ids);
716
716
  },
717
- archive: (rows, consumerId, consumerName) => {
718
- return this.arc.query(this.schema, this.table, rows, consumerId, consumerName);
717
+ archive: (rows, consumer) => {
718
+ return this.arc.query(this.schema, this.table, rows, consumer === null || consumer === void 0 ? void 0 : consumer.id, consumer === null || consumer === void 0 ? void 0 : consumer.nickname);
719
719
  },
720
720
  deleteArchive: () => {
721
721
  return queryByDate();
@@ -735,9 +735,7 @@ class SQLEntity extends Entity {
735
735
  const filters = cleanFilters(b.filters, this.properties) || null;
736
736
  const pagination = b.pagination || false;
737
737
  const dbClient = l.dbClient || null;
738
- log.debug(`get(first='${first}', rows='${rows}',
739
- sortOrder='${sortOrder}', sortField='${sortField}',
740
- pagination=${pagination}, filters=${JSON.stringify(filters)}`);
738
+ log.debug(() => `get(first='${first}', rows='${rows}', sortOrder='${sortOrder}', sortField='${sortField}', pagination=${pagination}, filters=${JSON.stringify(filters)}`);
741
739
  const { query, args } = this.sel.query(this._schema, this._table, first, rows, sortField, sortOrder, filters);
742
740
  this.sel.execute(query, args, dbClient)
743
741
  .then((r) => {
@@ -748,12 +746,13 @@ class SQLEntity extends Entity {
748
746
  .catch((err) => next(err));
749
747
  };
750
748
  this.add = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
749
+ var _a, _b;
751
750
  const l = res.locals;
752
751
  const rows = req.body.rows;
753
752
  const dbClient = l.dbClient || null;
754
- const cId = l.consumerId;
755
- const cName = l.consumerName;
756
- log.debug(`${LOGS_PREFIX}addMany(rows=${rows.length}, consumerId=${cId})`);
753
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
754
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
755
+ log.debug(() => `${LOGS_PREFIX}addMany(rows=${rows.length}, consumerId=${cId})`);
757
756
  const rtn = this.ins.rtn("id");
758
757
  const chunks = chunk(rows);
759
758
  for (const c of chunks) {
@@ -774,12 +773,13 @@ class SQLEntity extends Entity {
774
773
  next();
775
774
  });
776
775
  this.update = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
776
+ var _a, _b;
777
777
  const l = res.locals;
778
778
  const r = req.body.rows;
779
779
  const dbClient = l.dbClient || null;
780
- const cId = l.consumerId;
781
- const cName = l.consumerName;
782
- log.debug(`${LOGS_PREFIX}update(rows=${r.length}, consumerId=${cId})`);
780
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
781
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
782
+ log.debug(() => `${LOGS_PREFIX}update(rows=${r.length}, consumerId=${cId})`);
783
783
  const chunks = chunk(r);
784
784
  for (const c of chunks) {
785
785
  const { query, args } = this.upd.query(this._schema, this._table, c, cId, cName);
@@ -794,19 +794,20 @@ class SQLEntity extends Entity {
794
794
  next();
795
795
  });
796
796
  this.upsert = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
797
+ var _a, _b;
797
798
  const l = res.locals;
798
799
  const rows = req.body.rows;
799
800
  const conflictTarget = req.body.conflictTarget;
800
801
  const dbClient = l.dbClient || null;
801
- const cId = l.consumerId;
802
- const cName = l.consumerName;
802
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
803
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
803
804
  if (!conflictTarget) {
804
805
  return next({ status: 400, msg: "Missing conflictTarget for upsert operation" });
805
806
  }
806
807
  if (!rows || !Array.isArray(rows) || rows.length === 0) {
807
808
  return next({ status: 400, msg: "Missing or empty rows array for upsert operation" });
808
809
  }
809
- log.debug(`${LOGS_PREFIX}upsert(rows=${rows.length}, conflictTarget=${conflictTarget}, consumerId=${cId})`);
810
+ log.debug(() => `${LOGS_PREFIX}upsert(rows=${rows.length}, conflictTarget=${conflictTarget}, consumerId=${cId})`);
810
811
  const rtn = this.ups.rtn("id");
811
812
  const chunks = chunk(rows);
812
813
  for (const c of chunks) {
@@ -827,12 +828,13 @@ class SQLEntity extends Entity {
827
828
  next();
828
829
  });
829
830
  this.archive = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
831
+ var _a, _b;
830
832
  const l = res.locals;
831
- let r = req.body.rows;
833
+ const r = req.body.rows;
832
834
  const dbClient = l.dbClient || null;
833
- const cId = l.consumerId;
834
- const cName = l.consumerName;
835
- log.debug(`${LOGS_PREFIX}archive(rows=${r.length}, consumerId=${cId})`);
835
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
836
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
837
+ log.debug(() => `${LOGS_PREFIX}archive(rows=${r.length}, consumerId=${cId})`);
836
838
  const chunks = chunk(r);
837
839
  for (const c of chunks) {
838
840
  const { query, args } = this.arc.query(this._schema, this._table, c, cId, cName);
@@ -849,7 +851,7 @@ class SQLEntity extends Entity {
849
851
  const rows = req.body.rows;
850
852
  const dbClient = res.locals.dbClient || null;
851
853
  const ids = rows.map((row) => row.id);
852
- log.debug(`${LOGS_PREFIX}delete ${rows.length} rows : (${ids.join(", ")})`);
854
+ log.debug(() => `${LOGS_PREFIX}delete ${rows.length} rows : (${ids.join(", ")})`);
853
855
  const { query, args } = queryById(this._schema, this._table, ids);
854
856
  try {
855
857
  yield execute(query, args, dbClient);
@@ -862,7 +864,7 @@ class SQLEntity extends Entity {
862
864
  this.deleteArchive = (req, res, next) => {
863
865
  const date = req.body.date;
864
866
  const dbClient = res.locals.dbClient || null;
865
- log.debug(`${LOGS_PREFIX}deleteArchive(schema=${this._schema}, table=${this._table}, date=${date})`);
867
+ log.debug(() => `${LOGS_PREFIX}deleteArchive(schema=${this._schema}, table=${this._table}, date=${date})`);
866
868
  executeArchived(this._schema, this._table, date, queryByDate(), dbClient)
867
869
  .then(() => next())
868
870
  .catch((err) => next(err));
@@ -871,9 +873,10 @@ class SQLEntity extends Entity {
871
873
  const id = req.params.id;
872
874
  const dbClient = res.locals.dbClient || null;
873
875
  if (!id) {
874
- return next({ status: 400, msg: "Missing id" });
876
+ next({ status: 400, msg: "Missing id" });
877
+ return;
875
878
  }
876
- log.debug(`${LOGS_PREFIX}getHistory(schema=${this._schema}, table=${this._table}, id=${id})`);
879
+ log.debug(() => `${LOGS_PREFIX}getHistory(schema=${this._schema}, table=${this._table}, id=${id})`);
877
880
  const sql = `
878
881
  SELECT id, tstamp, operation, "consumerId", "consumerName"
879
882
  FROM log.history
@@ -895,16 +898,16 @@ class SQLEntity extends Entity {
895
898
  .catch((err) => next(err));
896
899
  };
897
900
  this.sync = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
898
- var _a;
901
+ var _a, _b, _c;
899
902
  const l = res.locals;
900
903
  const rows = req.body.rows;
901
904
  const idField = (_a = req.body.idField) !== null && _a !== void 0 ? _a : 'id';
902
- const cId = l.consumerId;
903
- const cName = l.consumerName;
905
+ const cId = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.id;
906
+ const cName = (_c = l.consumer) === null || _c === void 0 ? void 0 : _c.nickname;
904
907
  if (!rows || !Array.isArray(rows)) {
905
908
  return next({ status: 400, msg: "Missing or invalid rows array for sync operation" });
906
909
  }
907
- log.debug(`${LOGS_PREFIX}sync(rows=${rows.length}, idField=${idField}, consumerId=${cId})`);
910
+ log.debug(() => `${LOGS_PREFIX}sync(rows=${rows.length}, idField=${idField}, consumerId=${cId})`);
908
911
  const cleanedFilters = cleanFilters(req.body.filters, this.properties) || null;
909
912
  const { conditions, args: filterArgs } = add(cleanedFilters);
910
913
  const whereClause = conditions.length ? ` WHERE ${conditions.join(' AND ')}` : '';
@@ -964,7 +967,7 @@ class SQLEntity extends Entity {
964
967
  });
965
968
  this._table = name;
966
969
  this._schema = schema;
967
- log.info(`${LOGS_PREFIX}Creating SQLEntity: "${name}"`);
970
+ log.info(() => `${LOGS_PREFIX}Creating SQLEntity: "${name}"`);
968
971
  for (const p of properties) {
969
972
  this.mapProps(p.operations, p.key);
970
973
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity-pgsql",
3
- "version": "0.15.2",
3
+ "version": "0.17.0",
4
4
  "description": "Open source library to add PostgreSQL support to @dwtechs/Antity entities.",
5
5
  "keywords": [
6
6
  "entities"
@@ -37,7 +37,7 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@dwtechs/checkard": "3.6.0",
40
- "@dwtechs/winstan": "0.5.0",
40
+ "@dwtechs/winstan": "0.7.0",
41
41
  "@dwtechs/antity": "0.16.0",
42
42
  "@dwtechs/sparray": "0.2.1",
43
43
  "pg": "8.20.0"