@dwtechs/antity-pgsql 0.3.2 โ†’ 0.4.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
@@ -3,13 +3,11 @@
3
3
  [![npm version](https://badge.fury.io/js/%40dwtechs%2Fantity-pgsql.svg)](https://www.npmjs.com/package/@dwtechs/antity-pgsql)
4
4
  [![last version release date](https://img.shields.io/github/release-date/DWTechs/Antity-pgsql.js)](https://www.npmjs.com/package/@dwtechs/antity-pgsql)
5
5
  ![Jest:coverage](https://img.shields.io/badge/Jest:coverage-100%25-brightgreen.svg)
6
- [![minified size](https://img.shields.io/bundlephobia/min/@dwtechs/antity-pgsql?color=brightgreen)](https://www.npmjs.com/package/@dwtechs/antity-pgsql)
7
6
 
8
7
  - [Synopsis](#synopsis)
9
8
  - [Support](#support)
10
9
  - [Installation](#installation)
11
10
  - [Usage](#usage)
12
- - [ES6](#es6)
13
11
  - [API Reference](#api-reference)
14
12
  - [Contributors](#contributors)
15
13
  - [Stack](#stack)
@@ -19,11 +17,10 @@
19
17
 
20
18
  **[Antity-pgsql.js](https://github.com/DWTechs/Antity-pgsql.js)** adds PostgreSQL features to **Antity.js** library.
21
19
 
22
- - Very lightweight
23
- - Thoroughly tested
24
- - Works in Javascript, Typescript
25
- - Can be used as EcmaScrypt module
26
- - Written in Typescript
20
+ - ๐Ÿชถ Very lightweight
21
+ - ๐Ÿงช Thoroughly tested
22
+ - ๐Ÿšš Shipped as EcmaScrypt module
23
+ - ๐Ÿ“ Written in Typescript
27
24
 
28
25
 
29
26
  ## Support
@@ -43,8 +40,6 @@ $ npm i @dwtechs/antity-pgsql
43
40
  ## Usage
44
41
 
45
42
 
46
- ### ES6 / TypeScript
47
-
48
43
  ```javascript
49
44
 
50
45
  import { SQLEntity } from "@dwtechs/antity-pgsql";
@@ -57,7 +52,9 @@ const entity = new Entity("consumers", [
57
52
  min: 0,
58
53
  max: 120,
59
54
  typeCheck: true,
55
+ filter: true,
60
56
  methods: ["GET", "PUT", "DELETE"],
57
+ operations: ["SELECT", "UPDATE", "DELETE"],
61
58
  required: true,
62
59
  safe: true,
63
60
  sanitize: true,
@@ -73,7 +70,9 @@ const entity = new Entity("consumers", [
73
70
  min: 0,
74
71
  max: 255,
75
72
  typeCheck: true,
73
+ filter: false,
76
74
  methods: ["GET", "POST", "PUT", "DELETE"],
75
+ operations: ["SELECT", "UPDATE", "DELETE"],
77
76
  required: true,
78
77
  safe: true,
79
78
  sanitize: true,
@@ -89,7 +88,9 @@ const entity = new Entity("consumers", [
89
88
  min: 0,
90
89
  max: 255,
91
90
  typeCheck: true,
91
+ filter: false,
92
92
  methods: ["GET", "POST", "PUT", "DELETE"],
93
+ operations: ["SELECT", "UPDATE", "DELETE"],
93
94
  required: true,
94
95
  safe: true,
95
96
  sanitize: true,
@@ -105,7 +106,9 @@ const entity = new Entity("consumers", [
105
106
  min: 0,
106
107
  max: 255,
107
108
  typeCheck: true,
109
+ filter: true,
108
110
  methods: ["GET", "POST", "PUT", "DELETE"],
111
+ operations: ["SELECT", "UPDATE", "DELETE"],
109
112
  required: true,
110
113
  safe: true,
111
114
  sanitize: true,
@@ -117,8 +120,7 @@ const entity = new Entity("consumers", [
117
120
  },
118
121
  ]);
119
122
 
120
- // add a consumer. Used when loggin in from user service
121
- router.gett("/", ..., entity.get);
123
+ router.get("/", ..., entity.get);
122
124
  router.post("/", entity.normalize, entity.validate, ..., entity.add);
123
125
  router.put("/", entity.normalize, entity.validate, ..., entity.update);
124
126
  router.put("/", ..., entity.archive);
@@ -130,7 +132,7 @@ router.put("/", ..., entity.archive);
130
132
 
131
133
  ```javascript
132
134
 
133
- type Operation = "select" | "insert" | "update" | "merge" | "delete";
135
+ type Operation = "SELECT" | "INSERT" | "UPDATE" | "DELETE";
134
136
 
135
137
  type MatchMode =
136
138
  "startsWith" |
@@ -191,9 +193,9 @@ class SQLEntity {
191
193
 
192
194
  function filter(
193
195
  first: number,
194
- rows: number,
196
+ rows: number | null,
195
197
  sortField: string | null,
196
- sortOrder: Sort = "ASC",
198
+ sortOrder: Sort | null,
197
199
  filters: Filters | null,
198
200
  ): { filterClause: string, args: (Filter["value"])[] };
199
201
 
@@ -279,6 +281,35 @@ List of secondary types :
279
281
  | json | object |
280
282
  | object | object |
281
283
 
284
+
285
+ ## Available options for a property
286
+
287
+ Any of these can be passed into the options object for each function.
288
+
289
+ | Name | Type | Description | Default value |
290
+ | :-------------- | :------------------------ | :------------------------------------------------ | :-------------- |
291
+ | key | string | Name of the property |
292
+ | type | Type | Type of the property |
293
+ | min | number \| Date | Minimum value | 0 \| 1900-01-01
294
+ | max | number \| Date | Maximum value | 999999999 \| 2200-12-31
295
+ | required | boolean | Property is required during validation | false
296
+ | safe | boolean | Property is sent in the response | true
297
+ | typeCheck | boolean | Type is checked during validation | false
298
+ | filter | boolean | property is filterable in a SELECT operation | true
299
+ | methods | Method[] | property is validated for the listed methods only | [ "GET", "POST", "PUT", "DELETE" ]
300
+ | operations | Operation[] | SQL DML operations for the property | [ "SELECT", "INSERT", "UPDATE", "DELETE" ]
301
+ | sanitize | boolean | Sanitize the property if true | true
302
+ | normalize | boolean | Normalize the property if true | false
303
+ | validate | boolean | validate the property if true | true
304
+ | sanitizer | ((v:any) => any) \| null | Custom sanitizer function if sanitize is true | null
305
+ | normalizer | ((v:any) => any) \| null | Custop Normalizer function if normalize is true | null
306
+ | validator | ((v:any, min:number, max:number, typeCheck:boolean) => any) \| null | validator function if validate is true | null
307
+
308
+
309
+ * *Min and max parameters are not used for boolean type*
310
+ * *TypeCheck Parameter is not used for boolean, string and array types*
311
+
312
+
282
313
  ## Contributors
283
314
 
284
315
  Antity.js is still in development and we would be glad to get all the help you can provide.
@@ -24,8 +24,9 @@ SOFTWARE.
24
24
  https://github.com/DWTechs/Antity-pgsql.js
25
25
  */
26
26
 
27
- import { Entity, Property } from "@dwtechs/antity";
27
+ import { Entity } from "@dwtechs/antity";
28
28
  import { Type } from "@dwtechs/antity";
29
+ import { Property } from './property';
29
30
  import type { Request, Response, NextFunction } from 'express';
30
31
 
31
32
  export type Operation = "SELECT" | "INSERT" | "UPDATE" | "DELETE";
@@ -24,79 +24,12 @@ SOFTWARE.
24
24
  https://github.com/DWTechs/Antity-pgsql.js
25
25
  */
26
26
 
27
- import { isIn, isArray, isString } from '@dwtechs/checkard';
27
+ import { isArray, isIn, isString } from '@dwtechs/checkard';
28
28
  import { deleteProps, add as add$1, chunk, flatten } from '@dwtechs/sparray';
29
29
  import { log } from '@dwtechs/winstan';
30
30
  import { Entity } from '@dwtechs/antity';
31
31
  import Pool from 'pg-pool';
32
32
 
33
- function type(type) {
34
- const s = "string";
35
- const n = "number";
36
- const d = "date";
37
- switch (type) {
38
- case "integer":
39
- return n;
40
- case "float":
41
- return n;
42
- case "even":
43
- return n;
44
- case "odd":
45
- return n;
46
- case "positive":
47
- return n;
48
- case "negative":
49
- return n;
50
- case "powerOfTwo":
51
- return n;
52
- case "ascii":
53
- return n;
54
- case "jwt":
55
- return s;
56
- case "symbol":
57
- return s;
58
- case "password":
59
- return s;
60
- case "email":
61
- return s;
62
- case "regex":
63
- return s;
64
- case "ipAddress":
65
- return s;
66
- case "slug":
67
- return s;
68
- case "hexadecimal":
69
- return s;
70
- case "date":
71
- return d;
72
- case "timestamp":
73
- return d;
74
- case "function":
75
- return s;
76
- case "htmlElement":
77
- return s;
78
- case "htmlEventAttribute":
79
- return s;
80
- case "node":
81
- return s;
82
- case "json":
83
- return s;
84
- case "object":
85
- return s;
86
- default:
87
- return s;
88
- }
89
- }
90
-
91
- const matchModes = {
92
- string: ["startsWith", "contains", "endsWith", "notContains", "equals", "notEquals", "lt", "lte", "gt", "gte"],
93
- number: ["equals", "notEquals", "lt", "lte", "gt", "gte"],
94
- date: ["is", "isNot", "dateAfter"],
95
- };
96
- function matchMode(type, matchMode) {
97
- return isIn(matchModes[type], matchMode);
98
- }
99
-
100
33
  const { DB_HOST, DB_USER, DB_PWD, DB_NAME, DB_PORT, DB_MAX } = process.env;
101
34
  var pool = new Pool({
102
35
  host: DB_HOST,
@@ -107,10 +40,12 @@ var pool = new Pool({
107
40
  max: DB_MAX ? +DB_MAX : 10,
108
41
  });
109
42
 
43
+ const LOGS_PREFIX = '[Antity-PGSQL] ';
44
+
110
45
  function start(query, args) {
111
46
  const a = JSON.stringify(args);
112
47
  const q = query.replace(/[\n\r]+/g, "").replace(/\s{2,}/g, " ");
113
- log.debug(`Pgsql: { Query : '${q}', Args : '${a}' }`);
48
+ log.debug(`${LOGS_PREFIX}Pgsql: { Query : '${q}', Args : '${a}' }`);
114
49
  return Date.now();
115
50
  }
116
51
  function end(res, time) {
@@ -169,6 +104,111 @@ function quoteIfUppercase(word) {
169
104
  return word;
170
105
  }
171
106
 
107
+ function index(index, matchMode) {
108
+ const i = index.map((i) => `$${i}`);
109
+ switch (matchMode) {
110
+ case "startsWith":
111
+ return `${i}%`;
112
+ case "endsWith":
113
+ return `%${i}`;
114
+ case "contains":
115
+ return `%${i}%`;
116
+ case "notContains":
117
+ return `%${i}%`;
118
+ case "in":
119
+ return `(${i})`;
120
+ default:
121
+ return `${i}`;
122
+ }
123
+ }
124
+
125
+ function comparator(matchMode) {
126
+ switch (matchMode) {
127
+ case "startsWith":
128
+ return "LIKE";
129
+ case "endsWith":
130
+ return "LIKE";
131
+ case "contains":
132
+ return "LIKE";
133
+ case "notContains":
134
+ return "NOT LIKE";
135
+ case "equals":
136
+ return "=";
137
+ case "notEquals":
138
+ return "<>";
139
+ case "in":
140
+ return "IN";
141
+ case "lt":
142
+ return "<";
143
+ case "lte":
144
+ return "<=";
145
+ case "gt":
146
+ return ">";
147
+ case "gte":
148
+ return ">=";
149
+ case "is":
150
+ return "IS";
151
+ case "isNot":
152
+ return "IS NOT";
153
+ case "before":
154
+ return "<";
155
+ case "after":
156
+ return ">";
157
+ default:
158
+ return null;
159
+ }
160
+ }
161
+
162
+ function add(filters) {
163
+ const conditions = [];
164
+ const args = [];
165
+ if (filters) {
166
+ let i = 1;
167
+ for (const k in filters) {
168
+ const { value, matchMode } = filters[k];
169
+ const indexes = isArray(value) ? value.map(() => i++) : [i++];
170
+ const cond = addOne(k, indexes, matchMode);
171
+ if (cond) {
172
+ conditions.push(cond);
173
+ if (isArray(value))
174
+ args.push(...value);
175
+ else
176
+ args.push(value);
177
+ }
178
+ }
179
+ }
180
+ return { conditions, args };
181
+ }
182
+ function addOne(key, indexes, matchMode) {
183
+ const sqlKey = `${quoteIfUppercase(key)}`;
184
+ const comparator$1 = comparator(matchMode);
185
+ const index$1 = index(indexes, matchMode);
186
+ return comparator$1 ? `${sqlKey} ${comparator$1} ${index$1}` : "";
187
+ }
188
+
189
+ function filter(first, rows, sortField, sortOrder, filters) {
190
+ const { conditions, args } = add(filters);
191
+ const filterClause = where(conditions)
192
+ + orderBy(sortField, sortOrder)
193
+ + limit(rows, first);
194
+ return { filterClause, args };
195
+ }
196
+ function where(conditions, operator = "AND") {
197
+ if (!conditions.length)
198
+ return "";
199
+ const c = conditions.join(` ${operator} `).trim();
200
+ return ` WHERE ${c}`;
201
+ }
202
+ function orderBy(sortField, sortOrder) {
203
+ if (!sortField)
204
+ return "";
205
+ const o = sortOrder || "ASC";
206
+ return ` ORDER BY ${quoteIfUppercase(sortField)} ${o}`;
207
+ }
208
+ function limit(rows, first) {
209
+ return rows ? ` LIMIT ${rows} OFFSET ${first}` : "";
210
+ }
211
+
172
212
  class Select {
173
213
  constructor() {
174
214
  this._props = [];
@@ -182,10 +222,15 @@ class Select {
182
222
  get props() {
183
223
  return this._cols;
184
224
  }
185
- query(table, paginate) {
225
+ query(table, paginate, first = 0, rows = null, sortField = null, sortOrder = null, filters = null) {
186
226
  const p = paginate ? this._count : '';
187
227
  const c = this._cols ? this._cols : '*';
188
- return `SELECT ${c}${p} FROM ${quoteIfUppercase(table)}`;
228
+ const baseQuery = `SELECT ${c}${p} FROM ${quoteIfUppercase(table)}`;
229
+ const { filterClause, args } = filter(first, rows, sortField, sortOrder, filters);
230
+ return {
231
+ query: baseQuery + filterClause,
232
+ args: args
233
+ };
189
234
  }
190
235
  execute(query, args, client) {
191
236
  return execute$1(query, args, client)
@@ -315,109 +360,165 @@ function execute(date, query, client) {
315
360
  });
316
361
  }
317
362
 
318
- function index(index, matchMode) {
319
- const i = index.map((i) => `$${i}`);
320
- switch (matchMode) {
321
- case "startsWith":
322
- return `${i}%`;
323
- case "endsWith":
324
- return `%${i}`;
325
- case "contains":
326
- return `%${i}%`;
327
- case "notContains":
328
- return `%${i}%`;
329
- case "in":
330
- return `(${i})`;
363
+ function type(type) {
364
+ const s = "string";
365
+ const n = "number";
366
+ const d = "date";
367
+ switch (type) {
368
+ case "integer":
369
+ return n;
370
+ case "float":
371
+ return n;
372
+ case "even":
373
+ return n;
374
+ case "odd":
375
+ return n;
376
+ case "positive":
377
+ return n;
378
+ case "negative":
379
+ return n;
380
+ case "powerOfTwo":
381
+ return n;
382
+ case "ascii":
383
+ return n;
384
+ case "jwt":
385
+ return s;
386
+ case "symbol":
387
+ return s;
388
+ case "password":
389
+ return s;
390
+ case "email":
391
+ return s;
392
+ case "regex":
393
+ return s;
394
+ case "ipAddress":
395
+ return s;
396
+ case "slug":
397
+ return s;
398
+ case "hexadecimal":
399
+ return s;
400
+ case "date":
401
+ return d;
402
+ case "timestamp":
403
+ return d;
404
+ case "function":
405
+ return s;
406
+ case "htmlElement":
407
+ return s;
408
+ case "htmlEventAttribute":
409
+ return s;
410
+ case "node":
411
+ return s;
412
+ case "json":
413
+ return s;
414
+ case "object":
415
+ return s;
331
416
  default:
332
- return `${i}`;
417
+ return s;
333
418
  }
334
419
  }
335
420
 
336
- function comparator(matchMode) {
337
- switch (matchMode) {
338
- case "startsWith":
339
- return "LIKE";
340
- case "endsWith":
341
- return "LIKE";
342
- case "contains":
343
- return "LIKE";
344
- case "notContains":
345
- return "NOT LIKE";
346
- case "equals":
347
- return "=";
348
- case "notEquals":
349
- return "<>";
350
- case "in":
351
- return "IN";
352
- case "lt":
353
- return "<";
354
- case "lte":
355
- return "<=";
356
- case "gt":
357
- return ">";
358
- case "gte":
359
- return ">=";
360
- case "is":
361
- return "IS";
362
- case "isNot":
363
- return "IS NOT";
364
- case "before":
365
- return "<";
366
- case "after":
367
- return ">";
368
- default:
369
- return null;
370
- }
421
+ const matchModes = {
422
+ string: ["startsWith", "contains", "endsWith", "notContains", "equals", "notEquals", "lt", "lte", "gt", "gte"],
423
+ number: ["equals", "notEquals", "lt", "lte", "gt", "gte"],
424
+ date: ["is", "isNot", "dateAfter"],
425
+ };
426
+ function matchMode(type, matchMode) {
427
+ return isIn(matchModes[type], matchMode);
371
428
  }
372
429
 
373
- function add(filters) {
374
- const conditions = [];
375
- const args = [];
376
- if (filters) {
377
- let i = 1;
378
- for (const k in filters) {
379
- const { value, matchMode } = filters[k];
380
- const indexes = isArray(value) ? value.map(() => i++) : [i++];
381
- const cond = addOne(k, indexes, matchMode);
382
- if (cond) {
383
- conditions.push(cond);
384
- if (isArray(value))
385
- args.push(...value);
386
- else
387
- args.push(value);
430
+ function cleanFilters(filters, properties) {
431
+ for (const k in filters) {
432
+ if (filters.hasOwnProperty(k)) {
433
+ const prop = properties.find(p => p.key === k);
434
+ if (!prop) {
435
+ log.warn(`${LOGS_PREFIX}Filters: skipping unknown property: ${k}`);
436
+ delete filters[k];
437
+ continue;
438
+ }
439
+ if (!prop.filter) {
440
+ log.warn(`${LOGS_PREFIX}Filters: skipping unfilterable property: ${k}`);
441
+ delete filters[k];
442
+ continue;
443
+ }
444
+ const type$1 = type(prop.type);
445
+ const { matchMode: matchMode$1 } = filters[k];
446
+ if (!matchMode$1 || !matchMode(type$1, matchMode$1)) {
447
+ log.warn(`${LOGS_PREFIX}Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
448
+ delete filters[k];
449
+ continue;
388
450
  }
389
451
  }
390
452
  }
391
- return { conditions, args };
392
- }
393
- function addOne(key, indexes, matchMode) {
394
- const sqlKey = `${quoteIfUppercase(key)}`;
395
- const comparator$1 = comparator(matchMode);
396
- const index$1 = index(indexes, matchMode);
397
- return comparator$1 ? `${sqlKey} ${comparator$1} ${index$1}` : "";
453
+ return filters;
398
454
  }
399
455
 
400
- function filter(first, rows, sortField, sortOrder, filters) {
401
- const { conditions, args } = add(filters);
402
- const filterClause = where(conditions)
403
- + orderBy(sortField, sortOrder)
404
- + limit(rows, first);
405
- return { filterClause, args };
456
+ function logSummary(name, table, properties) {
457
+ const summary = generateSummary(name, table, properties);
458
+ log.info(`${LOGS_PREFIX}Entity "${name}" created successfully`);
459
+ log.info(`${LOGS_PREFIX}Entity Summary:\n${summary}`);
406
460
  }
407
- function where(conditions, operator = "AND") {
408
- if (!conditions.length)
409
- return "";
410
- const c = conditions.join(` ${operator} `).trim();
411
- return ` WHERE ${c}`;
461
+ function generateSummary(name, table, properties) {
462
+ const lines = [];
463
+ const propLen = properties.length;
464
+ lines.push(`โ”Œโ”€ SQLEntity: "${name}" (Table: ${table})`);
465
+ lines.push(`โ”œโ”€ Total Properties: ${propLen}`);
466
+ const operationStats = getOperationStatistics(properties);
467
+ lines.push(`โ”œโ”€ Operation Distribution:`);
468
+ Object.entries(operationStats).forEach(([op, count]) => {
469
+ lines.push(`โ”‚ โ””โ”€ ${op}: ${count} properties`);
470
+ });
471
+ lines.push(`โ”œโ”€ Property Details:`);
472
+ properties.forEach((p, index) => {
473
+ const isLast = index === propLen - 1;
474
+ const prefix = isLast ? 'โ””โ”€' : 'โ”œโ”€';
475
+ lines.push(`โ”‚ ${prefix} ${p.key}:`);
476
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Type: ${p.type}`);
477
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Min: ${p.min}`);
478
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Max: ${p.max}`);
479
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Required: ${p.required}`);
480
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Safe: ${p.safe}`);
481
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ TypeCheck: ${p.typeCheck}`);
482
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Filter: ${p.filter}`);
483
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Methods: [${p.methods.join(', ')}]`);
484
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Operations: [${p.operations.join(', ')}]`);
485
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Sanitize: ${p.sanitize}`);
486
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Normalize: ${p.normalize}`);
487
+ lines.push(`โ”‚ ${isLast ? ' ' : 'โ”‚'} โ”œโ”€ Validate: ${p.validate}`);
488
+ });
489
+ const crudMappings = getCrudMappings(properties);
490
+ lines.push(`โ”œโ”€ CRUD Mappings:`);
491
+ Object.entries(crudMappings).forEach(([operation, props]) => {
492
+ lines.push(`โ”‚ โ”œโ”€ ${operation}: [${props.join(', ')}]`);
493
+ });
494
+ lines.push(`โ””โ”€ Entity initialization completed`);
495
+ return lines.join('\n');
412
496
  }
413
- function orderBy(sortField, sortOrder) {
414
- if (!sortField)
415
- return "";
416
- const o = sortOrder || "ASC";
417
- return ` ORDER BY ${quoteIfUppercase(sortField)} ${o}`;
497
+ function getOperationStatistics(properties) {
498
+ const stats = {};
499
+ properties.forEach(prop => {
500
+ prop.operations.forEach(op => {
501
+ stats[op] = (stats[op] || 0) + 1;
502
+ });
503
+ });
504
+ return stats;
418
505
  }
419
- function limit(rows, first) {
420
- return rows ? ` LIMIT ${rows} OFFSET ${first}` : "";
506
+ function getCrudMappings(properties) {
507
+ const mappings = {
508
+ 'SELECT': [],
509
+ 'INSERT': [],
510
+ 'UPDATE': [],
511
+ 'DELETE': []
512
+ };
513
+ properties.forEach(prop => {
514
+ const p = prop;
515
+ prop.operations.forEach(op => {
516
+ if (mappings[op]) {
517
+ mappings[op].push(p.key);
518
+ }
519
+ });
520
+ });
521
+ return mappings;
421
522
  }
422
523
 
423
524
  var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
@@ -436,8 +537,8 @@ class SQLEntity extends Entity {
436
537
  this.ins = new Insert();
437
538
  this.upd = new Update();
438
539
  this.query = {
439
- select: (paginate) => {
440
- return this.sel.query(this.table, paginate);
540
+ select: (paginate, first = 0, rows = null, sortField = null, sortOrder = null, filters = null) => {
541
+ return this.sel.query(this.table, paginate, first, rows, sortField, sortOrder, filters);
441
542
  },
442
543
  update: (rows, consumerId, consumerName) => {
443
544
  return this.upd.query(this.table, rows, consumerId, consumerName);
@@ -460,14 +561,13 @@ class SQLEntity extends Entity {
460
561
  const rows = b.rows || null;
461
562
  const sortField = b.sortField || null;
462
563
  const sortOrder = b.sortOrder === -1 || b.sortOrder === "DESC" ? "DESC" : "ASC";
463
- const filters = this.cleanFilters(b.filters) || null;
564
+ const filters = cleanFilters(b.filters, this.properties || []) || null;
464
565
  const pagination = b.pagination || false;
465
566
  const dbClient = l.dbClient || null;
466
567
  log.debug(`get(first='${first}', rows='${rows}',
467
568
  sortOrder='${sortOrder}', sortField='${sortField}',
468
569
  pagination=${pagination}, filters=${JSON.stringify(filters)}`);
469
- const { filterClause, args } = filter(first, rows, sortField, sortOrder, filters);
470
- const q = this.sel.query(this._table, pagination) + filterClause;
570
+ const { query: q, args } = this.sel.query(this._table, pagination, first, rows, sortField, sortOrder, filters);
471
571
  this.sel.execute(q, args, dbClient)
472
572
  .then((r) => {
473
573
  l.rows = r.rows;
@@ -482,7 +582,7 @@ class SQLEntity extends Entity {
482
582
  const dbClient = l.dbClient || null;
483
583
  const cId = l.consumerId;
484
584
  const cName = l.consumerName;
485
- log.debug(`addMany(rows=${rows.length}, consumerId=${cId})`);
585
+ log.debug(`${LOGS_PREFIX}addMany(rows=${rows.length}, consumerId=${cId})`);
486
586
  const rtn = this.ins.rtn("id");
487
587
  const chunks = chunk(rows);
488
588
  for (const c of chunks) {
@@ -508,7 +608,7 @@ class SQLEntity extends Entity {
508
608
  const dbClient = l.dbClient || null;
509
609
  const cId = l.consumerId;
510
610
  const cName = l.consumerName;
511
- log.debug(`update(rows=${rows.length}, consumerId=${cId})`);
611
+ log.debug(`${LOGS_PREFIX}update(rows=${rows.length}, consumerId=${cId})`);
512
612
  const chunks = chunk(rows);
513
613
  for (const c of chunks) {
514
614
  const { query, args } = this.upd.query(this._table, c, cId, cName);
@@ -527,7 +627,7 @@ class SQLEntity extends Entity {
527
627
  const dbClient = l.dbClient || null;
528
628
  const cId = l.consumerId;
529
629
  const cName = l.consumerName;
530
- log.debug(`archive(rows=${rows.length}, consumerId=${cId})`);
630
+ log.debug(`${LOGS_PREFIX}archive(rows=${rows.length}, consumerId=${cId})`);
531
631
  rows = rows.map((id) => (Object.assign(Object.assign({}, id), { archived: true })));
532
632
  const chunks = chunk(rows);
533
633
  for (const c of chunks) {
@@ -544,58 +644,37 @@ class SQLEntity extends Entity {
544
644
  this.delete = (req, res, next) => {
545
645
  const date = req.body.date;
546
646
  const dbClient = res.locals.dbClient || null;
547
- log.debug(`delete archived`);
647
+ log.debug(`${LOGS_PREFIX}delete archived`);
548
648
  const q = query(this._table);
549
649
  execute(date, q, dbClient)
550
650
  .then(() => next())
551
651
  .catch((err) => next(err));
552
652
  };
553
653
  this._table = name;
654
+ log.info(`${LOGS_PREFIX}Creating SQLEntity: "${name}"`);
554
655
  for (const p of properties) {
555
- this.mapProps(p.methods, p.key);
656
+ this.mapProps(p.operations, p.key);
556
657
  }
658
+ logSummary(name, this._table, properties);
557
659
  }
558
660
  get table() {
559
661
  return this._table;
560
662
  }
561
663
  set table(table) {
562
664
  if (!isString(table, "!0"))
563
- throw new Error('table must be a string of length > 0');
665
+ throw new Error(`${LOGS_PREFIX}table must be a string of length > 0`);
564
666
  this._table = table;
565
667
  }
566
- cleanFilters(filters) {
567
- for (const k in filters) {
568
- if (filters.hasOwnProperty(k)) {
569
- const prop = this.getProp(k);
570
- if (!prop) {
571
- log.warn(`Filters: skipping unknown property: ${k}`);
572
- delete filters[k];
573
- continue;
574
- }
575
- const type$1 = type(prop.type);
576
- const { matchMode: matchMode$1 } = filters[k];
577
- if (!matchMode$1 || !matchMode(type$1, matchMode$1)) {
578
- log.warn(`Filters: skipping invalid match mode: "${matchMode$1}" for type: "${type$1}" at property: "${k}"`);
579
- delete filters[k];
580
- continue;
581
- }
582
- }
583
- }
584
- return filters;
585
- }
586
- mapProps(methods, key) {
587
- for (const m of methods) {
588
- switch (m) {
589
- case "GET":
668
+ mapProps(operations, key) {
669
+ for (const o of operations) {
670
+ switch (o) {
671
+ case "SELECT":
590
672
  this.sel.addProp(key);
591
673
  break;
592
- case "PATCH":
593
- this.upd.addProp(key);
594
- break;
595
- case "PUT":
674
+ case "UPDATE":
596
675
  this.upd.addProp(key);
597
676
  break;
598
- case "POST":
677
+ case "INSERT":
599
678
  this.ins.addProp(key);
600
679
  break;
601
680
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dwtechs/antity-pgsql",
3
- "version": "0.3.2",
4
- "description": "Open source library for easy entity management",
3
+ "version": "0.4.0",
4
+ "description": "Open source library to add PostgreSQL support to @dwtechs/Antity entities.",
5
5
  "keywords": [
6
6
  "entities"
7
7
  ],
@@ -36,10 +36,10 @@
36
36
  "dist/"
37
37
  ],
38
38
  "dependencies": {
39
- "@dwtechs/checkard": "3.2.3",
40
- "@dwtechs/winstan": "0.4.0",
41
- "@dwtechs/antity": "0.10.0",
42
- "@dwtechs/sparray": "0.2.0",
39
+ "@dwtechs/checkard": "3.6.0",
40
+ "@dwtechs/winstan": "0.5.0",
41
+ "@dwtechs/antity": "0.13.0",
42
+ "@dwtechs/sparray": "0.2.1",
43
43
  "pg": "8.13.1"
44
44
  },
45
45
  "devDependencies": {