@naturalcycles/db-lib 8.29.0 → 8.30.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.
@@ -39,6 +39,7 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
39
39
  */
40
40
  query(table?: string): RunnableDBQuery<BM, DBM, TM>;
41
41
  runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
42
+ runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]>;
42
43
  /**
43
44
  * Convenience method that runs multiple queries in parallel and then merges their results together.
44
45
  * Does deduplication by id.
@@ -184,6 +184,12 @@ class CommonDao {
184
184
  const { rows } = await this.runQueryExtended(q, opt);
185
185
  return rows;
186
186
  }
187
+ async runQuerySingleColumn(q, opt) {
188
+ (0, js_lib_1._assert)(q._selectedFieldNames?.length === 1, `runQuerySingleColumn requires exactly 1 column to be selected: ${q.pretty()}`);
189
+ const col = q._selectedFieldNames[0];
190
+ const { rows } = await this.runQueryExtended(q, opt);
191
+ return rows.map(r => r[col]);
192
+ }
187
193
  /**
188
194
  * Convenience method that runs multiple queries in parallel and then merges their results together.
189
195
  * Does deduplication by id.
@@ -65,6 +65,7 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
65
65
  */
66
66
  _selectedFieldNames?: (keyof ROW)[];
67
67
  _groupByFieldNames?: (keyof ROW)[];
68
+ _distinct: boolean;
68
69
  filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this;
69
70
  filterEq(name: keyof ROW, val: any): this;
70
71
  limit(limit: number): this;
@@ -72,6 +73,7 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
72
73
  order(name: keyof ROW, descending?: boolean): this;
73
74
  select(fieldNames: (keyof ROW)[]): this;
74
75
  groupBy(fieldNames: (keyof ROW)[]): this;
76
+ distinct(distinct?: boolean): this;
75
77
  startCursor(startCursor?: string): this;
76
78
  endCursor(endCursor?: string): this;
77
79
  clone(): DBQuery<ROW>;
@@ -88,6 +90,7 @@ export declare class RunnableDBQuery<BM extends Partial<ObjectWithId>, DBM exten
88
90
  */
89
91
  constructor(dao: CommonDao<BM, DBM, TM>, table?: string);
90
92
  runQuery(opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
93
+ runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
91
94
  runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
92
95
  runQueryAsTM(opt?: CommonDaoOptions): Promise<TM[]>;
93
96
  runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<Saved<BM>>>;
@@ -30,6 +30,7 @@ class DBQuery {
30
30
  this._limitValue = 0; // 0 means "no limit"
31
31
  this._offsetValue = 0; // 0 means "no offset"
32
32
  this._orders = [];
33
+ this._distinct = false;
33
34
  }
34
35
  /**
35
36
  * Convenience method.
@@ -71,6 +72,10 @@ class DBQuery {
71
72
  this._groupByFieldNames = fieldNames;
72
73
  return this;
73
74
  }
75
+ distinct(distinct = true) {
76
+ this._distinct = distinct;
77
+ return this;
78
+ }
74
79
  startCursor(startCursor) {
75
80
  this._startCursor = startCursor;
76
81
  return this;
@@ -86,6 +91,8 @@ class DBQuery {
86
91
  _offsetValue: this._offsetValue,
87
92
  _orders: [...this._orders],
88
93
  _selectedFieldNames: this._selectedFieldNames && [...this._selectedFieldNames],
94
+ _groupByFieldNames: this._groupByFieldNames && [...this._groupByFieldNames],
95
+ _distinct: this._distinct,
89
96
  _startCursor: this._startCursor,
90
97
  _endCursor: this._endCursor,
91
98
  });
@@ -99,7 +106,7 @@ class DBQuery {
99
106
  // tokens.push(`"${this.name}"`)
100
107
  // }
101
108
  if (this._selectedFieldNames) {
102
- tokens.push(`select(${this._selectedFieldNames.join(',')})`);
109
+ tokens.push(`select${this._distinct ? ' distinct' : ''}(${this._selectedFieldNames.join(',')})`);
103
110
  }
104
111
  tokens.push(...this._filters.map(f => `${f.name}${f.op}${f.val}`), ...this._orders.map(o => `order by ${o.name}${o.descending ? ' desc' : ''}`));
105
112
  if (this._groupByFieldNames) {
@@ -135,6 +142,9 @@ class RunnableDBQuery extends DBQuery {
135
142
  async runQuery(opt) {
136
143
  return await this.dao.runQuery(this, opt);
137
144
  }
145
+ async runQuerySingleColumn(opt) {
146
+ return await this.dao.runQuerySingleColumn(this, opt);
147
+ }
138
148
  async runQueryAsDBM(opt) {
139
149
  return await this.dao.runQueryAsDBM(this, opt);
140
150
  }
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "engines": {
44
44
  "node": ">=14.15"
45
45
  },
46
- "version": "8.29.0",
46
+ "version": "8.30.0",
47
47
  "description": "Lowest Common Denominator API to supported Databases",
48
48
  "keywords": [
49
49
  "db",
@@ -1,4 +1,5 @@
1
1
  import {
2
+ _assert,
2
3
  _filterNullishValues,
3
4
  _filterUndefinedValues,
4
5
  _passthroughPredicate,
@@ -262,6 +263,18 @@ export class CommonDao<
262
263
  return rows
263
264
  }
264
265
 
266
+ async runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]> {
267
+ _assert(
268
+ q._selectedFieldNames?.length === 1,
269
+ `runQuerySingleColumn requires exactly 1 column to be selected: ${q.pretty()}`,
270
+ )
271
+
272
+ const col = q._selectedFieldNames[0]!
273
+
274
+ const { rows } = await this.runQueryExtended(q, opt)
275
+ return rows.map(r => r[col as any])
276
+ }
277
+
265
278
  /**
266
279
  * Convenience method that runs multiple queries in parallel and then merges their results together.
267
280
  * Does deduplication by id.
@@ -97,6 +97,7 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
97
97
  */
98
98
  _selectedFieldNames?: (keyof ROW)[]
99
99
  _groupByFieldNames?: (keyof ROW)[]
100
+ _distinct = false
100
101
 
101
102
  filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this {
102
103
  this._filters.push({ name, op, val })
@@ -136,6 +137,11 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
136
137
  return this
137
138
  }
138
139
 
140
+ distinct(distinct = true): this {
141
+ this._distinct = distinct
142
+ return this
143
+ }
144
+
139
145
  startCursor(startCursor?: string): this {
140
146
  this._startCursor = startCursor
141
147
  return this
@@ -153,6 +159,8 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
153
159
  _offsetValue: this._offsetValue,
154
160
  _orders: [...this._orders],
155
161
  _selectedFieldNames: this._selectedFieldNames && [...this._selectedFieldNames],
162
+ _groupByFieldNames: this._groupByFieldNames && [...this._groupByFieldNames],
163
+ _distinct: this._distinct,
156
164
  _startCursor: this._startCursor,
157
165
  _endCursor: this._endCursor,
158
166
  })
@@ -170,7 +178,9 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
170
178
  // }
171
179
 
172
180
  if (this._selectedFieldNames) {
173
- tokens.push(`select(${this._selectedFieldNames.join(',')})`)
181
+ tokens.push(
182
+ `select${this._distinct ? ' distinct' : ''}(${this._selectedFieldNames.join(',')})`,
183
+ )
174
184
  }
175
185
 
176
186
  tokens.push(
@@ -221,6 +231,10 @@ export class RunnableDBQuery<
221
231
  return await this.dao.runQuery(this, opt)
222
232
  }
223
233
 
234
+ async runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]> {
235
+ return await this.dao.runQuerySingleColumn<T>(this, opt)
236
+ }
237
+
224
238
  async runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]> {
225
239
  return await this.dao.runQueryAsDBM(this, opt)
226
240
  }