@naturalcycles/db-lib 8.28.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.
|
@@ -13,11 +13,11 @@ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOp
|
|
|
13
13
|
export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId = Saved<BM>, TM = BM> {
|
|
14
14
|
cfg: CommonDaoCfg<BM, DBM, TM>;
|
|
15
15
|
constructor(cfg: CommonDaoCfg<BM, DBM, TM>);
|
|
16
|
-
create(part
|
|
16
|
+
create(part?: Partial<BM>, opt?: CommonDaoOptions): Saved<BM>;
|
|
17
17
|
getById(id: undefined, opt?: CommonDaoOptions): Promise<null>;
|
|
18
18
|
getById(id?: string, opt?: CommonDaoOptions): Promise<Saved<BM> | null>;
|
|
19
|
-
getByIdOrEmpty(id: string, part
|
|
20
|
-
getByIdAsDBMOrEmpty(id: string, part
|
|
19
|
+
getByIdOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<Saved<BM>>;
|
|
20
|
+
getByIdAsDBMOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
|
|
21
21
|
getByIdAsDBM(id: undefined, opt?: CommonDaoOptions): Promise<null>;
|
|
22
22
|
getByIdAsDBM(id?: string, opt?: CommonDaoOptions): Promise<DBM | null>;
|
|
23
23
|
getByIdAsTM(id: undefined, opt?: CommonDaoOptions): Promise<null>;
|
|
@@ -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.
|
|
@@ -44,7 +44,7 @@ class CommonDao {
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
// CREATE
|
|
47
|
-
create(part, opt = {}) {
|
|
47
|
+
create(part = {}, opt = {}) {
|
|
48
48
|
let bm = this.cfg.hooks.beforeCreate(part);
|
|
49
49
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, db_model_1.DBModelType.BM, opt);
|
|
50
50
|
// If no SCHEMA - return as is
|
|
@@ -71,13 +71,13 @@ class CommonDao {
|
|
|
71
71
|
this.logResult(started, op, bm, table);
|
|
72
72
|
return bm || null;
|
|
73
73
|
}
|
|
74
|
-
async getByIdOrEmpty(id, part, opt) {
|
|
74
|
+
async getByIdOrEmpty(id, part = {}, opt) {
|
|
75
75
|
const bm = await this.getById(id, opt);
|
|
76
76
|
if (bm)
|
|
77
77
|
return bm;
|
|
78
78
|
return this.create({ ...part, id }, opt);
|
|
79
79
|
}
|
|
80
|
-
async getByIdAsDBMOrEmpty(id, part, opt) {
|
|
80
|
+
async getByIdAsDBMOrEmpty(id, part = {}, opt) {
|
|
81
81
|
const dbm = await this.getByIdAsDBM(id, opt);
|
|
82
82
|
if (dbm)
|
|
83
83
|
return dbm;
|
|
@@ -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.
|
package/dist/query/dbQuery.d.ts
CHANGED
|
@@ -64,12 +64,16 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
64
64
|
* In undefined - all fields (*) will be returned.
|
|
65
65
|
*/
|
|
66
66
|
_selectedFieldNames?: (keyof ROW)[];
|
|
67
|
+
_groupByFieldNames?: (keyof ROW)[];
|
|
68
|
+
_distinct: boolean;
|
|
67
69
|
filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this;
|
|
68
70
|
filterEq(name: keyof ROW, val: any): this;
|
|
69
71
|
limit(limit: number): this;
|
|
70
72
|
offset(offset: number): this;
|
|
71
73
|
order(name: keyof ROW, descending?: boolean): this;
|
|
72
74
|
select(fieldNames: (keyof ROW)[]): this;
|
|
75
|
+
groupBy(fieldNames: (keyof ROW)[]): this;
|
|
76
|
+
distinct(distinct?: boolean): this;
|
|
73
77
|
startCursor(startCursor?: string): this;
|
|
74
78
|
endCursor(endCursor?: string): this;
|
|
75
79
|
clone(): DBQuery<ROW>;
|
|
@@ -86,6 +90,7 @@ export declare class RunnableDBQuery<BM extends Partial<ObjectWithId>, DBM exten
|
|
|
86
90
|
*/
|
|
87
91
|
constructor(dao: CommonDao<BM, DBM, TM>, table?: string);
|
|
88
92
|
runQuery(opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
|
|
93
|
+
runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
|
|
89
94
|
runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
|
|
90
95
|
runQueryAsTM(opt?: CommonDaoOptions): Promise<TM[]>;
|
|
91
96
|
runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<Saved<BM>>>;
|
package/dist/query/dbQuery.js
CHANGED
|
@@ -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.
|
|
@@ -67,6 +68,14 @@ class DBQuery {
|
|
|
67
68
|
this._selectedFieldNames = fieldNames;
|
|
68
69
|
return this;
|
|
69
70
|
}
|
|
71
|
+
groupBy(fieldNames) {
|
|
72
|
+
this._groupByFieldNames = fieldNames;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
distinct(distinct = true) {
|
|
76
|
+
this._distinct = distinct;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
70
79
|
startCursor(startCursor) {
|
|
71
80
|
this._startCursor = startCursor;
|
|
72
81
|
return this;
|
|
@@ -82,6 +91,8 @@ class DBQuery {
|
|
|
82
91
|
_offsetValue: this._offsetValue,
|
|
83
92
|
_orders: [...this._orders],
|
|
84
93
|
_selectedFieldNames: this._selectedFieldNames && [...this._selectedFieldNames],
|
|
94
|
+
_groupByFieldNames: this._groupByFieldNames && [...this._groupByFieldNames],
|
|
95
|
+
_distinct: this._distinct,
|
|
85
96
|
_startCursor: this._startCursor,
|
|
86
97
|
_endCursor: this._endCursor,
|
|
87
98
|
});
|
|
@@ -95,9 +106,12 @@ class DBQuery {
|
|
|
95
106
|
// tokens.push(`"${this.name}"`)
|
|
96
107
|
// }
|
|
97
108
|
if (this._selectedFieldNames) {
|
|
98
|
-
tokens.push(`select(${this._selectedFieldNames.join(',')})`);
|
|
109
|
+
tokens.push(`select${this._distinct ? ' distinct' : ''}(${this._selectedFieldNames.join(',')})`);
|
|
99
110
|
}
|
|
100
111
|
tokens.push(...this._filters.map(f => `${f.name}${f.op}${f.val}`), ...this._orders.map(o => `order by ${o.name}${o.descending ? ' desc' : ''}`));
|
|
112
|
+
if (this._groupByFieldNames) {
|
|
113
|
+
tokens.push(`groupBy(${this._groupByFieldNames.join(',')})`);
|
|
114
|
+
}
|
|
101
115
|
if (this._offsetValue) {
|
|
102
116
|
tokens.push(`offset ${this._offsetValue}`);
|
|
103
117
|
}
|
|
@@ -128,6 +142,9 @@ class RunnableDBQuery extends DBQuery {
|
|
|
128
142
|
async runQuery(opt) {
|
|
129
143
|
return await this.dao.runQuery(this, opt);
|
|
130
144
|
}
|
|
145
|
+
async runQuerySingleColumn(opt) {
|
|
146
|
+
return await this.dao.runQuerySingleColumn(this, opt);
|
|
147
|
+
}
|
|
131
148
|
async runQueryAsDBM(opt) {
|
|
132
149
|
return await this.dao.runQueryAsDBM(this, opt);
|
|
133
150
|
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
_assert,
|
|
2
3
|
_filterNullishValues,
|
|
3
4
|
_filterUndefinedValues,
|
|
4
5
|
_passthroughPredicate,
|
|
@@ -88,7 +89,7 @@ export class CommonDao<
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
// CREATE
|
|
91
|
-
create(part: Partial<BM
|
|
92
|
+
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
92
93
|
let bm = this.cfg.hooks!.beforeCreate!(part) as BM
|
|
93
94
|
bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
94
95
|
|
|
@@ -124,14 +125,22 @@ export class CommonDao<
|
|
|
124
125
|
return bm || null
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
async getByIdOrEmpty(
|
|
128
|
+
async getByIdOrEmpty(
|
|
129
|
+
id: string,
|
|
130
|
+
part: Partial<BM> = {},
|
|
131
|
+
opt?: CommonDaoOptions,
|
|
132
|
+
): Promise<Saved<BM>> {
|
|
128
133
|
const bm = await this.getById(id, opt)
|
|
129
134
|
if (bm) return bm
|
|
130
135
|
|
|
131
136
|
return this.create({ ...part, id }, opt)
|
|
132
137
|
}
|
|
133
138
|
|
|
134
|
-
async getByIdAsDBMOrEmpty(
|
|
139
|
+
async getByIdAsDBMOrEmpty(
|
|
140
|
+
id: string,
|
|
141
|
+
part: Partial<BM> = {},
|
|
142
|
+
opt?: CommonDaoOptions,
|
|
143
|
+
): Promise<DBM> {
|
|
135
144
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
136
145
|
if (dbm) return dbm
|
|
137
146
|
|
|
@@ -254,6 +263,18 @@ export class CommonDao<
|
|
|
254
263
|
return rows
|
|
255
264
|
}
|
|
256
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
|
+
|
|
257
278
|
/**
|
|
258
279
|
* Convenience method that runs multiple queries in parallel and then merges their results together.
|
|
259
280
|
* Does deduplication by id.
|
package/src/query/dbQuery.ts
CHANGED
|
@@ -96,6 +96,8 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
96
96
|
* In undefined - all fields (*) will be returned.
|
|
97
97
|
*/
|
|
98
98
|
_selectedFieldNames?: (keyof ROW)[]
|
|
99
|
+
_groupByFieldNames?: (keyof ROW)[]
|
|
100
|
+
_distinct = false
|
|
99
101
|
|
|
100
102
|
filter(name: keyof ROW, op: DBQueryFilterOperator, val: any): this {
|
|
101
103
|
this._filters.push({ name, op, val })
|
|
@@ -130,6 +132,16 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
130
132
|
return this
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
groupBy(fieldNames: (keyof ROW)[]): this {
|
|
136
|
+
this._groupByFieldNames = fieldNames
|
|
137
|
+
return this
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
distinct(distinct = true): this {
|
|
141
|
+
this._distinct = distinct
|
|
142
|
+
return this
|
|
143
|
+
}
|
|
144
|
+
|
|
133
145
|
startCursor(startCursor?: string): this {
|
|
134
146
|
this._startCursor = startCursor
|
|
135
147
|
return this
|
|
@@ -147,6 +159,8 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
147
159
|
_offsetValue: this._offsetValue,
|
|
148
160
|
_orders: [...this._orders],
|
|
149
161
|
_selectedFieldNames: this._selectedFieldNames && [...this._selectedFieldNames],
|
|
162
|
+
_groupByFieldNames: this._groupByFieldNames && [...this._groupByFieldNames],
|
|
163
|
+
_distinct: this._distinct,
|
|
150
164
|
_startCursor: this._startCursor,
|
|
151
165
|
_endCursor: this._endCursor,
|
|
152
166
|
})
|
|
@@ -164,7 +178,9 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
164
178
|
// }
|
|
165
179
|
|
|
166
180
|
if (this._selectedFieldNames) {
|
|
167
|
-
tokens.push(
|
|
181
|
+
tokens.push(
|
|
182
|
+
`select${this._distinct ? ' distinct' : ''}(${this._selectedFieldNames.join(',')})`,
|
|
183
|
+
)
|
|
168
184
|
}
|
|
169
185
|
|
|
170
186
|
tokens.push(
|
|
@@ -172,6 +188,10 @@ export class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
|
|
|
172
188
|
...this._orders.map(o => `order by ${o.name}${o.descending ? ' desc' : ''}`),
|
|
173
189
|
)
|
|
174
190
|
|
|
191
|
+
if (this._groupByFieldNames) {
|
|
192
|
+
tokens.push(`groupBy(${this._groupByFieldNames.join(',')})`)
|
|
193
|
+
}
|
|
194
|
+
|
|
175
195
|
if (this._offsetValue) {
|
|
176
196
|
tokens.push(`offset ${this._offsetValue}`)
|
|
177
197
|
}
|
|
@@ -211,6 +231,10 @@ export class RunnableDBQuery<
|
|
|
211
231
|
return await this.dao.runQuery(this, opt)
|
|
212
232
|
}
|
|
213
233
|
|
|
234
|
+
async runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]> {
|
|
235
|
+
return await this.dao.runQuerySingleColumn<T>(this, opt)
|
|
236
|
+
}
|
|
237
|
+
|
|
214
238
|
async runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]> {
|
|
215
239
|
return await this.dao.runQueryAsDBM(this, opt)
|
|
216
240
|
}
|