@naturalcycles/db-lib 9.4.1 → 9.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/dist/commondao/common.dao.d.ts +46 -53
- package/dist/commondao/common.dao.js +2 -58
- package/dist/commondao/common.dao.model.d.ts +6 -8
- package/dist/db.model.d.ts +1 -2
- package/dist/db.model.js +0 -1
- package/dist/query/dbQuery.d.ts +12 -14
- package/dist/query/dbQuery.js +0 -6
- package/dist/testing/daoTest.js +0 -1
- package/dist/testing/test.model.d.ts +5 -5
- package/dist/testing/test.model.js +3 -0
- package/package.json +1 -1
- package/src/commondao/common.dao.model.ts +5 -13
- package/src/commondao/common.dao.ts +86 -193
- package/src/db.model.ts +0 -1
- package/src/pipeline/dbPipelineRestore.ts +1 -2
- package/src/query/dbQuery.ts +10 -21
- package/src/testing/daoTest.ts +0 -2
- package/src/testing/test.model.ts +8 -5
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
_truncate,
|
|
12
12
|
_typeCast,
|
|
13
13
|
_uniqBy,
|
|
14
|
-
AnyObject,
|
|
15
14
|
AppError,
|
|
16
15
|
AsyncMapper,
|
|
17
16
|
BaseDBEntity,
|
|
@@ -21,10 +20,9 @@ import {
|
|
|
21
20
|
JsonSchemaRootObject,
|
|
22
21
|
ObjectWithId,
|
|
23
22
|
pMap,
|
|
24
|
-
Saved,
|
|
25
23
|
SKIP,
|
|
26
24
|
UnixTimestampMillisNumber,
|
|
27
|
-
|
|
25
|
+
Unsaved,
|
|
28
26
|
ZodSchema,
|
|
29
27
|
ZodValidationError,
|
|
30
28
|
zSafeValidate,
|
|
@@ -77,12 +75,8 @@ const isCI = !!process.env['CI']
|
|
|
77
75
|
* BM = Backend model (optimized for API access)
|
|
78
76
|
* TM = Transport model (optimized to be sent over the wire)
|
|
79
77
|
*/
|
|
80
|
-
export class CommonDao<
|
|
81
|
-
BM
|
|
82
|
-
DBM extends BaseDBEntity = BM,
|
|
83
|
-
TM extends AnyObject = BM,
|
|
84
|
-
> {
|
|
85
|
-
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
78
|
+
export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
79
|
+
constructor(public cfg: CommonDaoCfg<BM, DBM>) {
|
|
86
80
|
this.cfg = {
|
|
87
81
|
// Default is to NOT log in AppEngine and in CI,
|
|
88
82
|
// otherwise to log Operations
|
|
@@ -100,11 +94,10 @@ export class CommonDao<
|
|
|
100
94
|
beforeDBMValidate: dbm => dbm,
|
|
101
95
|
beforeDBMToBM: dbm => dbm as any,
|
|
102
96
|
beforeBMToDBM: bm => bm as any,
|
|
103
|
-
beforeBMToTM: bm => bm as any,
|
|
104
97
|
anonymize: dbm => dbm,
|
|
105
98
|
onValidationError: err => err,
|
|
106
99
|
...cfg.hooks,
|
|
107
|
-
} satisfies Partial<CommonDaoHooks<BM, DBM
|
|
100
|
+
} satisfies Partial<CommonDaoHooks<BM, DBM>>,
|
|
108
101
|
}
|
|
109
102
|
|
|
110
103
|
if (this.cfg.generateId) {
|
|
@@ -115,7 +108,7 @@ export class CommonDao<
|
|
|
115
108
|
}
|
|
116
109
|
|
|
117
110
|
// CREATE
|
|
118
|
-
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}):
|
|
111
|
+
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): BM {
|
|
119
112
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
120
113
|
// First assignIdCreatedUpdated, then validate!
|
|
121
114
|
this.assignIdCreatedUpdated(bm, opt)
|
|
@@ -124,14 +117,14 @@ export class CommonDao<
|
|
|
124
117
|
|
|
125
118
|
// GET
|
|
126
119
|
async getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
127
|
-
async getById(id?: string | null, opt?: CommonDaoOptions): Promise<
|
|
128
|
-
async getById(id?: string | null, opt: CommonDaoOptions = {}): Promise<
|
|
120
|
+
async getById(id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>
|
|
121
|
+
async getById(id?: string | null, opt: CommonDaoOptions = {}): Promise<BM | null> {
|
|
129
122
|
if (!id) return null
|
|
130
123
|
const op = `getById(${id})`
|
|
131
124
|
const table = opt.table || this.cfg.table
|
|
132
125
|
const started = this.logStarted(op, table)
|
|
133
126
|
|
|
134
|
-
let dbm = (await (opt.tx || this.cfg.db).getByIds<
|
|
127
|
+
let dbm = (await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id]))[0]
|
|
135
128
|
if (dbm && !opt.raw && this.cfg.hooks!.afterLoad) {
|
|
136
129
|
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
137
130
|
}
|
|
@@ -141,11 +134,7 @@ export class CommonDao<
|
|
|
141
134
|
return bm || null
|
|
142
135
|
}
|
|
143
136
|
|
|
144
|
-
async getByIdOrEmpty(
|
|
145
|
-
id: string,
|
|
146
|
-
part: Partial<BM> = {},
|
|
147
|
-
opt?: CommonDaoOptions,
|
|
148
|
-
): Promise<Saved<BM>> {
|
|
137
|
+
async getByIdOrEmpty(id: string, part: Partial<BM> = {}, opt?: CommonDaoOptions): Promise<BM> {
|
|
149
138
|
const bm = await this.getById(id, opt)
|
|
150
139
|
if (bm) return bm
|
|
151
140
|
|
|
@@ -156,7 +145,7 @@ export class CommonDao<
|
|
|
156
145
|
id: string,
|
|
157
146
|
part: Partial<BM> = {},
|
|
158
147
|
opt?: CommonDaoOptions,
|
|
159
|
-
): Promise<
|
|
148
|
+
): Promise<DBM> {
|
|
160
149
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
161
150
|
if (dbm) return dbm
|
|
162
151
|
|
|
@@ -165,13 +154,13 @@ export class CommonDao<
|
|
|
165
154
|
}
|
|
166
155
|
|
|
167
156
|
async getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
168
|
-
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<
|
|
169
|
-
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<
|
|
157
|
+
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>
|
|
158
|
+
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
|
|
170
159
|
if (!id) return null
|
|
171
160
|
const op = `getByIdAsDBM(${id})`
|
|
172
161
|
const table = opt.table || this.cfg.table
|
|
173
162
|
const started = this.logStarted(op, table)
|
|
174
|
-
let [dbm] = await (opt.tx || this.cfg.db).getByIds<
|
|
163
|
+
let [dbm] = await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id])
|
|
175
164
|
if (dbm && !opt.raw && this.cfg.hooks!.afterLoad) {
|
|
176
165
|
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
177
166
|
}
|
|
@@ -183,34 +172,12 @@ export class CommonDao<
|
|
|
183
172
|
return dbm || null
|
|
184
173
|
}
|
|
185
174
|
|
|
186
|
-
async
|
|
187
|
-
async getByIdAsTM(id?: string | null, opt?: CommonDaoOptions): Promise<TM | null>
|
|
188
|
-
async getByIdAsTM(id?: string | null, opt: CommonDaoOptions = {}): Promise<TM | null> {
|
|
189
|
-
if (!id) return null
|
|
190
|
-
const op = `getByIdAsTM(${id})`
|
|
191
|
-
const table = opt.table || this.cfg.table
|
|
192
|
-
const started = this.logStarted(op, table)
|
|
193
|
-
let [dbm] = await (opt.tx || this.cfg.db).getByIds<Saved<DBM>>(table, [id])
|
|
194
|
-
if (dbm && !opt.raw && this.cfg.hooks!.afterLoad) {
|
|
195
|
-
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (opt.raw) {
|
|
199
|
-
this.logResult(started, op, dbm, table)
|
|
200
|
-
return (dbm as any) || null
|
|
201
|
-
}
|
|
202
|
-
const bm = await this.dbmToBM(dbm, opt)
|
|
203
|
-
const tm = this.bmToTM(bm, opt)
|
|
204
|
-
this.logResult(started, op, tm, table)
|
|
205
|
-
return tm || null
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async getByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
175
|
+
async getByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
209
176
|
if (!ids.length) return []
|
|
210
177
|
const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
211
178
|
const table = opt.table || this.cfg.table
|
|
212
179
|
const started = this.logStarted(op, table)
|
|
213
|
-
let dbms = await (opt.tx || this.cfg.db).getByIds<
|
|
180
|
+
let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
|
|
214
181
|
if (!opt.raw && this.cfg.hooks!.afterLoad && dbms.length) {
|
|
215
182
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
216
183
|
_isTruthy,
|
|
@@ -222,12 +189,12 @@ export class CommonDao<
|
|
|
222
189
|
return bms
|
|
223
190
|
}
|
|
224
191
|
|
|
225
|
-
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<
|
|
192
|
+
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
226
193
|
if (!ids.length) return []
|
|
227
194
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
228
195
|
const table = opt.table || this.cfg.table
|
|
229
196
|
const started = this.logStarted(op, table)
|
|
230
|
-
let dbms = await (opt.tx || this.cfg.db).getByIds<
|
|
197
|
+
let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
|
|
231
198
|
if (!opt.raw && this.cfg.hooks!.afterLoad && dbms.length) {
|
|
232
199
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
233
200
|
_isTruthy,
|
|
@@ -238,7 +205,7 @@ export class CommonDao<
|
|
|
238
205
|
return dbms
|
|
239
206
|
}
|
|
240
207
|
|
|
241
|
-
async requireById(id: string, opt: CommonDaoOptions = {}): Promise<
|
|
208
|
+
async requireById(id: string, opt: CommonDaoOptions = {}): Promise<BM> {
|
|
242
209
|
const r = await this.getById(id, opt)
|
|
243
210
|
if (!r) {
|
|
244
211
|
this.throwRequiredError(id, opt)
|
|
@@ -246,7 +213,7 @@ export class CommonDao<
|
|
|
246
213
|
return r
|
|
247
214
|
}
|
|
248
215
|
|
|
249
|
-
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<
|
|
216
|
+
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<DBM> {
|
|
250
217
|
const r = await this.getByIdAsDBM(id, opt)
|
|
251
218
|
if (!r) {
|
|
252
219
|
this.throwRequiredError(id, opt)
|
|
@@ -295,16 +262,16 @@ export class CommonDao<
|
|
|
295
262
|
}
|
|
296
263
|
}
|
|
297
264
|
|
|
298
|
-
async getBy(by: keyof DBM, value: any, limit = 0, opt?: CommonDaoOptions): Promise<
|
|
265
|
+
async getBy(by: keyof DBM, value: any, limit = 0, opt?: CommonDaoOptions): Promise<BM[]> {
|
|
299
266
|
return await this.query().filterEq(by, value).limit(limit).runQuery(opt)
|
|
300
267
|
}
|
|
301
268
|
|
|
302
|
-
async getOneBy(by: keyof DBM, value: any, opt?: CommonDaoOptions): Promise<
|
|
269
|
+
async getOneBy(by: keyof DBM, value: any, opt?: CommonDaoOptions): Promise<BM | null> {
|
|
303
270
|
const [bm] = await this.query().filterEq(by, value).limit(1).runQuery(opt)
|
|
304
271
|
return bm || null
|
|
305
272
|
}
|
|
306
273
|
|
|
307
|
-
async getAll(opt?: CommonDaoOptions): Promise<
|
|
274
|
+
async getAll(opt?: CommonDaoOptions): Promise<BM[]> {
|
|
308
275
|
return await this.query().runQuery(opt)
|
|
309
276
|
}
|
|
310
277
|
|
|
@@ -312,11 +279,11 @@ export class CommonDao<
|
|
|
312
279
|
/**
|
|
313
280
|
* Pass `table` to override table
|
|
314
281
|
*/
|
|
315
|
-
query(table?: string): RunnableDBQuery<BM, DBM
|
|
316
|
-
return new RunnableDBQuery<BM, DBM
|
|
282
|
+
query(table?: string): RunnableDBQuery<BM, DBM> {
|
|
283
|
+
return new RunnableDBQuery<BM, DBM>(this, table)
|
|
317
284
|
}
|
|
318
285
|
|
|
319
|
-
async runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<
|
|
286
|
+
async runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<BM[]> {
|
|
320
287
|
const { rows } = await this.runQueryExtended(q, opt)
|
|
321
288
|
return rows
|
|
322
289
|
}
|
|
@@ -338,21 +305,18 @@ export class CommonDao<
|
|
|
338
305
|
* Does deduplication by id.
|
|
339
306
|
* Order is not guaranteed, as queries run in parallel.
|
|
340
307
|
*/
|
|
341
|
-
async runUnionQueries(queries: DBQuery<DBM>[], opt?: CommonDaoOptions): Promise<
|
|
308
|
+
async runUnionQueries(queries: DBQuery<DBM>[], opt?: CommonDaoOptions): Promise<BM[]> {
|
|
342
309
|
const results = (
|
|
343
310
|
await pMap(queries, async q => (await this.runQueryExtended(q, opt)).rows)
|
|
344
311
|
).flat()
|
|
345
312
|
return _uniqBy(results, r => r.id)
|
|
346
313
|
}
|
|
347
314
|
|
|
348
|
-
async runQueryExtended(
|
|
349
|
-
q: DBQuery<DBM>,
|
|
350
|
-
opt: CommonDaoOptions = {},
|
|
351
|
-
): Promise<RunQueryResult<Saved<BM>>> {
|
|
315
|
+
async runQueryExtended(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<RunQueryResult<BM>> {
|
|
352
316
|
q.table = opt.table || q.table
|
|
353
317
|
const op = `runQuery(${q.pretty()})`
|
|
354
318
|
const started = this.logStarted(op, q.table)
|
|
355
|
-
let { rows, ...queryResult } = await this.cfg.db.runQuery<
|
|
319
|
+
let { rows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
|
|
356
320
|
const partialQuery = !!q._selectedFieldNames
|
|
357
321
|
if (!opt.raw && this.cfg.hooks!.afterLoad && rows.length) {
|
|
358
322
|
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
@@ -368,7 +332,7 @@ export class CommonDao<
|
|
|
368
332
|
}
|
|
369
333
|
}
|
|
370
334
|
|
|
371
|
-
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<
|
|
335
|
+
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]> {
|
|
372
336
|
const { rows } = await this.runQueryExtendedAsDBM(q, opt)
|
|
373
337
|
return rows
|
|
374
338
|
}
|
|
@@ -376,11 +340,11 @@ export class CommonDao<
|
|
|
376
340
|
async runQueryExtendedAsDBM(
|
|
377
341
|
q: DBQuery<DBM>,
|
|
378
342
|
opt: CommonDaoOptions = {},
|
|
379
|
-
): Promise<RunQueryResult<
|
|
343
|
+
): Promise<RunQueryResult<DBM>> {
|
|
380
344
|
q.table = opt.table || q.table
|
|
381
345
|
const op = `runQueryAsDBM(${q.pretty()})`
|
|
382
346
|
const started = this.logStarted(op, q.table)
|
|
383
|
-
let { rows, ...queryResult } = await this.cfg.db.runQuery<
|
|
347
|
+
let { rows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
|
|
384
348
|
if (!opt.raw && this.cfg.hooks!.afterLoad && rows.length) {
|
|
385
349
|
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
386
350
|
_isTruthy,
|
|
@@ -393,35 +357,6 @@ export class CommonDao<
|
|
|
393
357
|
return { rows: dbms, ...queryResult }
|
|
394
358
|
}
|
|
395
359
|
|
|
396
|
-
async runQueryAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<TM[]> {
|
|
397
|
-
const { rows } = await this.runQueryExtendedAsTM(q, opt)
|
|
398
|
-
return rows
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
async runQueryExtendedAsTM(
|
|
402
|
-
q: DBQuery<DBM>,
|
|
403
|
-
opt: CommonDaoOptions = {},
|
|
404
|
-
): Promise<RunQueryResult<TM>> {
|
|
405
|
-
q.table = opt.table || q.table
|
|
406
|
-
const op = `runQueryAsTM(${q.pretty()})`
|
|
407
|
-
const started = this.logStarted(op, q.table)
|
|
408
|
-
let { rows, ...queryResult } = await this.cfg.db.runQuery<Saved<DBM>>(q, opt)
|
|
409
|
-
if (!opt.raw && this.cfg.hooks!.afterLoad && rows.length) {
|
|
410
|
-
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
411
|
-
_isTruthy,
|
|
412
|
-
)
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const partialQuery = !!q._selectedFieldNames
|
|
416
|
-
const tms =
|
|
417
|
-
partialQuery || opt.raw ? (rows as any[]) : this.bmsToTM(await this.dbmsToBM(rows, opt), opt)
|
|
418
|
-
this.logResult(started, op, tms, q.table)
|
|
419
|
-
return {
|
|
420
|
-
rows: tms,
|
|
421
|
-
...queryResult,
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
360
|
async runQueryCount(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
|
|
426
361
|
q.table = opt.table || q.table
|
|
427
362
|
const op = `runQueryCount(${q.pretty()})`
|
|
@@ -435,8 +370,8 @@ export class CommonDao<
|
|
|
435
370
|
|
|
436
371
|
async streamQueryForEach(
|
|
437
372
|
q: DBQuery<DBM>,
|
|
438
|
-
mapper: AsyncMapper<
|
|
439
|
-
opt: CommonDaoStreamForEachOptions<
|
|
373
|
+
mapper: AsyncMapper<BM, void>,
|
|
374
|
+
opt: CommonDaoStreamForEachOptions<BM> = {},
|
|
440
375
|
): Promise<void> {
|
|
441
376
|
q.table = opt.table || q.table
|
|
442
377
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
@@ -450,7 +385,7 @@ export class CommonDao<
|
|
|
450
385
|
|
|
451
386
|
await _pipeline([
|
|
452
387
|
this.cfg.db.streamQuery<DBM>(q, opt),
|
|
453
|
-
transformMap<
|
|
388
|
+
transformMap<DBM, BM>(
|
|
454
389
|
async dbm => {
|
|
455
390
|
count++
|
|
456
391
|
if (partialQuery || opt.raw) return dbm as any
|
|
@@ -466,7 +401,7 @@ export class CommonDao<
|
|
|
466
401
|
errorMode: opt.errorMode,
|
|
467
402
|
},
|
|
468
403
|
),
|
|
469
|
-
transformMap<
|
|
404
|
+
transformMap<BM, void>(mapper, {
|
|
470
405
|
...opt,
|
|
471
406
|
predicate: _passthroughPredicate, // to be able to logProgress
|
|
472
407
|
}),
|
|
@@ -485,7 +420,7 @@ export class CommonDao<
|
|
|
485
420
|
|
|
486
421
|
async streamQueryAsDBMForEach(
|
|
487
422
|
q: DBQuery<DBM>,
|
|
488
|
-
mapper: AsyncMapper<
|
|
423
|
+
mapper: AsyncMapper<DBM, void>,
|
|
489
424
|
opt: CommonDaoStreamForEachOptions<DBM> = {},
|
|
490
425
|
): Promise<void> {
|
|
491
426
|
q.table = opt.table || q.table
|
|
@@ -516,7 +451,7 @@ export class CommonDao<
|
|
|
516
451
|
errorMode: opt.errorMode,
|
|
517
452
|
},
|
|
518
453
|
),
|
|
519
|
-
transformMap<
|
|
454
|
+
transformMap<DBM, void>(mapper, {
|
|
520
455
|
...opt,
|
|
521
456
|
predicate: _passthroughPredicate, // to be able to logProgress
|
|
522
457
|
}),
|
|
@@ -536,10 +471,7 @@ export class CommonDao<
|
|
|
536
471
|
/**
|
|
537
472
|
* Stream as Readable, to be able to .pipe() it further with support of backpressure.
|
|
538
473
|
*/
|
|
539
|
-
streamQueryAsDBM(
|
|
540
|
-
q: DBQuery<DBM>,
|
|
541
|
-
opt: CommonDaoStreamOptions<DBM> = {},
|
|
542
|
-
): ReadableTyped<Saved<DBM>> {
|
|
474
|
+
streamQueryAsDBM(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<DBM> = {}): ReadableTyped<DBM> {
|
|
543
475
|
q.table = opt.table || q.table
|
|
544
476
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
545
477
|
opt.skipConversion = opt.skipConversion !== false // default true
|
|
@@ -553,7 +485,7 @@ export class CommonDao<
|
|
|
553
485
|
return stream
|
|
554
486
|
.on('error', err => stream.emit('error', err))
|
|
555
487
|
.pipe(
|
|
556
|
-
transformMap<any,
|
|
488
|
+
transformMap<any, DBM>(
|
|
557
489
|
async dbm => {
|
|
558
490
|
if (this.cfg.hooks!.afterLoad) {
|
|
559
491
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -578,10 +510,7 @@ export class CommonDao<
|
|
|
578
510
|
*
|
|
579
511
|
* You can do `.pipe(transformNoOp)` to make it "valid again".
|
|
580
512
|
*/
|
|
581
|
-
streamQuery(
|
|
582
|
-
q: DBQuery<DBM>,
|
|
583
|
-
opt: CommonDaoStreamOptions<Saved<BM>> = {},
|
|
584
|
-
): ReadableTyped<Saved<BM>> {
|
|
513
|
+
streamQuery(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<BM> = {}): ReadableTyped<BM> {
|
|
585
514
|
q.table = opt.table || q.table
|
|
586
515
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
587
516
|
opt.skipConversion = opt.skipConversion !== false // default true
|
|
@@ -595,10 +524,10 @@ export class CommonDao<
|
|
|
595
524
|
stream
|
|
596
525
|
// optimization: 1 validation is enough
|
|
597
526
|
// .pipe(transformMap<any, DBM>(dbm => this.anyToDBM(dbm, opt), safeOpt))
|
|
598
|
-
// .pipe(transformMap<DBM,
|
|
527
|
+
// .pipe(transformMap<DBM, BM>(dbm => this.dbmToBM(dbm, opt), safeOpt))
|
|
599
528
|
.on('error', err => stream.emit('error', err))
|
|
600
529
|
.pipe(
|
|
601
|
-
transformMap<
|
|
530
|
+
transformMap<DBM, BM>(
|
|
602
531
|
async dbm => {
|
|
603
532
|
if (this.cfg.hooks!.afterLoad) {
|
|
604
533
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -632,7 +561,7 @@ export class CommonDao<
|
|
|
632
561
|
.streamQuery<DBM>(q.select(['id']), opt)
|
|
633
562
|
.on('error', err => stream.emit('error', err))
|
|
634
563
|
.pipe(
|
|
635
|
-
transformMapSimple<
|
|
564
|
+
transformMapSimple<DBM, string>(r => r.id, {
|
|
636
565
|
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
637
566
|
}),
|
|
638
567
|
)
|
|
@@ -654,7 +583,7 @@ export class CommonDao<
|
|
|
654
583
|
|
|
655
584
|
await _pipeline([
|
|
656
585
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
657
|
-
transformMapSimple<
|
|
586
|
+
transformMapSimple<DBM, string>(r => {
|
|
658
587
|
count++
|
|
659
588
|
return r.id
|
|
660
589
|
}),
|
|
@@ -701,17 +630,17 @@ export class CommonDao<
|
|
|
701
630
|
/**
|
|
702
631
|
* Mutates with id, created, updated
|
|
703
632
|
*/
|
|
704
|
-
async save(bm:
|
|
633
|
+
async save(bm: Unsaved<BM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<BM> {
|
|
705
634
|
this.requireWriteAccess()
|
|
706
635
|
|
|
707
636
|
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
708
637
|
// Skipping the save operation
|
|
709
|
-
return bm as
|
|
638
|
+
return bm as BM
|
|
710
639
|
}
|
|
711
640
|
|
|
712
641
|
const idWasGenerated = !bm.id && this.cfg.generateId
|
|
713
642
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
714
|
-
_typeCast<
|
|
643
|
+
_typeCast<BM>(bm)
|
|
715
644
|
let dbm = await this.bmToDBM(bm, opt)
|
|
716
645
|
|
|
717
646
|
if (this.cfg.hooks!.beforeSave) {
|
|
@@ -751,11 +680,7 @@ export class CommonDao<
|
|
|
751
680
|
* Similar to `save` with skipIfEquals.
|
|
752
681
|
* Similar to `patch`, but doesn't load the object from the Database.
|
|
753
682
|
*/
|
|
754
|
-
async savePatch(
|
|
755
|
-
bm: BM,
|
|
756
|
-
patch: Partial<BM>,
|
|
757
|
-
opt: CommonDaoSaveBatchOptions<DBM>,
|
|
758
|
-
): Promise<Saved<BM>> {
|
|
683
|
+
async savePatch(bm: BM, patch: Partial<BM>, opt: CommonDaoSaveBatchOptions<DBM>): Promise<BM> {
|
|
759
684
|
const patched: BM = {
|
|
760
685
|
...bm,
|
|
761
686
|
...patch,
|
|
@@ -763,7 +688,7 @@ export class CommonDao<
|
|
|
763
688
|
|
|
764
689
|
if (_deepJsonEquals(bm, patched)) {
|
|
765
690
|
// Skipping the save operation, as data is the same
|
|
766
|
-
return bm
|
|
691
|
+
return bm
|
|
767
692
|
}
|
|
768
693
|
|
|
769
694
|
// Actually apply the patch by mutating the original object (by design)
|
|
@@ -785,7 +710,7 @@ export class CommonDao<
|
|
|
785
710
|
id: string,
|
|
786
711
|
patch: Partial<BM>,
|
|
787
712
|
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
788
|
-
): Promise<
|
|
713
|
+
): Promise<BM> {
|
|
789
714
|
if (this.cfg.patchInTransaction && !opt.tx) {
|
|
790
715
|
// patchInTransaction means that we should run this op in Transaction
|
|
791
716
|
// But if opt.tx is passed - means that we are already in a Transaction,
|
|
@@ -793,7 +718,7 @@ export class CommonDao<
|
|
|
793
718
|
return await this.patchByIdInTransaction(id, patch, opt)
|
|
794
719
|
}
|
|
795
720
|
|
|
796
|
-
let patched:
|
|
721
|
+
let patched: BM
|
|
797
722
|
const loaded = await this.getById(id, opt)
|
|
798
723
|
|
|
799
724
|
if (loaded) {
|
|
@@ -817,7 +742,7 @@ export class CommonDao<
|
|
|
817
742
|
id: string,
|
|
818
743
|
patch: Partial<BM>,
|
|
819
744
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
820
|
-
): Promise<
|
|
745
|
+
): Promise<BM> {
|
|
821
746
|
return await this.runInTransaction(async daoTx => {
|
|
822
747
|
return await this.patchById(id, patch, { ...opt, tx: daoTx.tx })
|
|
823
748
|
})
|
|
@@ -829,11 +754,7 @@ export class CommonDao<
|
|
|
829
754
|
* Otherwise, similar behavior as patchById.
|
|
830
755
|
* It still loads the row from the DB.
|
|
831
756
|
*/
|
|
832
|
-
async patch(
|
|
833
|
-
bm: BM,
|
|
834
|
-
patch: Partial<BM>,
|
|
835
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
836
|
-
): Promise<Saved<BM>> {
|
|
757
|
+
async patch(bm: BM, patch: Partial<BM>, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<BM> {
|
|
837
758
|
if (this.cfg.patchInTransaction && !opt.tx) {
|
|
838
759
|
// patchInTransaction means that we should run this op in Transaction
|
|
839
760
|
// But if opt.tx is passed - means that we are already in a Transaction,
|
|
@@ -848,7 +769,7 @@ export class CommonDao<
|
|
|
848
769
|
|
|
849
770
|
if (_deepJsonEquals(loaded, bm)) {
|
|
850
771
|
// Skipping the save operation, as data is the same
|
|
851
|
-
return bm
|
|
772
|
+
return bm
|
|
852
773
|
}
|
|
853
774
|
|
|
854
775
|
// Make `bm` exactly the same as `loaded`
|
|
@@ -867,22 +788,19 @@ export class CommonDao<
|
|
|
867
788
|
bm: BM,
|
|
868
789
|
patch: Partial<BM>,
|
|
869
790
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
870
|
-
): Promise<
|
|
791
|
+
): Promise<BM> {
|
|
871
792
|
return await this.runInTransaction(async daoTx => {
|
|
872
793
|
return await this.patch(bm, patch, { ...opt, tx: daoTx.tx })
|
|
873
794
|
})
|
|
874
795
|
}
|
|
875
796
|
|
|
876
|
-
async saveAsDBM(
|
|
877
|
-
dbm: UnsavedId<DBM>,
|
|
878
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
879
|
-
): Promise<Saved<DBM>> {
|
|
797
|
+
async saveAsDBM(dbm: Unsaved<DBM>, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM> {
|
|
880
798
|
this.requireWriteAccess()
|
|
881
799
|
const table = opt.table || this.cfg.table
|
|
882
800
|
|
|
883
801
|
// assigning id in case it misses the id
|
|
884
802
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
885
|
-
let row = dbm as
|
|
803
|
+
let row = dbm as DBM
|
|
886
804
|
if (!opt.raw) {
|
|
887
805
|
const idWasGenerated = !dbm.id && this.cfg.generateId
|
|
888
806
|
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
@@ -899,7 +817,7 @@ export class CommonDao<
|
|
|
899
817
|
|
|
900
818
|
if (this.cfg.hooks!.beforeSave) {
|
|
901
819
|
row = (await this.cfg.hooks!.beforeSave(row))!
|
|
902
|
-
if (row === null) return dbm as
|
|
820
|
+
if (row === null) return dbm as DBM
|
|
903
821
|
}
|
|
904
822
|
|
|
905
823
|
await (opt.tx || this.cfg.db).saveBatch(table, [row], {
|
|
@@ -916,10 +834,7 @@ export class CommonDao<
|
|
|
916
834
|
return row
|
|
917
835
|
}
|
|
918
836
|
|
|
919
|
-
async saveBatch(
|
|
920
|
-
bms: UnsavedId<BM>[],
|
|
921
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
922
|
-
): Promise<Saved<BM>[]> {
|
|
837
|
+
async saveBatch(bms: Unsaved<BM>[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<BM[]> {
|
|
923
838
|
if (!bms.length) return []
|
|
924
839
|
this.requireWriteAccess()
|
|
925
840
|
const table = opt.table || this.cfg.table
|
|
@@ -960,20 +875,20 @@ export class CommonDao<
|
|
|
960
875
|
|
|
961
876
|
this.logSaveResult(started, op, table)
|
|
962
877
|
|
|
963
|
-
return bms as
|
|
878
|
+
return bms as BM[]
|
|
964
879
|
}
|
|
965
880
|
|
|
966
881
|
async saveBatchAsDBM(
|
|
967
|
-
dbms:
|
|
882
|
+
dbms: Unsaved<DBM>[],
|
|
968
883
|
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
969
|
-
): Promise<
|
|
884
|
+
): Promise<DBM[]> {
|
|
970
885
|
if (!dbms.length) return []
|
|
971
886
|
this.requireWriteAccess()
|
|
972
887
|
const table = opt.table || this.cfg.table
|
|
973
|
-
let rows = dbms as
|
|
888
|
+
let rows = dbms as DBM[]
|
|
974
889
|
if (!opt.raw) {
|
|
975
890
|
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
976
|
-
rows = this.anyToDBMs(dbms as
|
|
891
|
+
rows = this.anyToDBMs(dbms as DBM[], opt)
|
|
977
892
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
978
893
|
}
|
|
979
894
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
@@ -1034,7 +949,7 @@ export class CommonDao<
|
|
|
1034
949
|
const { batchSize = 500, batchConcurrency = 16, errorMode } = opt
|
|
1035
950
|
|
|
1036
951
|
return [
|
|
1037
|
-
transformMap<BM,
|
|
952
|
+
transformMap<BM, DBM>(
|
|
1038
953
|
async bm => {
|
|
1039
954
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
1040
955
|
|
|
@@ -1191,8 +1106,8 @@ export class CommonDao<
|
|
|
1191
1106
|
// CONVERSIONS
|
|
1192
1107
|
|
|
1193
1108
|
async dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1194
|
-
async dbmToBM(_dbm?: DBM, opt?: CommonDaoOptions): Promise<
|
|
1195
|
-
async dbmToBM(_dbm?: DBM, opt: CommonDaoOptions = {}): Promise<
|
|
1109
|
+
async dbmToBM(_dbm?: DBM, opt?: CommonDaoOptions): Promise<BM>
|
|
1110
|
+
async dbmToBM(_dbm?: DBM, opt: CommonDaoOptions = {}): Promise<BM | undefined> {
|
|
1196
1111
|
if (!_dbm) return
|
|
1197
1112
|
|
|
1198
1113
|
// optimization: no need to run full joi DBM validation, cause BM validation will be run
|
|
@@ -1211,7 +1126,7 @@ export class CommonDao<
|
|
|
1211
1126
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1212
1127
|
}
|
|
1213
1128
|
|
|
1214
|
-
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<
|
|
1129
|
+
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
1215
1130
|
return await pMap(dbms, async dbm => await this.dbmToBM(dbm, opt))
|
|
1216
1131
|
}
|
|
1217
1132
|
|
|
@@ -1220,8 +1135,8 @@ export class CommonDao<
|
|
|
1220
1135
|
* Returns DBM (new reference).
|
|
1221
1136
|
*/
|
|
1222
1137
|
async bmToDBM(bm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1223
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<
|
|
1224
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<
|
|
1138
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM>
|
|
1139
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM | undefined> {
|
|
1225
1140
|
if (bm === undefined) return
|
|
1226
1141
|
|
|
1227
1142
|
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
@@ -1240,14 +1155,14 @@ export class CommonDao<
|
|
|
1240
1155
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1241
1156
|
}
|
|
1242
1157
|
|
|
1243
|
-
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<
|
|
1158
|
+
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
1244
1159
|
// try/catch?
|
|
1245
1160
|
return await pMap(bms, async bm => await this.bmToDBM(bm, opt))
|
|
1246
1161
|
}
|
|
1247
1162
|
|
|
1248
1163
|
anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined
|
|
1249
|
-
anyToDBM(dbm?: any, opt?: CommonDaoOptions):
|
|
1250
|
-
anyToDBM(dbm?: DBM, opt: CommonDaoOptions = {}):
|
|
1164
|
+
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM
|
|
1165
|
+
anyToDBM(dbm?: DBM, opt: CommonDaoOptions = {}): DBM | undefined {
|
|
1251
1166
|
if (!dbm) return
|
|
1252
1167
|
|
|
1253
1168
|
// this shouldn't be happening on load! but should on save!
|
|
@@ -1263,32 +1178,10 @@ export class CommonDao<
|
|
|
1263
1178
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1264
1179
|
}
|
|
1265
1180
|
|
|
1266
|
-
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}):
|
|
1181
|
+
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}): DBM[] {
|
|
1267
1182
|
return entities.map(entity => this.anyToDBM(entity, opt))
|
|
1268
1183
|
}
|
|
1269
1184
|
|
|
1270
|
-
bmToTM(bm: undefined, opt?: CommonDaoOptions): TM | undefined
|
|
1271
|
-
bmToTM(bm?: BM, opt?: CommonDaoOptions): TM
|
|
1272
|
-
bmToTM(bm?: BM, opt?: CommonDaoOptions): TM | undefined {
|
|
1273
|
-
if (bm === undefined) return
|
|
1274
|
-
|
|
1275
|
-
// optimization: 1 validation is enough
|
|
1276
|
-
// Validate/convert BM
|
|
1277
|
-
// bm gets assigned to the new reference
|
|
1278
|
-
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1279
|
-
|
|
1280
|
-
// BM > TM
|
|
1281
|
-
const tm = this.cfg.hooks!.beforeBMToTM!(bm)
|
|
1282
|
-
|
|
1283
|
-
// Validate/convert DBM
|
|
1284
|
-
return this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
bmsToTM(bms: BM[], opt: CommonDaoOptions = {}): TM[] {
|
|
1288
|
-
// try/catch?
|
|
1289
|
-
return bms.map(bm => this.bmToTM(bm, opt))
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
1185
|
/**
|
|
1293
1186
|
* Returns *converted value*.
|
|
1294
1187
|
* Validates (unless `skipValidation=true` passed).
|
|
@@ -1298,7 +1191,7 @@ export class CommonDao<
|
|
|
1298
1191
|
validateAndConvert<T>(
|
|
1299
1192
|
obj: Partial<T>,
|
|
1300
1193
|
schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined,
|
|
1301
|
-
modelType
|
|
1194
|
+
modelType?: DBModelType,
|
|
1302
1195
|
opt: CommonDaoOptions = {},
|
|
1303
1196
|
): any {
|
|
1304
1197
|
// `raw` option completely bypasses any processing
|
|
@@ -1488,18 +1381,18 @@ export class CommonDaoTransaction {
|
|
|
1488
1381
|
}
|
|
1489
1382
|
|
|
1490
1383
|
async getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1491
|
-
dao: CommonDao<BM, DBM
|
|
1384
|
+
dao: CommonDao<BM, DBM>,
|
|
1492
1385
|
id?: string | null,
|
|
1493
1386
|
opt?: CommonDaoOptions,
|
|
1494
|
-
): Promise<
|
|
1387
|
+
): Promise<BM | null> {
|
|
1495
1388
|
return await dao.getById(id, { ...opt, tx: this.tx })
|
|
1496
1389
|
}
|
|
1497
1390
|
|
|
1498
1391
|
async getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1499
|
-
dao: CommonDao<BM, DBM
|
|
1392
|
+
dao: CommonDao<BM, DBM>,
|
|
1500
1393
|
ids: string[],
|
|
1501
1394
|
opt?: CommonDaoOptions,
|
|
1502
|
-
): Promise<
|
|
1395
|
+
): Promise<BM[]> {
|
|
1503
1396
|
return await dao.getByIds(ids, { ...opt, tx: this.tx })
|
|
1504
1397
|
}
|
|
1505
1398
|
|
|
@@ -1508,7 +1401,7 @@ export class CommonDaoTransaction {
|
|
|
1508
1401
|
// dao: CommonDao<BM, DBM, any>,
|
|
1509
1402
|
// q: DBQuery<DBM>,
|
|
1510
1403
|
// opt?: CommonDaoOptions,
|
|
1511
|
-
// ): Promise<
|
|
1404
|
+
// ): Promise<BM[]> {
|
|
1512
1405
|
// try {
|
|
1513
1406
|
// return await dao.runQuery(q, { ...opt, tx: this.tx })
|
|
1514
1407
|
// } catch (err) {
|
|
@@ -1518,18 +1411,18 @@ export class CommonDaoTransaction {
|
|
|
1518
1411
|
// }
|
|
1519
1412
|
|
|
1520
1413
|
async save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1521
|
-
dao: CommonDao<BM, DBM
|
|
1522
|
-
bm:
|
|
1414
|
+
dao: CommonDao<BM, DBM>,
|
|
1415
|
+
bm: Unsaved<BM>,
|
|
1523
1416
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1524
|
-
): Promise<
|
|
1417
|
+
): Promise<BM> {
|
|
1525
1418
|
return (await this.saveBatch(dao, [bm], opt))[0]!
|
|
1526
1419
|
}
|
|
1527
1420
|
|
|
1528
1421
|
async saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1529
|
-
dao: CommonDao<BM, DBM
|
|
1530
|
-
bms:
|
|
1422
|
+
dao: CommonDao<BM, DBM>,
|
|
1423
|
+
bms: Unsaved<BM>[],
|
|
1531
1424
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1532
|
-
): Promise<
|
|
1425
|
+
): Promise<BM[]> {
|
|
1533
1426
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx })
|
|
1534
1427
|
}
|
|
1535
1428
|
|