pg-promise 12.3.0 → 12.5.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
@@ -392,7 +392,7 @@ When a variable name ends with `:value`, or shorter syntax `#`, it is escaped as
392
392
  the trailing quotes are not added.
393
393
 
394
394
  Open values are primarily to be able to compose complete `LIKE`/`ILIKE` dynamic statements in external SQL files,
395
- without having to generate them in the code.
395
+ without having to generate them in the code. They should not be used otherwise because they are not safe from SQL injection.
396
396
 
397
397
  i.e. you can either generate a filter like this in your code:
398
398
 
@@ -56,6 +56,12 @@ const npm = {
56
56
  *
57
57
  * By default, only the object's own properties are enumerated for column names.
58
58
  *
59
+ * @param {'error' | 'skip' | 'replace'} [options.duplicate = 'error']
60
+ * Strategy for processing duplicate columns:
61
+ * - `'error'` - throws {@link external:Error Error} = `Duplicate column name "name".` (Default)
62
+ * - `'skip'` - skips repeated columns (only the first will be used)
63
+ * - `'replace'` - replaces repeated columns (the last one will be used)
64
+ *
59
65
  * @returns {helpers.ColumnSet}
60
66
  *
61
67
  * @see
@@ -166,17 +172,17 @@ const npm = {
166
172
  */
167
173
  class ColumnSet extends InnerState {
168
174
 
169
- constructor(columns, opt) {
175
+ constructor(columns, options) {
170
176
  super();
171
177
 
172
178
  if (!columns || typeof columns !== 'object') {
173
179
  throw new TypeError('Invalid parameter \'columns\' specified.');
174
180
  }
175
181
 
176
- opt = assert(opt, ['table', 'inherit']);
182
+ options = assert(options, ['table', 'inherit', 'duplicate']);
177
183
 
178
- if (!npm.utils.isNull(opt.table)) {
179
- this.table = (opt.table instanceof TableName) ? opt.table : new TableName(opt.table);
184
+ if (!npm.utils.isNull(options.table)) {
185
+ this.table = (options.table instanceof TableName) ? options.table : new TableName(options.table);
180
186
  }
181
187
 
182
188
  /**
@@ -190,6 +196,7 @@ class ColumnSet extends InnerState {
190
196
  * - **secondary:** to be automatically written into the console (for logging purposes).
191
197
  */
192
198
 
199
+ this.columns = [];
193
200
 
194
201
  /**
195
202
  * @name helpers.ColumnSet#columns
@@ -199,22 +206,28 @@ class ColumnSet extends InnerState {
199
206
  * Array of {@link helpers.Column Column} objects.
200
207
  */
201
208
  if (Array.isArray(columns)) {
202
- const colNames = {};
203
- this.columns = columns.map(c => {
209
+ const duplicate = options.duplicate || 'error';
210
+ columns.forEach(c => {
204
211
  const col = (c instanceof Column) ? c : new Column(c);
205
- if (col.name in colNames) {
206
- throw new Error(`Duplicate column name "${col.name}".`);
212
+ const idx = this.columns.findIndex(a => a.name === col.name);
213
+ if (idx === -1) {
214
+ this.columns.push(col);
215
+ } else {
216
+ if (duplicate === 'replace') {
217
+ this.columns[idx] = col;
218
+ return;
219
+ }
220
+ if (duplicate !== 'skip') {
221
+ throw new Error(`Duplicate column name "${col.name}".`);
222
+ }
207
223
  }
208
- colNames[col.name] = true;
209
- return col;
210
224
  });
211
225
  } else {
212
226
  if (columns instanceof Column) {
213
227
  this.columns = [columns];
214
228
  } else {
215
- this.columns = [];
216
229
  for (const name in columns) {
217
- if (opt.inherit || Object.prototype.hasOwnProperty.call(columns, name)) {
230
+ if (options.inherit || Object.prototype.hasOwnProperty.call(columns, name)) {
218
231
  this.columns.push(new Column(name));
219
232
  }
220
233
  }
@@ -415,13 +428,18 @@ ColumnSet.prototype.assignColumns = function (options) {
415
428
  * @description
416
429
  * Creates a new {@link helpers.ColumnSet ColumnSet}, by joining the two sets of columns.
417
430
  *
418
- * If the two sets contain a column with the same `name` (case-sensitive), an error is thrown.
431
+ * If the two sets contain a column with the same `name` (case-sensitive), an error is thrown (unless `opts.skip` is set to `true`).
419
432
  *
420
433
  * @param {helpers.Column|helpers.ColumnSet|array} columns
421
434
  * Columns to be appended, of the same type as parameter `columns` during {@link helpers.ColumnSet ColumnSet} construction, except:
422
435
  * - it can also be of type {@link helpers.ColumnSet ColumnSet}
423
436
  * - it cannot be a simple object (properties enumeration is not supported here)
424
437
  *
438
+ * @param {object} [options]
439
+ *
440
+ * @param {boolean} [options.skip = false]
441
+ * When set to `true`, it skips duplicate columns (by default, it throws an error).
442
+ *
425
443
  * @returns {helpers.ColumnSet}
426
444
  * New {@link helpers.ColumnSet ColumnSet} object with the extended/concatenated list of columns.
427
445
  *
@@ -465,13 +483,12 @@ ColumnSet.prototype.assignColumns = function (options) {
465
483
  * // ]
466
484
  * // }
467
485
  */
468
- ColumnSet.prototype.extend = function (columns) {
469
- let cs = columns;
470
- if (!(cs instanceof ColumnSet)) {
471
- cs = new ColumnSet(columns);
472
- }
473
- // Any duplicate column will throw Error = 'Duplicate column name "name".',
474
- return new ColumnSet(this.columns.concat(cs.columns), {table: this.table});
486
+ ColumnSet.prototype.extend = function (columns, options) {
487
+ options = assert(options, ['skip']);
488
+ const duplicate = options.skip ? 'skip' : 'error';
489
+ const cs = columns instanceof ColumnSet ? columns : new ColumnSet(columns, {duplicate});
490
+ const joinedCols = this.columns.concat(...cs.columns);
491
+ return new ColumnSet(joinedCols, {table: this.table, duplicate});
475
492
  };
476
493
 
477
494
  /**
@@ -536,23 +553,10 @@ ColumnSet.prototype.extend = function (columns) {
536
553
  *
537
554
  */
538
555
  ColumnSet.prototype.merge = function (columns) {
539
- let cs = columns;
540
- if (!(cs instanceof ColumnSet)) {
541
- cs = new ColumnSet(columns);
542
- }
543
- const colNames = {}, cols = [];
544
- this.columns.forEach((c, idx) => {
545
- cols.push(c);
546
- colNames[c.name] = idx;
547
- });
548
- cs.columns.forEach(c => {
549
- if (c.name in colNames) {
550
- cols[colNames[c.name]] = c;
551
- } else {
552
- cols.push(c);
553
- }
554
- });
555
- return new ColumnSet(cols, {table: this.table});
556
+ const duplicate = 'replace';
557
+ const cs = columns instanceof ColumnSet ? columns : new ColumnSet(columns, {duplicate});
558
+ const joinedCols = this.columns.concat(...cs.columns);
559
+ return new ColumnSet(joinedCols, {table: this.table, duplicate});
556
560
  };
557
561
 
558
562
  /**
@@ -364,7 +364,7 @@ npm.utils.addInspection(Column, function () {
364
364
  * Used by methods {@link helpers.update update} and {@link helpers.sets sets}, ignored by methods {@link helpers.insert insert} and
365
365
  * {@link helpers.values values}. It indicates that the column is reserved for a `WHERE` condition, not to be set or updated.
366
366
  *
367
- * It can be set from a string initialization, by adding `?` in front of the name.
367
+ * It can be set from a string initialization by adding `?` in front of the name.
368
368
  *
369
369
  * @property {*} [def]
370
370
  * Default value for the property, to be used only when the source object doesn't have the property.
@@ -379,7 +379,7 @@ npm.utils.addInspection(Column, function () {
379
379
  * Used by methods {@link helpers.update update} (for a single object) and {@link helpers.sets sets}, ignored by methods
380
380
  * {@link helpers.insert insert} and {@link helpers.values values}.
381
381
  *
382
- * It is also ignored when conditional flag `cnd` is set.
382
+ * It is also ignored when the conditional flag `cnd` is set.
383
383
  *
384
384
  */
385
385
 
package/lib/main.js CHANGED
@@ -34,7 +34,7 @@ let originalClientConnect;
34
34
  * @module pg-promise
35
35
  *
36
36
  * @description
37
- * ## pg-promise v12.0
37
+ * ## pg-promise v12.5
38
38
  * All documentation here is for the latest official release only.
39
39
  *
40
40
  * ### Initialization Options
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pg-promise",
3
- "version": "12.3.0",
3
+ "version": "12.5.0",
4
4
  "description": "PostgreSQL interface for Node.js",
5
5
  "main": "lib/index.js",
6
6
  "typings": "typescript/pg-promise.d.ts",
7
7
  "scripts": {
8
8
  "spelling": "cspell --config=.cspell.json \"**/*.{md,ts,js}\" --no-progress",
9
- "coverage": "istanbul cover ./node_modules/jasmine-node/bin/jasmine-node --captureExceptions test",
9
+ "coverage": "nyc --reporter=html --reporter=text ./node_modules/jasmine-node/bin/jasmine-node --captureExceptions test",
10
10
  "doc": "jsdoc -c ./jsdoc/jsdoc.js ./jsdoc/README.md -t ./jsdoc/templates/custom",
11
11
  "lint": "eslint ./lib ./test/*.js ./test/db",
12
12
  "lint:fix": "npm run lint -- --fix",
@@ -42,24 +42,24 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "assert-options": "0.8.3",
45
- "pg": "8.16.3",
45
+ "pg": "8.18.0",
46
46
  "pg-minify": "1.8.0",
47
47
  "spex": "4.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "pg-query-stream": "4.10.3"
50
+ "pg-query-stream": "4.12.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@eslint/js": "9.39.1",
54
- "@types/node": "24.10.0",
53
+ "@eslint/js": "9.39.2",
54
+ "@types/node": "25.1.0",
55
55
  "coveralls": "3.1.1",
56
- "cspell": "9.3.0",
57
- "eslint": "9.39.1",
58
- "globals": "16.5.0",
59
- "istanbul": "0.4.5",
56
+ "cspell": "9.6.2",
57
+ "eslint": "9.39.2",
58
+ "globals": "17.2.0",
60
59
  "jasmine-node": "3.0.0",
61
60
  "jsdoc": "4.0.5",
62
61
  "JSONStream": "1.3.5",
62
+ "nyc": "17.1.0",
63
63
  "typescript": "5.9.3"
64
64
  }
65
65
  }
@@ -130,6 +130,7 @@ declare namespace pgPromise {
130
130
  interface IColumnSetOptions {
131
131
  table?: string | ITable | TableName
132
132
  inherit?: boolean
133
+ duplicate?: 'error' | 'skip' | 'replace'
133
134
  }
134
135
 
135
136
  interface ITable {
@@ -206,9 +207,15 @@ declare namespace pgPromise {
206
207
  skip?: string | string[] | ((c: Column<T>) => boolean)
207
208
  }): string
208
209
 
209
- extend<S>(columns: Column<T> | ColumnSet<T> | Array<string | IColumnConfig<T> | Column<T>>): ColumnSet<S>
210
+ extend<K extends string>(columns: K[], opts?: {
211
+ skip?: boolean
212
+ }): ColumnSet<T & Record<K, unknown>>
213
+ extend<S>(columns: Column<S> | ColumnSet<S> | Array<IColumnConfig<S> | Column<S>>, opts?: {
214
+ skip?: boolean
215
+ }): ColumnSet<T & S>
210
216
 
211
- merge<S>(columns: Column<T> | ColumnSet<T> | Array<string | IColumnConfig<T> | Column<T>>): ColumnSet<S>
217
+ merge<K extends string>(columns: K[]): ColumnSet<T & Record<K, unknown>>
218
+ merge<S>(columns: Column<S> | ColumnSet<S> | Array<IColumnConfig<S> | Column<S>>): ColumnSet<T & S>
212
219
 
213
220
  prepare(obj: object): object
214
221