@naturalcycles/db-lib 9.2.0 → 9.3.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/adapter/cachedb/cache.db.d.ts +11 -12
- package/dist/adapter/cachedb/cache.db.model.d.ts +2 -2
- package/dist/adapter/file/file.db.d.ts +12 -12
- package/dist/adapter/file/file.db.model.d.ts +2 -2
- package/dist/adapter/file/localFile.persistence.plugin.d.ts +3 -3
- package/dist/adapter/file/noop.persistence.plugin.d.ts +2 -2
- package/dist/adapter/inmemory/inMemory.db.d.ts +12 -12
- package/dist/adapter/inmemory/queryInMemory.d.ts +2 -2
- package/dist/base.common.db.d.ts +10 -10
- package/dist/common.db.d.ts +10 -10
- package/dist/commondao/common.dao.d.ts +26 -27
- package/dist/commondao/common.dao.js +12 -12
- package/dist/commondao/common.dao.model.d.ts +13 -13
- package/dist/db.model.d.ts +4 -4
- package/dist/query/dbQuery.d.ts +9 -9
- package/dist/testing/test.model.d.ts +3 -4
- package/dist/testing/test.model.js +1 -1
- package/dist/transaction/dbTransaction.util.d.ts +3 -3
- package/dist/validation/index.d.ts +2 -2
- package/package.json +1 -1
- package/src/adapter/cachedb/cache.db.model.ts +2 -2
- package/src/adapter/cachedb/cache.db.ts +18 -16
- package/src/adapter/file/file.db.model.ts +2 -2
- package/src/adapter/file/file.db.ts +17 -15
- package/src/adapter/file/localFile.persistence.plugin.ts +4 -4
- package/src/adapter/file/noop.persistence.plugin.ts +2 -2
- package/src/adapter/inmemory/inMemory.db.ts +20 -18
- package/src/adapter/inmemory/queryInMemory.ts +5 -2
- package/src/base.common.db.ts +20 -10
- package/src/common.db.ts +20 -13
- package/src/commondao/common.dao.model.ts +21 -15
- package/src/commondao/common.dao.ts +80 -69
- package/src/db.model.ts +4 -4
- package/src/query/dbQuery.ts +13 -11
- package/src/testing/test.model.ts +4 -6
- package/src/transaction/dbTransaction.util.ts +3 -3
package/src/common.db.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
JsonSchemaObject,
|
|
3
|
+
JsonSchemaRootObject,
|
|
4
|
+
PartialObjectWithId,
|
|
5
|
+
Saved,
|
|
6
|
+
} from '@naturalcycles/js-lib'
|
|
2
7
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
3
8
|
import {
|
|
4
9
|
CommonDBCreateOptions,
|
|
@@ -64,13 +69,15 @@ export interface CommonDB {
|
|
|
64
69
|
*
|
|
65
70
|
* This is important for the code to rely on it, and it's verified by dbTest
|
|
66
71
|
*/
|
|
67
|
-
getTableSchema: <ROW extends
|
|
72
|
+
getTableSchema: <ROW extends PartialObjectWithId>(
|
|
73
|
+
table: string,
|
|
74
|
+
) => Promise<JsonSchemaRootObject<ROW>>
|
|
68
75
|
|
|
69
76
|
/**
|
|
70
77
|
* Will do like `create table ...` for mysql.
|
|
71
78
|
* Caution! dropIfExists defaults to false. If set to true - will actually DROP the table!
|
|
72
79
|
*/
|
|
73
|
-
createTable: <ROW extends
|
|
80
|
+
createTable: <ROW extends PartialObjectWithId>(
|
|
74
81
|
table: string,
|
|
75
82
|
schema: JsonSchemaObject<ROW>,
|
|
76
83
|
opt?: CommonDBCreateOptions,
|
|
@@ -81,36 +88,36 @@ export interface CommonDB {
|
|
|
81
88
|
* Order of items returned is not guaranteed to match order of ids.
|
|
82
89
|
* (Such limitation exists because Datastore doesn't support it).
|
|
83
90
|
*/
|
|
84
|
-
getByIds: <ROW extends
|
|
91
|
+
getByIds: <ROW extends PartialObjectWithId>(
|
|
85
92
|
table: string,
|
|
86
93
|
ids: string[],
|
|
87
94
|
opt?: CommonDBOptions,
|
|
88
|
-
) => Promise<ROW[]>
|
|
95
|
+
) => Promise<Saved<ROW>[]>
|
|
89
96
|
|
|
90
97
|
// QUERY
|
|
91
98
|
/**
|
|
92
99
|
* Order by 'id' is not supported by all implementations (for example, Datastore doesn't support it).
|
|
93
100
|
*/
|
|
94
|
-
runQuery: <ROW extends
|
|
101
|
+
runQuery: <ROW extends PartialObjectWithId>(
|
|
95
102
|
q: DBQuery<ROW>,
|
|
96
103
|
opt?: CommonDBOptions,
|
|
97
|
-
) => Promise<RunQueryResult<ROW
|
|
104
|
+
) => Promise<RunQueryResult<Saved<ROW>>>
|
|
98
105
|
|
|
99
|
-
runQueryCount: <ROW extends
|
|
106
|
+
runQueryCount: <ROW extends PartialObjectWithId>(
|
|
100
107
|
q: DBQuery<ROW>,
|
|
101
108
|
opt?: CommonDBOptions,
|
|
102
109
|
) => Promise<number>
|
|
103
110
|
|
|
104
|
-
streamQuery: <ROW extends
|
|
111
|
+
streamQuery: <ROW extends PartialObjectWithId>(
|
|
105
112
|
q: DBQuery<ROW>,
|
|
106
113
|
opt?: CommonDBStreamOptions,
|
|
107
|
-
) => ReadableTyped<ROW
|
|
114
|
+
) => ReadableTyped<Saved<ROW>>
|
|
108
115
|
|
|
109
116
|
// SAVE
|
|
110
117
|
/**
|
|
111
118
|
* rows can have missing ids only if DB supports auto-generating them (like mysql auto_increment).
|
|
112
119
|
*/
|
|
113
|
-
saveBatch: <ROW extends
|
|
120
|
+
saveBatch: <ROW extends PartialObjectWithId>(
|
|
114
121
|
table: string,
|
|
115
122
|
rows: ROW[],
|
|
116
123
|
opt?: CommonDBSaveOptions<ROW>,
|
|
@@ -127,7 +134,7 @@ export interface CommonDB {
|
|
|
127
134
|
* Returns number of deleted items.
|
|
128
135
|
* Not supported by all implementations (e.g Datastore will always return same number as number of ids).
|
|
129
136
|
*/
|
|
130
|
-
deleteByQuery: <ROW extends
|
|
137
|
+
deleteByQuery: <ROW extends PartialObjectWithId>(
|
|
131
138
|
q: DBQuery<ROW>,
|
|
132
139
|
opt?: CommonDBOptions,
|
|
133
140
|
) => Promise<number>
|
|
@@ -150,7 +157,7 @@ export interface CommonDB {
|
|
|
150
157
|
*
|
|
151
158
|
* Returns number of rows affected.
|
|
152
159
|
*/
|
|
153
|
-
updateByQuery: <ROW extends
|
|
160
|
+
updateByQuery: <ROW extends PartialObjectWithId>(
|
|
154
161
|
q: DBQuery<ROW>,
|
|
155
162
|
patch: DBPatch<ROW>,
|
|
156
163
|
opt?: CommonDBOptions,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CommonLogger,
|
|
3
3
|
ErrorMode,
|
|
4
|
-
|
|
4
|
+
PartialObjectWithId,
|
|
5
5
|
Promisable,
|
|
6
6
|
Saved,
|
|
7
7
|
ZodError,
|
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
import { CommonDB } from '../common.db'
|
|
19
19
|
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model'
|
|
20
20
|
|
|
21
|
-
export interface CommonDaoHooks<
|
|
21
|
+
export interface CommonDaoHooks<
|
|
22
|
+
BM extends PartialObjectWithId,
|
|
23
|
+
DBM extends PartialObjectWithId,
|
|
24
|
+
TM,
|
|
25
|
+
> {
|
|
22
26
|
/**
|
|
23
27
|
* Allows to override the id generation function.
|
|
24
28
|
* By default it uses `stringId` from nodejs-lib
|
|
@@ -59,7 +63,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
59
63
|
*/
|
|
60
64
|
beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>
|
|
61
65
|
|
|
62
|
-
beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>
|
|
66
|
+
beforeDBMToBM: (dbm: Saved<DBM>) => Partial<BM> | Promise<Partial<BM>>
|
|
63
67
|
beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>
|
|
64
68
|
beforeBMToTM: (bm: BM) => Partial<TM>
|
|
65
69
|
|
|
@@ -75,7 +79,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
75
79
|
*
|
|
76
80
|
* You can do validations as needed here and throw errors, they will be propagated.
|
|
77
81
|
*/
|
|
78
|
-
afterLoad?: (dbm: DBM) => Promisable<DBM | null>
|
|
82
|
+
afterLoad?: (dbm: Saved<DBM>) => Promisable<Saved<DBM> | null>
|
|
79
83
|
|
|
80
84
|
/**
|
|
81
85
|
* Allows to access the DBM just before it's supposed to be saved to the DB.
|
|
@@ -90,7 +94,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
90
94
|
*
|
|
91
95
|
* You can do validations as needed here and throw errors, they will be propagated.
|
|
92
96
|
*/
|
|
93
|
-
beforeSave?: (dbm: DBM) => Promisable<DBM | null>
|
|
97
|
+
beforeSave?: (dbm: Saved<DBM>) => Promisable<Saved<DBM> | null>
|
|
94
98
|
|
|
95
99
|
/**
|
|
96
100
|
* Called in:
|
|
@@ -101,7 +105,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
101
105
|
* It still applies to BM "transitively", during dbmToBM
|
|
102
106
|
* (e.g after loaded from the Database).
|
|
103
107
|
*/
|
|
104
|
-
anonymize: (dbm: DBM) => DBM
|
|
108
|
+
anonymize: (dbm: Saved<DBM>) => Saved<DBM>
|
|
105
109
|
|
|
106
110
|
/**
|
|
107
111
|
* If hook is defined - allows to prevent or modify the error thrown.
|
|
@@ -132,8 +136,8 @@ export enum CommonDaoLogLevel {
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
export interface CommonDaoCfg<
|
|
135
|
-
BM extends
|
|
136
|
-
DBM extends
|
|
139
|
+
BM extends PartialObjectWithId,
|
|
140
|
+
DBM extends PartialObjectWithId = BM,
|
|
137
141
|
TM = BM,
|
|
138
142
|
> {
|
|
139
143
|
db: CommonDB
|
|
@@ -200,13 +204,13 @@ export interface CommonDaoCfg<
|
|
|
200
204
|
* Defaults to true
|
|
201
205
|
* Set to false to disable `created` field management.
|
|
202
206
|
*/
|
|
203
|
-
|
|
207
|
+
useCreatedProperty?: boolean
|
|
204
208
|
|
|
205
209
|
/**
|
|
206
210
|
* Defaults to true
|
|
207
211
|
* Set to false to disable `updated` field management.
|
|
208
212
|
*/
|
|
209
|
-
|
|
213
|
+
useUpdatedProperty?: boolean
|
|
210
214
|
|
|
211
215
|
/**
|
|
212
216
|
* Default is false.
|
|
@@ -276,8 +280,10 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
276
280
|
table?: string
|
|
277
281
|
}
|
|
278
282
|
|
|
279
|
-
export interface CommonDaoSaveOptions<
|
|
280
|
-
extends
|
|
283
|
+
export interface CommonDaoSaveOptions<
|
|
284
|
+
BM extends PartialObjectWithId,
|
|
285
|
+
DBM extends PartialObjectWithId,
|
|
286
|
+
> extends CommonDaoSaveBatchOptions<DBM> {
|
|
281
287
|
/**
|
|
282
288
|
* If provided - a check will be made.
|
|
283
289
|
* If the object for saving equals to the object passed to `skipIfEquals` - save operation will be skipped.
|
|
@@ -292,7 +298,7 @@ export interface CommonDaoSaveOptions<BM extends Partial<ObjectWithId>, DBM exte
|
|
|
292
298
|
/**
|
|
293
299
|
* All properties default to undefined.
|
|
294
300
|
*/
|
|
295
|
-
export interface CommonDaoSaveBatchOptions<DBM extends
|
|
301
|
+
export interface CommonDaoSaveBatchOptions<DBM extends PartialObjectWithId>
|
|
296
302
|
extends CommonDaoOptions,
|
|
297
303
|
CommonDBSaveOptions<DBM> {
|
|
298
304
|
/**
|
|
@@ -307,10 +313,10 @@ export interface CommonDaoSaveBatchOptions<DBM extends ObjectWithId>
|
|
|
307
313
|
ensureUniqueId?: boolean
|
|
308
314
|
}
|
|
309
315
|
|
|
310
|
-
export interface CommonDaoStreamDeleteOptions<DBM extends
|
|
316
|
+
export interface CommonDaoStreamDeleteOptions<DBM extends PartialObjectWithId>
|
|
311
317
|
extends CommonDaoStreamOptions<DBM> {}
|
|
312
318
|
|
|
313
|
-
export interface CommonDaoStreamSaveOptions<DBM extends
|
|
319
|
+
export interface CommonDaoStreamSaveOptions<DBM extends PartialObjectWithId>
|
|
314
320
|
extends CommonDaoSaveBatchOptions<DBM>,
|
|
315
321
|
CommonDaoStreamOptions<DBM> {}
|
|
316
322
|
|
|
@@ -18,11 +18,11 @@ import {
|
|
|
18
18
|
JsonSchemaObject,
|
|
19
19
|
JsonSchemaRootObject,
|
|
20
20
|
ObjectWithId,
|
|
21
|
+
PartialObjectWithId,
|
|
21
22
|
pMap,
|
|
22
23
|
Saved,
|
|
23
24
|
SKIP,
|
|
24
25
|
UnixTimestampMillisNumber,
|
|
25
|
-
Unsaved,
|
|
26
26
|
ZodSchema,
|
|
27
27
|
ZodValidationError,
|
|
28
28
|
zSafeValidate,
|
|
@@ -43,7 +43,13 @@ import {
|
|
|
43
43
|
writableVoid,
|
|
44
44
|
} from '@naturalcycles/nodejs-lib'
|
|
45
45
|
import { DBLibError } from '../cnst'
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
CommonDBTransactionOptions,
|
|
48
|
+
DBModelType,
|
|
49
|
+
DBPatch,
|
|
50
|
+
DBTransaction,
|
|
51
|
+
RunQueryResult,
|
|
52
|
+
} from '../db.model'
|
|
47
53
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
|
|
48
54
|
import {
|
|
49
55
|
CommonDaoCfg,
|
|
@@ -70,8 +76,8 @@ const isCI = !!process.env['CI']
|
|
|
70
76
|
* TM = Transport model (optimized to be sent over the wire)
|
|
71
77
|
*/
|
|
72
78
|
export class CommonDao<
|
|
73
|
-
BM extends
|
|
74
|
-
DBM extends
|
|
79
|
+
BM extends PartialObjectWithId,
|
|
80
|
+
DBM extends PartialObjectWithId = BM,
|
|
75
81
|
TM extends AnyObject = BM,
|
|
76
82
|
> {
|
|
77
83
|
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
@@ -82,8 +88,8 @@ export class CommonDao<
|
|
|
82
88
|
logLevel: isGAE || isCI ? CommonDaoLogLevel.NONE : CommonDaoLogLevel.OPERATIONS,
|
|
83
89
|
createId: true,
|
|
84
90
|
assignGeneratedIds: false,
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
useCreatedProperty: true,
|
|
92
|
+
useUpdatedProperty: true,
|
|
87
93
|
logger: console,
|
|
88
94
|
...cfg,
|
|
89
95
|
hooks: {
|
|
@@ -110,7 +116,7 @@ export class CommonDao<
|
|
|
110
116
|
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
111
117
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
112
118
|
// First assignIdCreatedUpdated, then validate!
|
|
113
|
-
this.assignIdCreatedUpdated(bm as
|
|
119
|
+
this.assignIdCreatedUpdated(bm as BM, opt)
|
|
114
120
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
115
121
|
}
|
|
116
122
|
|
|
@@ -148,17 +154,17 @@ export class CommonDao<
|
|
|
148
154
|
id: string,
|
|
149
155
|
part: Partial<BM> = {},
|
|
150
156
|
opt?: CommonDaoOptions,
|
|
151
|
-
): Promise<DBM
|
|
157
|
+
): Promise<Saved<DBM>> {
|
|
152
158
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
153
159
|
if (dbm) return dbm
|
|
154
160
|
|
|
155
|
-
const bm
|
|
161
|
+
const bm = this.create({ ...part, id }, opt)
|
|
156
162
|
return await this.bmToDBM(bm, opt)
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
async getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
160
|
-
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>
|
|
161
|
-
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
|
|
166
|
+
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<Saved<DBM> | null>
|
|
167
|
+
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<Saved<DBM> | null> {
|
|
162
168
|
if (!id) return null
|
|
163
169
|
const op = `getByIdAsDBM(${id})`
|
|
164
170
|
const table = opt.table || this.cfg.table
|
|
@@ -214,7 +220,7 @@ export class CommonDao<
|
|
|
214
220
|
return bms
|
|
215
221
|
}
|
|
216
222
|
|
|
217
|
-
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
223
|
+
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
218
224
|
if (!ids.length) return []
|
|
219
225
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
220
226
|
const table = opt.table || this.cfg.table
|
|
@@ -238,7 +244,7 @@ export class CommonDao<
|
|
|
238
244
|
return r
|
|
239
245
|
}
|
|
240
246
|
|
|
241
|
-
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<DBM
|
|
247
|
+
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<Saved<DBM>> {
|
|
242
248
|
const r = await this.getByIdAsDBM(id, opt)
|
|
243
249
|
if (!r) {
|
|
244
250
|
this.throwRequiredError(id, opt)
|
|
@@ -276,7 +282,7 @@ export class CommonDao<
|
|
|
276
282
|
}
|
|
277
283
|
}
|
|
278
284
|
|
|
279
|
-
private async ensureUniqueId(table: string, dbm: DBM): Promise<void> {
|
|
285
|
+
private async ensureUniqueId(table: string, dbm: Saved<DBM>): Promise<void> {
|
|
280
286
|
// todo: retry N times
|
|
281
287
|
const existing = await this.cfg.db.getByIds<DBM>(table, [dbm.id])
|
|
282
288
|
if (existing.length) {
|
|
@@ -360,7 +366,7 @@ export class CommonDao<
|
|
|
360
366
|
}
|
|
361
367
|
}
|
|
362
368
|
|
|
363
|
-
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]> {
|
|
369
|
+
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<DBM>[]> {
|
|
364
370
|
const { rows } = await this.runQueryExtendedAsDBM(q, opt)
|
|
365
371
|
return rows
|
|
366
372
|
}
|
|
@@ -368,7 +374,7 @@ export class CommonDao<
|
|
|
368
374
|
async runQueryExtendedAsDBM(
|
|
369
375
|
q: DBQuery<DBM>,
|
|
370
376
|
opt: CommonDaoOptions = {},
|
|
371
|
-
): Promise<RunQueryResult<DBM
|
|
377
|
+
): Promise<RunQueryResult<Saved<DBM>>> {
|
|
372
378
|
q.table = opt.table || q.table
|
|
373
379
|
const op = `runQueryAsDBM(${q.pretty()})`
|
|
374
380
|
const started = this.logStarted(op, q.table)
|
|
@@ -442,7 +448,7 @@ export class CommonDao<
|
|
|
442
448
|
|
|
443
449
|
await _pipeline([
|
|
444
450
|
this.cfg.db.streamQuery<DBM>(q, opt),
|
|
445
|
-
transformMap<DBM
|
|
451
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
446
452
|
async dbm => {
|
|
447
453
|
count++
|
|
448
454
|
if (partialQuery || opt.raw) return dbm as any
|
|
@@ -542,7 +548,7 @@ export class CommonDao<
|
|
|
542
548
|
return stream
|
|
543
549
|
.on('error', err => stream.emit('error', err))
|
|
544
550
|
.pipe(
|
|
545
|
-
transformMap<any, DBM
|
|
551
|
+
transformMap<any, Saved<DBM>>(
|
|
546
552
|
async dbm => {
|
|
547
553
|
if (this.cfg.hooks!.afterLoad) {
|
|
548
554
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -587,7 +593,7 @@ export class CommonDao<
|
|
|
587
593
|
// .pipe(transformMap<DBM, Saved<BM>>(dbm => this.dbmToBM(dbm, opt), safeOpt))
|
|
588
594
|
.on('error', err => stream.emit('error', err))
|
|
589
595
|
.pipe(
|
|
590
|
-
transformMap<DBM
|
|
596
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
591
597
|
async dbm => {
|
|
592
598
|
if (this.cfg.hooks!.afterLoad) {
|
|
593
599
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -621,7 +627,7 @@ export class CommonDao<
|
|
|
621
627
|
.streamQuery<DBM>(q.select(['id']), opt)
|
|
622
628
|
.on('error', err => stream.emit('error', err))
|
|
623
629
|
.pipe(
|
|
624
|
-
transformMapSimple<DBM
|
|
630
|
+
transformMapSimple<Saved<DBM>, string>(r => r.id, {
|
|
625
631
|
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
626
632
|
}),
|
|
627
633
|
)
|
|
@@ -643,9 +649,9 @@ export class CommonDao<
|
|
|
643
649
|
|
|
644
650
|
await _pipeline([
|
|
645
651
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
646
|
-
transformMapSimple<DBM
|
|
652
|
+
transformMapSimple<Saved<DBM>, string>(r => {
|
|
647
653
|
count++
|
|
648
|
-
return
|
|
654
|
+
return r.id
|
|
649
655
|
}),
|
|
650
656
|
transformMap<string, void>(mapper, {
|
|
651
657
|
...opt,
|
|
@@ -668,17 +674,19 @@ export class CommonDao<
|
|
|
668
674
|
* Mutates!
|
|
669
675
|
* "Returns", just to have a type of "Saved"
|
|
670
676
|
*/
|
|
671
|
-
assignIdCreatedUpdated(obj: DBM
|
|
672
|
-
assignIdCreatedUpdated(obj: BM
|
|
673
|
-
assignIdCreatedUpdated(
|
|
674
|
-
|
|
677
|
+
assignIdCreatedUpdated(obj: Partial<DBM>, opt?: CommonDaoOptions): Saved<Partial<DBM>>
|
|
678
|
+
assignIdCreatedUpdated(obj: Partial<BM>, opt?: CommonDaoOptions): Saved<Partial<BM>>
|
|
679
|
+
assignIdCreatedUpdated(
|
|
680
|
+
obj: Partial<DBM> | Partial<BM>,
|
|
681
|
+
opt: CommonDaoOptions = {},
|
|
682
|
+
): Saved<Partial<DBM>> | Saved<Partial<BM>> {
|
|
675
683
|
const now = Math.floor(Date.now() / 1000)
|
|
676
684
|
|
|
677
|
-
if (this.cfg.
|
|
685
|
+
if (this.cfg.useCreatedProperty) {
|
|
678
686
|
;(obj as any)['created'] ||= (obj as any)['updated'] || now
|
|
679
687
|
}
|
|
680
688
|
|
|
681
|
-
if (this.cfg.
|
|
689
|
+
if (this.cfg.useUpdatedProperty) {
|
|
682
690
|
;(obj as any)['updated'] =
|
|
683
691
|
opt.preserveUpdatedCreated && (obj as any)['updated'] ? (obj as any)['updated'] : now
|
|
684
692
|
}
|
|
@@ -694,7 +702,7 @@ export class CommonDao<
|
|
|
694
702
|
/**
|
|
695
703
|
* Mutates with id, created, updated
|
|
696
704
|
*/
|
|
697
|
-
async save(bm:
|
|
705
|
+
async save(bm: BM, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<Saved<BM>> {
|
|
698
706
|
this.requireWriteAccess()
|
|
699
707
|
|
|
700
708
|
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
@@ -704,7 +712,7 @@ export class CommonDao<
|
|
|
704
712
|
|
|
705
713
|
const idWasGenerated = !bm.id && this.cfg.createId
|
|
706
714
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
707
|
-
let dbm = await this.bmToDBM(bm
|
|
715
|
+
let dbm = await this.bmToDBM(bm, opt)
|
|
708
716
|
|
|
709
717
|
if (this.cfg.hooks!.beforeSave) {
|
|
710
718
|
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
@@ -728,11 +736,11 @@ export class CommonDao<
|
|
|
728
736
|
})
|
|
729
737
|
|
|
730
738
|
if (assignGeneratedIds) {
|
|
731
|
-
bm.id = dbm.id
|
|
739
|
+
bm.id = dbm.id
|
|
732
740
|
}
|
|
733
741
|
|
|
734
742
|
this.logSaveResult(started, op, table)
|
|
735
|
-
return bm as
|
|
743
|
+
return bm as Saved<BM>
|
|
736
744
|
}
|
|
737
745
|
|
|
738
746
|
/**
|
|
@@ -829,13 +837,13 @@ export class CommonDao<
|
|
|
829
837
|
return await this.save(bm, opt)
|
|
830
838
|
}
|
|
831
839
|
|
|
832
|
-
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM
|
|
840
|
+
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<DBM>> {
|
|
833
841
|
this.requireWriteAccess()
|
|
834
842
|
const table = opt.table || this.cfg.table
|
|
835
843
|
|
|
836
844
|
// assigning id in case it misses the id
|
|
837
845
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
838
|
-
let row = dbm
|
|
846
|
+
let row = dbm as Saved<DBM>
|
|
839
847
|
if (!opt.raw) {
|
|
840
848
|
const idWasGenerated = !dbm.id && this.cfg.createId
|
|
841
849
|
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
@@ -852,7 +860,7 @@ export class CommonDao<
|
|
|
852
860
|
|
|
853
861
|
if (this.cfg.hooks!.beforeSave) {
|
|
854
862
|
row = (await this.cfg.hooks!.beforeSave(row))!
|
|
855
|
-
if (row === null) return dbm
|
|
863
|
+
if (row === null) return dbm as Saved<DBM>
|
|
856
864
|
}
|
|
857
865
|
|
|
858
866
|
await this.cfg.db.saveBatch(table, [row], {
|
|
@@ -869,15 +877,12 @@ export class CommonDao<
|
|
|
869
877
|
return row
|
|
870
878
|
}
|
|
871
879
|
|
|
872
|
-
async saveBatch(
|
|
873
|
-
bms: Unsaved<BM>[],
|
|
874
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
875
|
-
): Promise<Saved<BM>[]> {
|
|
880
|
+
async saveBatch(bms: BM[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<BM>[]> {
|
|
876
881
|
if (!bms.length) return []
|
|
877
882
|
this.requireWriteAccess()
|
|
878
883
|
const table = opt.table || this.cfg.table
|
|
879
884
|
bms.forEach(bm => this.assignIdCreatedUpdated(bm, opt))
|
|
880
|
-
let dbms = await this.bmsToDBM(bms
|
|
885
|
+
let dbms = await this.bmsToDBM(bms, opt)
|
|
881
886
|
|
|
882
887
|
if (this.cfg.hooks!.beforeSave && dbms.length) {
|
|
883
888
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.beforeSave!(dbm))).filter(
|
|
@@ -908,22 +913,25 @@ export class CommonDao<
|
|
|
908
913
|
})
|
|
909
914
|
|
|
910
915
|
if (assignGeneratedIds) {
|
|
911
|
-
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id
|
|
916
|
+
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id))
|
|
912
917
|
}
|
|
913
918
|
|
|
914
919
|
this.logSaveResult(started, op, table)
|
|
915
920
|
|
|
916
|
-
return bms as
|
|
921
|
+
return bms as Saved<BM>[]
|
|
917
922
|
}
|
|
918
923
|
|
|
919
|
-
async saveBatchAsDBM(
|
|
924
|
+
async saveBatchAsDBM(
|
|
925
|
+
dbms: DBM[],
|
|
926
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
927
|
+
): Promise<Saved<DBM>[]> {
|
|
920
928
|
if (!dbms.length) return []
|
|
921
929
|
this.requireWriteAccess()
|
|
922
930
|
const table = opt.table || this.cfg.table
|
|
923
|
-
let rows = dbms
|
|
931
|
+
let rows = dbms as Saved<DBM>[]
|
|
924
932
|
if (!opt.raw) {
|
|
925
933
|
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
926
|
-
rows = this.anyToDBMs(dbms, opt)
|
|
934
|
+
rows = this.anyToDBMs(dbms as Saved<DBM>[], opt)
|
|
927
935
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
928
936
|
}
|
|
929
937
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
@@ -984,7 +992,7 @@ export class CommonDao<
|
|
|
984
992
|
const { batchSize = 500, batchConcurrency = 16, errorMode } = opt
|
|
985
993
|
|
|
986
994
|
return [
|
|
987
|
-
transformMap<BM, DBM
|
|
995
|
+
transformMap<BM, Saved<DBM>>(
|
|
988
996
|
async bm => {
|
|
989
997
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
990
998
|
|
|
@@ -1077,7 +1085,7 @@ export class CommonDao<
|
|
|
1077
1085
|
|
|
1078
1086
|
await _pipeline([
|
|
1079
1087
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
1080
|
-
transformMapSimple<
|
|
1088
|
+
transformMapSimple<ObjectWithId, string>(r => r.id, {
|
|
1081
1089
|
errorMode: ErrorMode.SUPPRESS,
|
|
1082
1090
|
}),
|
|
1083
1091
|
transformBuffer<string>({ batchSize }),
|
|
@@ -1141,13 +1149,13 @@ export class CommonDao<
|
|
|
1141
1149
|
// CONVERSIONS
|
|
1142
1150
|
|
|
1143
1151
|
async dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1144
|
-
async dbmToBM(_dbm?: DBM
|
|
1145
|
-
async dbmToBM(_dbm?: DBM
|
|
1152
|
+
async dbmToBM(_dbm?: Saved<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>>
|
|
1153
|
+
async dbmToBM(_dbm?: Saved<DBM>, opt: CommonDaoOptions = {}): Promise<Saved<BM> | undefined> {
|
|
1146
1154
|
if (!_dbm) return
|
|
1147
1155
|
|
|
1148
1156
|
// optimization: no need to run full joi DBM validation, cause BM validation will be run
|
|
1149
1157
|
// const dbm = this.anyToDBM(_dbm, opt)
|
|
1150
|
-
let dbm: DBM = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1158
|
+
let dbm: Saved<DBM> = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1151
1159
|
|
|
1152
1160
|
if (opt.anonymize) {
|
|
1153
1161
|
dbm = this.cfg.hooks!.anonymize!(dbm)
|
|
@@ -1161,7 +1169,7 @@ export class CommonDao<
|
|
|
1161
1169
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1162
1170
|
}
|
|
1163
1171
|
|
|
1164
|
-
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1172
|
+
async dbmsToBM(dbms: Saved<DBM>[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1165
1173
|
return await pMap(dbms, async dbm => await this.dbmToBM(dbm, opt))
|
|
1166
1174
|
}
|
|
1167
1175
|
|
|
@@ -1170,8 +1178,8 @@ export class CommonDao<
|
|
|
1170
1178
|
* Returns DBM (new reference).
|
|
1171
1179
|
*/
|
|
1172
1180
|
async bmToDBM(bm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1173
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM
|
|
1174
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM | undefined> {
|
|
1181
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM>>
|
|
1182
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM> | undefined> {
|
|
1175
1183
|
if (bm === undefined) return
|
|
1176
1184
|
|
|
1177
1185
|
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
@@ -1190,14 +1198,14 @@ export class CommonDao<
|
|
|
1190
1198
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1191
1199
|
}
|
|
1192
1200
|
|
|
1193
|
-
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
1201
|
+
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
1194
1202
|
// try/catch?
|
|
1195
1203
|
return await pMap(bms, async bm => await this.bmToDBM(bm, opt))
|
|
1196
1204
|
}
|
|
1197
1205
|
|
|
1198
1206
|
anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined
|
|
1199
|
-
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM
|
|
1200
|
-
anyToDBM(dbm?: DBM
|
|
1207
|
+
anyToDBM(dbm?: any, opt?: CommonDaoOptions): Saved<DBM>
|
|
1208
|
+
anyToDBM(dbm?: Saved<DBM>, opt: CommonDaoOptions = {}): Saved<DBM> | undefined {
|
|
1201
1209
|
if (!dbm) return
|
|
1202
1210
|
|
|
1203
1211
|
// this shouldn't be happening on load! but should on save!
|
|
@@ -1213,7 +1221,7 @@ export class CommonDao<
|
|
|
1213
1221
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1214
1222
|
}
|
|
1215
1223
|
|
|
1216
|
-
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}): DBM[] {
|
|
1224
|
+
anyToDBMs(entities: Saved<DBM>[], opt: CommonDaoOptions = {}): Saved<DBM>[] {
|
|
1217
1225
|
return entities.map(entity => this.anyToDBM(entity, opt))
|
|
1218
1226
|
}
|
|
1219
1227
|
|
|
@@ -1228,7 +1236,7 @@ export class CommonDao<
|
|
|
1228
1236
|
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1229
1237
|
|
|
1230
1238
|
// BM > TM
|
|
1231
|
-
const tm = this.cfg.hooks!.beforeBMToTM!(bm
|
|
1239
|
+
const tm = this.cfg.hooks!.beforeBMToTM!(bm)
|
|
1232
1240
|
|
|
1233
1241
|
// Validate/convert DBM
|
|
1234
1242
|
return this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
@@ -1321,7 +1329,7 @@ export class CommonDao<
|
|
|
1321
1329
|
|
|
1322
1330
|
async createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void> {
|
|
1323
1331
|
this.requireWriteAccess()
|
|
1324
|
-
await this.cfg.db.createTable(this.cfg.table, schema
|
|
1332
|
+
await this.cfg.db.createTable(this.cfg.table, schema, opt)
|
|
1325
1333
|
}
|
|
1326
1334
|
|
|
1327
1335
|
/**
|
|
@@ -1331,17 +1339,20 @@ export class CommonDao<
|
|
|
1331
1339
|
await this.cfg.db.ping()
|
|
1332
1340
|
}
|
|
1333
1341
|
|
|
1334
|
-
async runInTransaction(
|
|
1342
|
+
async runInTransaction(
|
|
1343
|
+
fn: CommonDaoTransactionFn,
|
|
1344
|
+
opt?: CommonDBTransactionOptions,
|
|
1345
|
+
): Promise<void> {
|
|
1335
1346
|
await this.cfg.db.runInTransaction(async tx => {
|
|
1336
1347
|
const daoTx = new CommonDaoTransaction(tx, this.cfg.logger!)
|
|
1337
1348
|
|
|
1338
1349
|
try {
|
|
1339
1350
|
await fn(daoTx)
|
|
1340
1351
|
} catch (err) {
|
|
1341
|
-
await daoTx.rollback()
|
|
1352
|
+
await daoTx.rollback() // graceful rollback that "never throws"
|
|
1342
1353
|
throw err
|
|
1343
1354
|
}
|
|
1344
|
-
})
|
|
1355
|
+
}, opt)
|
|
1345
1356
|
}
|
|
1346
1357
|
|
|
1347
1358
|
protected logResult(started: number, op: string, res: any, table: string): void {
|
|
@@ -1430,7 +1441,7 @@ export class CommonDaoTransaction {
|
|
|
1430
1441
|
}
|
|
1431
1442
|
}
|
|
1432
1443
|
|
|
1433
|
-
async getById<BM extends
|
|
1444
|
+
async getById<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1434
1445
|
dao: CommonDao<BM, DBM, any>,
|
|
1435
1446
|
id?: string | null,
|
|
1436
1447
|
opt?: CommonDaoOptions,
|
|
@@ -1439,7 +1450,7 @@ export class CommonDaoTransaction {
|
|
|
1439
1450
|
return (await this.getByIds(dao, [id], opt))[0] || null
|
|
1440
1451
|
}
|
|
1441
1452
|
|
|
1442
|
-
async getByIds<BM extends
|
|
1453
|
+
async getByIds<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1443
1454
|
dao: CommonDao<BM, DBM, any>,
|
|
1444
1455
|
ids: string[],
|
|
1445
1456
|
opt?: CommonDaoOptions,
|
|
@@ -1448,7 +1459,7 @@ export class CommonDaoTransaction {
|
|
|
1448
1459
|
}
|
|
1449
1460
|
|
|
1450
1461
|
// todo: Queries inside Transaction are not supported yet
|
|
1451
|
-
// async runQuery<BM extends
|
|
1462
|
+
// async runQuery<BM extends PartialObjectWithId, DBM extends ObjectWithId>(
|
|
1452
1463
|
// dao: CommonDao<BM, DBM, any>,
|
|
1453
1464
|
// q: DBQuery<DBM>,
|
|
1454
1465
|
// opt?: CommonDaoOptions,
|
|
@@ -1461,17 +1472,17 @@ export class CommonDaoTransaction {
|
|
|
1461
1472
|
// }
|
|
1462
1473
|
// }
|
|
1463
1474
|
|
|
1464
|
-
async save<BM extends
|
|
1475
|
+
async save<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1465
1476
|
dao: CommonDao<BM, DBM, any>,
|
|
1466
|
-
bm:
|
|
1477
|
+
bm: BM,
|
|
1467
1478
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1468
1479
|
): Promise<Saved<BM>> {
|
|
1469
1480
|
return (await this.saveBatch(dao, [bm], opt))[0]!
|
|
1470
1481
|
}
|
|
1471
1482
|
|
|
1472
|
-
async saveBatch<BM extends
|
|
1483
|
+
async saveBatch<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1473
1484
|
dao: CommonDao<BM, DBM, any>,
|
|
1474
|
-
bms:
|
|
1485
|
+
bms: BM[],
|
|
1475
1486
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1476
1487
|
): Promise<Saved<BM>[]> {
|
|
1477
1488
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx })
|