@dwtechs/antity-pgsql 0.15.1 → 0.16.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` and `consumer.nickname` for history 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` and `consumer.nickname` for history 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` and `consumer.nickname` for history 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` and `consumer.nickname` for history 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 and updates for history tracking.
376
380
 
377
381
  ### Upsert (Insert or Update)
378
382
 
@@ -432,8 +436,7 @@ 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:
@@ -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,
@@ -108,6 +108,7 @@ function index(index, matchMode) {
108
108
  const i = index.map((i) => `$${i}`);
109
109
  switch (matchMode) {
110
110
  case "in":
111
+ case "notIn":
111
112
  return `(${i})`;
112
113
  default:
113
114
  return `${i}`;
@@ -130,6 +131,8 @@ function comparator(matchMode) {
130
131
  return "<>";
131
132
  case "in":
132
133
  return "IN";
134
+ case "notIn":
135
+ return "NOT IN";
133
136
  case "lt":
134
137
  return "<";
135
138
  case "lte":
@@ -308,13 +311,14 @@ class Insert {
308
311
  const args = [];
309
312
  let i = 0;
310
313
  for (const row of rows) {
311
- if (consumerId !== undefined && consumerName !== undefined) {
312
- row.consumerId = consumerId;
313
- row.consumerName = consumerName;
314
- }
315
314
  query += `${$i(nbProps, i)}, `;
316
315
  for (const prop of propsToUse) {
317
- 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]);
318
322
  }
319
323
  i += nbProps;
320
324
  }
@@ -353,7 +357,7 @@ class Update {
353
357
  const propsToUse = [...this._props];
354
358
  if (consumerId !== undefined && consumerName !== undefined)
355
359
  propsToUse.push("consumerId", "consumerName");
356
- 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)}`);
357
361
  const l = rows.length;
358
362
  const args = rows.map(row => row.id);
359
363
  let query = `UPDATE ${quoteIfUppercase(schema)}.${quoteIfUppercase(table)} SET `;
@@ -419,14 +423,13 @@ class Upsert {
419
423
  const args = [];
420
424
  let i = 0;
421
425
  for (const row of rows) {
422
- if (consumerId !== undefined && consumerName !== undefined) {
423
- row.consumerId = consumerId;
424
- row.consumerName = consumerName;
425
- }
426
426
  query += `${$i(nbProps, i)}, `;
427
- for (const prop of propsToUse) {
427
+ for (const prop of this._props) {
428
428
  args.push(row[prop]);
429
429
  }
430
+ if (consumerId !== undefined && consumerName !== undefined) {
431
+ args.push(consumerId, consumerName);
432
+ }
430
433
  i += nbProps;
431
434
  }
432
435
  query = query.slice(0, -2);
@@ -463,7 +466,7 @@ var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _argu
463
466
  };
464
467
  class Archive {
465
468
  query(schema, table, rows, consumerId, consumerName) {
466
- log.debug(`${LOGS_PREFIX}Archive query input rows: ${JSON.stringify(rows, null, 2)}`);
469
+ log.debug(() => `${LOGS_PREFIX}Archive query input rows: ${JSON.stringify(rows, null, 2)}`);
467
470
  const l = rows.length;
468
471
  const args = rows.map(row => row.id);
469
472
  let query = `UPDATE ${quoteIfUppercase(schema)}.${quoteIfUppercase(table)} SET archived = true`;
@@ -571,8 +574,8 @@ function type(type) {
571
574
  }
572
575
 
573
576
  const matchModes = {
574
- string: ["startsWith", "contains", "endsWith", "notContains", "equals", "notEquals", "lt", "lte", "gt", "gte"],
575
- number: ["equals", "notEquals", "lt", "lte", "gt", "gte"],
577
+ string: ["startsWith", "contains", "endsWith", "notContains", "equals", "notEquals", "lt", "lte", "gt", "gte", "in", "notIn"],
578
+ number: ["equals", "notEquals", "lt", "lte", "gt", "gte", "in", "notIn"],
576
579
  date: ["is", "isNot", "dateAfter"],
577
580
  };
578
581
  function matchMode(type, matchMode) {
@@ -584,12 +587,12 @@ function cleanFilters(filters, properties) {
584
587
  if (filters.hasOwnProperty(k)) {
585
588
  const prop = properties.find(p => p.key === k);
586
589
  if (!prop) {
587
- log.warn(`${LOGS_PREFIX}Filters: skipping unknown property: ${k}`);
590
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping unknown property: ${k}`);
588
591
  delete filters[k];
589
592
  continue;
590
593
  }
591
594
  if (!prop.isFilterable) {
592
- log.warn(`${LOGS_PREFIX}Filters: skipping unfilterable property: ${k}`);
595
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping unfilterable property: ${k}`);
593
596
  delete filters[k];
594
597
  continue;
595
598
  }
@@ -599,7 +602,7 @@ function cleanFilters(filters, properties) {
599
602
  const validFilters = filterArray.filter((f) => {
600
603
  const { matchMode: matchMode$1 } = f;
601
604
  if (!matchMode$1 || !matchMode(type$1, matchMode$1)) {
602
- log.warn(`${LOGS_PREFIX}Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
605
+ log.warn(() => `${LOGS_PREFIX}Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
603
606
  return false;
604
607
  }
605
608
  return true;
@@ -614,9 +617,8 @@ function cleanFilters(filters, properties) {
614
617
  }
615
618
 
616
619
  function logSummary(name, table, properties) {
617
- const summary = generateSummary(name, table, properties);
618
620
  log.info(`${LOGS_PREFIX}Entity "${name}" created successfully`);
619
- log.info(`${LOGS_PREFIX}Entity Summary:\n${summary}`);
621
+ log.info(() => `${LOGS_PREFIX}Entity Summary:\n${generateSummary(name, table, properties)}`);
620
622
  }
621
623
  function generateSummary(name, table, properties) {
622
624
  const lines = [];
@@ -699,20 +701,20 @@ class SQLEntity extends Entity {
699
701
  select: (first = 0, rows = null, sortField = null, sortOrder = null, filters = null) => {
700
702
  return this.sel.query(this.schema, this.table, first, rows, sortField, sortOrder, filters);
701
703
  },
702
- update: (rows, consumerId, consumerName) => {
703
- return this.upd.query(this.schema, this.table, rows, consumerId, consumerName);
704
+ update: (rows, consumer) => {
705
+ 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);
704
706
  },
705
- insert: (rows, consumerId, consumerName, rtn = "") => {
706
- return this.ins.query(this.schema, this.table, rows, consumerId, consumerName, rtn);
707
+ insert: (rows, consumer, rtn = "") => {
708
+ 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);
707
709
  },
708
- upsert: (rows, conflictTarget, consumerId, consumerName, rtn = "") => {
709
- return this.ups.query(this.schema, this.table, rows, conflictTarget, consumerId, consumerName, rtn);
710
+ upsert: (rows, conflictTarget, consumer, rtn = "") => {
711
+ 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);
710
712
  },
711
713
  delete: (ids) => {
712
714
  return queryById(this.schema, this.table, ids);
713
715
  },
714
- archive: (rows, consumerId, consumerName) => {
715
- return this.arc.query(this.schema, this.table, rows, consumerId, consumerName);
716
+ archive: (rows, consumer) => {
717
+ 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);
716
718
  },
717
719
  deleteArchive: () => {
718
720
  return queryByDate();
@@ -732,9 +734,7 @@ class SQLEntity extends Entity {
732
734
  const filters = cleanFilters(b.filters, this.properties) || null;
733
735
  const pagination = b.pagination || false;
734
736
  const dbClient = l.dbClient || null;
735
- log.debug(`get(first='${first}', rows='${rows}',
736
- sortOrder='${sortOrder}', sortField='${sortField}',
737
- pagination=${pagination}, filters=${JSON.stringify(filters)}`);
737
+ log.debug(() => `get(first='${first}', rows='${rows}', sortOrder='${sortOrder}', sortField='${sortField}', pagination=${pagination}, filters=${JSON.stringify(filters)}`);
738
738
  const { query, args } = this.sel.query(this._schema, this._table, first, rows, sortField, sortOrder, filters);
739
739
  this.sel.execute(query, args, dbClient)
740
740
  .then((r) => {
@@ -745,12 +745,13 @@ class SQLEntity extends Entity {
745
745
  .catch((err) => next(err));
746
746
  };
747
747
  this.add = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
748
+ var _a, _b;
748
749
  const l = res.locals;
749
750
  const rows = req.body.rows;
750
751
  const dbClient = l.dbClient || null;
751
- const cId = l.consumerId;
752
- const cName = l.consumerName;
753
- log.debug(`${LOGS_PREFIX}addMany(rows=${rows.length}, consumerId=${cId})`);
752
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
753
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
754
+ log.debug(() => `${LOGS_PREFIX}addMany(rows=${rows.length}, consumerId=${cId})`);
754
755
  const rtn = this.ins.rtn("id");
755
756
  const chunks = chunk(rows);
756
757
  for (const c of chunks) {
@@ -771,12 +772,13 @@ class SQLEntity extends Entity {
771
772
  next();
772
773
  });
773
774
  this.update = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
775
+ var _a, _b;
774
776
  const l = res.locals;
775
777
  const r = req.body.rows;
776
778
  const dbClient = l.dbClient || null;
777
- const cId = l.consumerId;
778
- const cName = l.consumerName;
779
- log.debug(`${LOGS_PREFIX}update(rows=${r.length}, consumerId=${cId})`);
779
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
780
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
781
+ log.debug(() => `${LOGS_PREFIX}update(rows=${r.length}, consumerId=${cId})`);
780
782
  const chunks = chunk(r);
781
783
  for (const c of chunks) {
782
784
  const { query, args } = this.upd.query(this._schema, this._table, c, cId, cName);
@@ -791,19 +793,20 @@ class SQLEntity extends Entity {
791
793
  next();
792
794
  });
793
795
  this.upsert = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
796
+ var _a, _b;
794
797
  const l = res.locals;
795
798
  const rows = req.body.rows;
796
799
  const conflictTarget = req.body.conflictTarget;
797
800
  const dbClient = l.dbClient || null;
798
- const cId = l.consumerId;
799
- const cName = l.consumerName;
801
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
802
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
800
803
  if (!conflictTarget) {
801
804
  return next({ status: 400, msg: "Missing conflictTarget for upsert operation" });
802
805
  }
803
806
  if (!rows || !Array.isArray(rows) || rows.length === 0) {
804
807
  return next({ status: 400, msg: "Missing or empty rows array for upsert operation" });
805
808
  }
806
- log.debug(`${LOGS_PREFIX}upsert(rows=${rows.length}, conflictTarget=${conflictTarget}, consumerId=${cId})`);
809
+ log.debug(() => `${LOGS_PREFIX}upsert(rows=${rows.length}, conflictTarget=${conflictTarget}, consumerId=${cId})`);
807
810
  const rtn = this.ups.rtn("id");
808
811
  const chunks = chunk(rows);
809
812
  for (const c of chunks) {
@@ -824,12 +827,13 @@ class SQLEntity extends Entity {
824
827
  next();
825
828
  });
826
829
  this.archive = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
830
+ var _a, _b;
827
831
  const l = res.locals;
828
- let r = req.body.rows;
832
+ const r = req.body.rows;
829
833
  const dbClient = l.dbClient || null;
830
- const cId = l.consumerId;
831
- const cName = l.consumerName;
832
- log.debug(`${LOGS_PREFIX}archive(rows=${r.length}, consumerId=${cId})`);
834
+ const cId = (_a = l.consumer) === null || _a === void 0 ? void 0 : _a.id;
835
+ const cName = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.nickname;
836
+ log.debug(() => `${LOGS_PREFIX}archive(rows=${r.length}, consumerId=${cId})`);
833
837
  const chunks = chunk(r);
834
838
  for (const c of chunks) {
835
839
  const { query, args } = this.arc.query(this._schema, this._table, c, cId, cName);
@@ -846,7 +850,7 @@ class SQLEntity extends Entity {
846
850
  const rows = req.body.rows;
847
851
  const dbClient = res.locals.dbClient || null;
848
852
  const ids = rows.map((row) => row.id);
849
- log.debug(`${LOGS_PREFIX}delete ${rows.length} rows : (${ids.join(", ")})`);
853
+ log.debug(() => `${LOGS_PREFIX}delete ${rows.length} rows : (${ids.join(", ")})`);
850
854
  const { query, args } = queryById(this._schema, this._table, ids);
851
855
  try {
852
856
  yield execute(query, args, dbClient);
@@ -859,7 +863,7 @@ class SQLEntity extends Entity {
859
863
  this.deleteArchive = (req, res, next) => {
860
864
  const date = req.body.date;
861
865
  const dbClient = res.locals.dbClient || null;
862
- log.debug(`${LOGS_PREFIX}deleteArchive(schema=${this._schema}, table=${this._table}, date=${date})`);
866
+ log.debug(() => `${LOGS_PREFIX}deleteArchive(schema=${this._schema}, table=${this._table}, date=${date})`);
863
867
  executeArchived(this._schema, this._table, date, queryByDate(), dbClient)
864
868
  .then(() => next())
865
869
  .catch((err) => next(err));
@@ -868,9 +872,10 @@ class SQLEntity extends Entity {
868
872
  const id = req.params.id;
869
873
  const dbClient = res.locals.dbClient || null;
870
874
  if (!id) {
871
- return next({ status: 400, msg: "Missing id" });
875
+ next({ status: 400, msg: "Missing id" });
876
+ return;
872
877
  }
873
- log.debug(`${LOGS_PREFIX}getHistory(schema=${this._schema}, table=${this._table}, id=${id})`);
878
+ log.debug(() => `${LOGS_PREFIX}getHistory(schema=${this._schema}, table=${this._table}, id=${id})`);
874
879
  const sql = `
875
880
  SELECT id, tstamp, operation, "consumerId", "consumerName"
876
881
  FROM log.history
@@ -892,16 +897,16 @@ class SQLEntity extends Entity {
892
897
  .catch((err) => next(err));
893
898
  };
894
899
  this.sync = (req, res, next) => __awaiter(this, void 0, void 0, function* () {
895
- var _a;
900
+ var _a, _b, _c;
896
901
  const l = res.locals;
897
902
  const rows = req.body.rows;
898
903
  const idField = (_a = req.body.idField) !== null && _a !== void 0 ? _a : 'id';
899
- const cId = l.consumerId;
900
- const cName = l.consumerName;
904
+ const cId = (_b = l.consumer) === null || _b === void 0 ? void 0 : _b.id;
905
+ const cName = (_c = l.consumer) === null || _c === void 0 ? void 0 : _c.nickname;
901
906
  if (!rows || !Array.isArray(rows)) {
902
907
  return next({ status: 400, msg: "Missing or invalid rows array for sync operation" });
903
908
  }
904
- log.debug(`${LOGS_PREFIX}sync(rows=${rows.length}, idField=${idField}, consumerId=${cId})`);
909
+ log.debug(() => `${LOGS_PREFIX}sync(rows=${rows.length}, idField=${idField}, consumerId=${cId})`);
905
910
  const cleanedFilters = cleanFilters(req.body.filters, this.properties) || null;
906
911
  const { conditions, args: filterArgs } = add(cleanedFilters);
907
912
  const whereClause = conditions.length ? ` WHERE ${conditions.join(' AND ')}` : '';
@@ -961,7 +966,7 @@ class SQLEntity extends Entity {
961
966
  });
962
967
  this._table = name;
963
968
  this._schema = schema;
964
- log.info(`${LOGS_PREFIX}Creating SQLEntity: "${name}"`);
969
+ log.info(() => `${LOGS_PREFIX}Creating SQLEntity: "${name}"`);
965
970
  for (const p of properties) {
966
971
  this.mapProps(p.operations, p.key);
967
972
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/antity-pgsql",
3
- "version": "0.15.1",
3
+ "version": "0.16.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"