@naturalcycles/db-lib 9.2.1 → 9.3.1
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 +23 -25
- package/dist/commondao/common.dao.js +16 -15
- 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 +23 -16
- package/src/commondao/common.dao.ts +68 -71
- 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,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AnyObject,
|
|
2
3
|
CommonLogger,
|
|
3
4
|
ErrorMode,
|
|
4
|
-
|
|
5
|
+
PartialObjectWithId,
|
|
5
6
|
Promisable,
|
|
6
7
|
Saved,
|
|
7
8
|
ZodError,
|
|
@@ -18,7 +19,11 @@ import {
|
|
|
18
19
|
import { CommonDB } from '../common.db'
|
|
19
20
|
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model'
|
|
20
21
|
|
|
21
|
-
export interface CommonDaoHooks<
|
|
22
|
+
export interface CommonDaoHooks<
|
|
23
|
+
BM extends PartialObjectWithId,
|
|
24
|
+
DBM extends PartialObjectWithId,
|
|
25
|
+
TM,
|
|
26
|
+
> {
|
|
22
27
|
/**
|
|
23
28
|
* Allows to override the id generation function.
|
|
24
29
|
* By default it uses `stringId` from nodejs-lib
|
|
@@ -59,7 +64,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
59
64
|
*/
|
|
60
65
|
beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>
|
|
61
66
|
|
|
62
|
-
beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>
|
|
67
|
+
beforeDBMToBM: (dbm: Saved<DBM>) => Partial<BM> | Promise<Partial<BM>>
|
|
63
68
|
beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>
|
|
64
69
|
beforeBMToTM: (bm: BM) => Partial<TM>
|
|
65
70
|
|
|
@@ -75,7 +80,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
75
80
|
*
|
|
76
81
|
* You can do validations as needed here and throw errors, they will be propagated.
|
|
77
82
|
*/
|
|
78
|
-
afterLoad?: (dbm: DBM) => Promisable<DBM | null>
|
|
83
|
+
afterLoad?: (dbm: Saved<DBM>) => Promisable<Saved<DBM> | null>
|
|
79
84
|
|
|
80
85
|
/**
|
|
81
86
|
* Allows to access the DBM just before it's supposed to be saved to the DB.
|
|
@@ -90,7 +95,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
90
95
|
*
|
|
91
96
|
* You can do validations as needed here and throw errors, they will be propagated.
|
|
92
97
|
*/
|
|
93
|
-
beforeSave?: (dbm: DBM) => Promisable<DBM | null>
|
|
98
|
+
beforeSave?: (dbm: Saved<DBM>) => Promisable<Saved<DBM> | null>
|
|
94
99
|
|
|
95
100
|
/**
|
|
96
101
|
* Called in:
|
|
@@ -101,7 +106,7 @@ export interface CommonDaoHooks<BM extends Partial<ObjectWithId>, DBM extends Ob
|
|
|
101
106
|
* It still applies to BM "transitively", during dbmToBM
|
|
102
107
|
* (e.g after loaded from the Database).
|
|
103
108
|
*/
|
|
104
|
-
anonymize: (dbm: DBM) => DBM
|
|
109
|
+
anonymize: (dbm: Saved<DBM>) => Saved<DBM>
|
|
105
110
|
|
|
106
111
|
/**
|
|
107
112
|
* If hook is defined - allows to prevent or modify the error thrown.
|
|
@@ -132,9 +137,9 @@ export enum CommonDaoLogLevel {
|
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
export interface CommonDaoCfg<
|
|
135
|
-
BM extends
|
|
136
|
-
DBM extends
|
|
137
|
-
TM = BM,
|
|
140
|
+
BM extends PartialObjectWithId,
|
|
141
|
+
DBM extends PartialObjectWithId = BM,
|
|
142
|
+
TM extends AnyObject = BM,
|
|
138
143
|
> {
|
|
139
144
|
db: CommonDB
|
|
140
145
|
table: string
|
|
@@ -200,13 +205,13 @@ export interface CommonDaoCfg<
|
|
|
200
205
|
* Defaults to true
|
|
201
206
|
* Set to false to disable `created` field management.
|
|
202
207
|
*/
|
|
203
|
-
|
|
208
|
+
useCreatedProperty?: boolean
|
|
204
209
|
|
|
205
210
|
/**
|
|
206
211
|
* Defaults to true
|
|
207
212
|
* Set to false to disable `updated` field management.
|
|
208
213
|
*/
|
|
209
|
-
|
|
214
|
+
useUpdatedProperty?: boolean
|
|
210
215
|
|
|
211
216
|
/**
|
|
212
217
|
* Default is false.
|
|
@@ -276,8 +281,10 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
276
281
|
table?: string
|
|
277
282
|
}
|
|
278
283
|
|
|
279
|
-
export interface CommonDaoSaveOptions<
|
|
280
|
-
extends
|
|
284
|
+
export interface CommonDaoSaveOptions<
|
|
285
|
+
BM extends PartialObjectWithId,
|
|
286
|
+
DBM extends PartialObjectWithId,
|
|
287
|
+
> extends CommonDaoSaveBatchOptions<DBM> {
|
|
281
288
|
/**
|
|
282
289
|
* If provided - a check will be made.
|
|
283
290
|
* If the object for saving equals to the object passed to `skipIfEquals` - save operation will be skipped.
|
|
@@ -292,7 +299,7 @@ export interface CommonDaoSaveOptions<BM extends Partial<ObjectWithId>, DBM exte
|
|
|
292
299
|
/**
|
|
293
300
|
* All properties default to undefined.
|
|
294
301
|
*/
|
|
295
|
-
export interface CommonDaoSaveBatchOptions<DBM extends
|
|
302
|
+
export interface CommonDaoSaveBatchOptions<DBM extends PartialObjectWithId>
|
|
296
303
|
extends CommonDaoOptions,
|
|
297
304
|
CommonDBSaveOptions<DBM> {
|
|
298
305
|
/**
|
|
@@ -307,10 +314,10 @@ export interface CommonDaoSaveBatchOptions<DBM extends ObjectWithId>
|
|
|
307
314
|
ensureUniqueId?: boolean
|
|
308
315
|
}
|
|
309
316
|
|
|
310
|
-
export interface CommonDaoStreamDeleteOptions<DBM extends
|
|
317
|
+
export interface CommonDaoStreamDeleteOptions<DBM extends PartialObjectWithId>
|
|
311
318
|
extends CommonDaoStreamOptions<DBM> {}
|
|
312
319
|
|
|
313
|
-
export interface CommonDaoStreamSaveOptions<DBM extends
|
|
320
|
+
export interface CommonDaoStreamSaveOptions<DBM extends PartialObjectWithId>
|
|
314
321
|
extends CommonDaoSaveBatchOptions<DBM>,
|
|
315
322
|
CommonDaoStreamOptions<DBM> {}
|
|
316
323
|
|
|
@@ -13,16 +13,17 @@ import {
|
|
|
13
13
|
AnyObject,
|
|
14
14
|
AppError,
|
|
15
15
|
AsyncMapper,
|
|
16
|
+
BaseDBEntity,
|
|
16
17
|
CommonLogger,
|
|
17
18
|
ErrorMode,
|
|
18
19
|
JsonSchemaObject,
|
|
19
20
|
JsonSchemaRootObject,
|
|
20
21
|
ObjectWithId,
|
|
22
|
+
PartialObjectWithId,
|
|
21
23
|
pMap,
|
|
22
24
|
Saved,
|
|
23
25
|
SKIP,
|
|
24
26
|
UnixTimestampMillisNumber,
|
|
25
|
-
Unsaved,
|
|
26
27
|
ZodSchema,
|
|
27
28
|
ZodValidationError,
|
|
28
29
|
zSafeValidate,
|
|
@@ -76,8 +77,8 @@ const isCI = !!process.env['CI']
|
|
|
76
77
|
* TM = Transport model (optimized to be sent over the wire)
|
|
77
78
|
*/
|
|
78
79
|
export class CommonDao<
|
|
79
|
-
BM extends
|
|
80
|
-
DBM extends
|
|
80
|
+
BM extends PartialObjectWithId,
|
|
81
|
+
DBM extends PartialObjectWithId = BM,
|
|
81
82
|
TM extends AnyObject = BM,
|
|
82
83
|
> {
|
|
83
84
|
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
@@ -88,8 +89,8 @@ export class CommonDao<
|
|
|
88
89
|
logLevel: isGAE || isCI ? CommonDaoLogLevel.NONE : CommonDaoLogLevel.OPERATIONS,
|
|
89
90
|
createId: true,
|
|
90
91
|
assignGeneratedIds: false,
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
useCreatedProperty: true,
|
|
93
|
+
useUpdatedProperty: true,
|
|
93
94
|
logger: console,
|
|
94
95
|
...cfg,
|
|
95
96
|
hooks: {
|
|
@@ -116,7 +117,7 @@ export class CommonDao<
|
|
|
116
117
|
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
117
118
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
118
119
|
// First assignIdCreatedUpdated, then validate!
|
|
119
|
-
this.assignIdCreatedUpdated(bm
|
|
120
|
+
this.assignIdCreatedUpdated(bm, opt)
|
|
120
121
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
121
122
|
}
|
|
122
123
|
|
|
@@ -154,17 +155,17 @@ export class CommonDao<
|
|
|
154
155
|
id: string,
|
|
155
156
|
part: Partial<BM> = {},
|
|
156
157
|
opt?: CommonDaoOptions,
|
|
157
|
-
): Promise<DBM
|
|
158
|
+
): Promise<Saved<DBM>> {
|
|
158
159
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
159
160
|
if (dbm) return dbm
|
|
160
161
|
|
|
161
|
-
const bm
|
|
162
|
+
const bm = this.create({ ...part, id }, opt)
|
|
162
163
|
return await this.bmToDBM(bm, opt)
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
async getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
166
|
-
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>
|
|
167
|
-
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
|
|
167
|
+
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<Saved<DBM> | null>
|
|
168
|
+
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<Saved<DBM> | null> {
|
|
168
169
|
if (!id) return null
|
|
169
170
|
const op = `getByIdAsDBM(${id})`
|
|
170
171
|
const table = opt.table || this.cfg.table
|
|
@@ -220,7 +221,7 @@ export class CommonDao<
|
|
|
220
221
|
return bms
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
224
|
+
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
224
225
|
if (!ids.length) return []
|
|
225
226
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
226
227
|
const table = opt.table || this.cfg.table
|
|
@@ -244,7 +245,7 @@ export class CommonDao<
|
|
|
244
245
|
return r
|
|
245
246
|
}
|
|
246
247
|
|
|
247
|
-
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<DBM
|
|
248
|
+
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<Saved<DBM>> {
|
|
248
249
|
const r = await this.getByIdAsDBM(id, opt)
|
|
249
250
|
if (!r) {
|
|
250
251
|
this.throwRequiredError(id, opt)
|
|
@@ -282,7 +283,7 @@ export class CommonDao<
|
|
|
282
283
|
}
|
|
283
284
|
}
|
|
284
285
|
|
|
285
|
-
private async ensureUniqueId(table: string, dbm: DBM): Promise<void> {
|
|
286
|
+
private async ensureUniqueId(table: string, dbm: Saved<DBM>): Promise<void> {
|
|
286
287
|
// todo: retry N times
|
|
287
288
|
const existing = await this.cfg.db.getByIds<DBM>(table, [dbm.id])
|
|
288
289
|
if (existing.length) {
|
|
@@ -366,7 +367,7 @@ export class CommonDao<
|
|
|
366
367
|
}
|
|
367
368
|
}
|
|
368
369
|
|
|
369
|
-
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]> {
|
|
370
|
+
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<DBM>[]> {
|
|
370
371
|
const { rows } = await this.runQueryExtendedAsDBM(q, opt)
|
|
371
372
|
return rows
|
|
372
373
|
}
|
|
@@ -374,7 +375,7 @@ export class CommonDao<
|
|
|
374
375
|
async runQueryExtendedAsDBM(
|
|
375
376
|
q: DBQuery<DBM>,
|
|
376
377
|
opt: CommonDaoOptions = {},
|
|
377
|
-
): Promise<RunQueryResult<DBM
|
|
378
|
+
): Promise<RunQueryResult<Saved<DBM>>> {
|
|
378
379
|
q.table = opt.table || q.table
|
|
379
380
|
const op = `runQueryAsDBM(${q.pretty()})`
|
|
380
381
|
const started = this.logStarted(op, q.table)
|
|
@@ -448,7 +449,7 @@ export class CommonDao<
|
|
|
448
449
|
|
|
449
450
|
await _pipeline([
|
|
450
451
|
this.cfg.db.streamQuery<DBM>(q, opt),
|
|
451
|
-
transformMap<DBM
|
|
452
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
452
453
|
async dbm => {
|
|
453
454
|
count++
|
|
454
455
|
if (partialQuery || opt.raw) return dbm as any
|
|
@@ -548,7 +549,7 @@ export class CommonDao<
|
|
|
548
549
|
return stream
|
|
549
550
|
.on('error', err => stream.emit('error', err))
|
|
550
551
|
.pipe(
|
|
551
|
-
transformMap<any, DBM
|
|
552
|
+
transformMap<any, Saved<DBM>>(
|
|
552
553
|
async dbm => {
|
|
553
554
|
if (this.cfg.hooks!.afterLoad) {
|
|
554
555
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -593,7 +594,7 @@ export class CommonDao<
|
|
|
593
594
|
// .pipe(transformMap<DBM, Saved<BM>>(dbm => this.dbmToBM(dbm, opt), safeOpt))
|
|
594
595
|
.on('error', err => stream.emit('error', err))
|
|
595
596
|
.pipe(
|
|
596
|
-
transformMap<DBM
|
|
597
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
597
598
|
async dbm => {
|
|
598
599
|
if (this.cfg.hooks!.afterLoad) {
|
|
599
600
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -627,7 +628,7 @@ export class CommonDao<
|
|
|
627
628
|
.streamQuery<DBM>(q.select(['id']), opt)
|
|
628
629
|
.on('error', err => stream.emit('error', err))
|
|
629
630
|
.pipe(
|
|
630
|
-
transformMapSimple<DBM
|
|
631
|
+
transformMapSimple<Saved<DBM>, string>(r => r.id, {
|
|
631
632
|
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
632
633
|
}),
|
|
633
634
|
)
|
|
@@ -649,9 +650,9 @@ export class CommonDao<
|
|
|
649
650
|
|
|
650
651
|
await _pipeline([
|
|
651
652
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
652
|
-
transformMapSimple<DBM
|
|
653
|
+
transformMapSimple<Saved<DBM>, string>(r => {
|
|
653
654
|
count++
|
|
654
|
-
return
|
|
655
|
+
return r.id
|
|
655
656
|
}),
|
|
656
657
|
transformMap<string, void>(mapper, {
|
|
657
658
|
...opt,
|
|
@@ -674,33 +675,29 @@ export class CommonDao<
|
|
|
674
675
|
* Mutates!
|
|
675
676
|
* "Returns", just to have a type of "Saved"
|
|
676
677
|
*/
|
|
677
|
-
assignIdCreatedUpdated(obj:
|
|
678
|
-
assignIdCreatedUpdated(obj: BM, opt?: CommonDaoOptions): Saved<BM>
|
|
679
|
-
assignIdCreatedUpdated(obj: Unsaved<BM>, opt?: CommonDaoOptions): Saved<BM>
|
|
680
|
-
assignIdCreatedUpdated(obj: DBM | BM | Unsaved<BM>, opt: CommonDaoOptions = {}): DBM | Saved<BM> {
|
|
678
|
+
assignIdCreatedUpdated<T extends BaseDBEntity>(obj: T, opt: CommonDaoOptions = {}): Saved<T> {
|
|
681
679
|
const now = Math.floor(Date.now() / 1000)
|
|
682
680
|
|
|
683
|
-
if (this.cfg.
|
|
684
|
-
|
|
681
|
+
if (this.cfg.useCreatedProperty) {
|
|
682
|
+
obj.created ||= obj.updated || now
|
|
685
683
|
}
|
|
686
684
|
|
|
687
|
-
if (this.cfg.
|
|
688
|
-
|
|
689
|
-
opt.preserveUpdatedCreated && (obj as any)['updated'] ? (obj as any)['updated'] : now
|
|
685
|
+
if (this.cfg.useUpdatedProperty) {
|
|
686
|
+
obj.updated = opt.preserveUpdatedCreated && obj.updated ? obj.updated : now
|
|
690
687
|
}
|
|
691
688
|
|
|
692
689
|
if (this.cfg.createId) {
|
|
693
|
-
obj.id ||= this.cfg.hooks!.createNaturalId?.(obj as
|
|
690
|
+
obj.id ||= this.cfg.hooks!.createNaturalId?.(obj as any) || this.cfg.hooks!.createRandomId!()
|
|
694
691
|
}
|
|
695
692
|
|
|
696
|
-
return obj as
|
|
693
|
+
return obj as Saved<T>
|
|
697
694
|
}
|
|
698
695
|
|
|
699
696
|
// SAVE
|
|
700
697
|
/**
|
|
701
698
|
* Mutates with id, created, updated
|
|
702
699
|
*/
|
|
703
|
-
async save(bm:
|
|
700
|
+
async save(bm: BM, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<Saved<BM>> {
|
|
704
701
|
this.requireWriteAccess()
|
|
705
702
|
|
|
706
703
|
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
@@ -710,7 +707,7 @@ export class CommonDao<
|
|
|
710
707
|
|
|
711
708
|
const idWasGenerated = !bm.id && this.cfg.createId
|
|
712
709
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
713
|
-
let dbm = await this.bmToDBM(bm
|
|
710
|
+
let dbm = await this.bmToDBM(bm, opt)
|
|
714
711
|
|
|
715
712
|
if (this.cfg.hooks!.beforeSave) {
|
|
716
713
|
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
@@ -734,11 +731,11 @@ export class CommonDao<
|
|
|
734
731
|
})
|
|
735
732
|
|
|
736
733
|
if (assignGeneratedIds) {
|
|
737
|
-
bm.id = dbm.id
|
|
734
|
+
bm.id = dbm.id
|
|
738
735
|
}
|
|
739
736
|
|
|
740
737
|
this.logSaveResult(started, op, table)
|
|
741
|
-
return bm as
|
|
738
|
+
return bm as Saved<BM>
|
|
742
739
|
}
|
|
743
740
|
|
|
744
741
|
/**
|
|
@@ -835,13 +832,13 @@ export class CommonDao<
|
|
|
835
832
|
return await this.save(bm, opt)
|
|
836
833
|
}
|
|
837
834
|
|
|
838
|
-
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM
|
|
835
|
+
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<DBM>> {
|
|
839
836
|
this.requireWriteAccess()
|
|
840
837
|
const table = opt.table || this.cfg.table
|
|
841
838
|
|
|
842
839
|
// assigning id in case it misses the id
|
|
843
840
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
844
|
-
let row = dbm
|
|
841
|
+
let row = dbm as Saved<DBM>
|
|
845
842
|
if (!opt.raw) {
|
|
846
843
|
const idWasGenerated = !dbm.id && this.cfg.createId
|
|
847
844
|
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
@@ -858,7 +855,7 @@ export class CommonDao<
|
|
|
858
855
|
|
|
859
856
|
if (this.cfg.hooks!.beforeSave) {
|
|
860
857
|
row = (await this.cfg.hooks!.beforeSave(row))!
|
|
861
|
-
if (row === null) return dbm
|
|
858
|
+
if (row === null) return dbm as Saved<DBM>
|
|
862
859
|
}
|
|
863
860
|
|
|
864
861
|
await this.cfg.db.saveBatch(table, [row], {
|
|
@@ -875,15 +872,12 @@ export class CommonDao<
|
|
|
875
872
|
return row
|
|
876
873
|
}
|
|
877
874
|
|
|
878
|
-
async saveBatch(
|
|
879
|
-
bms: Unsaved<BM>[],
|
|
880
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
881
|
-
): Promise<Saved<BM>[]> {
|
|
875
|
+
async saveBatch(bms: BM[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<BM>[]> {
|
|
882
876
|
if (!bms.length) return []
|
|
883
877
|
this.requireWriteAccess()
|
|
884
878
|
const table = opt.table || this.cfg.table
|
|
885
879
|
bms.forEach(bm => this.assignIdCreatedUpdated(bm, opt))
|
|
886
|
-
let dbms = await this.bmsToDBM(bms
|
|
880
|
+
let dbms = await this.bmsToDBM(bms, opt)
|
|
887
881
|
|
|
888
882
|
if (this.cfg.hooks!.beforeSave && dbms.length) {
|
|
889
883
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.beforeSave!(dbm))).filter(
|
|
@@ -914,22 +908,25 @@ export class CommonDao<
|
|
|
914
908
|
})
|
|
915
909
|
|
|
916
910
|
if (assignGeneratedIds) {
|
|
917
|
-
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id
|
|
911
|
+
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id))
|
|
918
912
|
}
|
|
919
913
|
|
|
920
914
|
this.logSaveResult(started, op, table)
|
|
921
915
|
|
|
922
|
-
return bms as
|
|
916
|
+
return bms as Saved<BM>[]
|
|
923
917
|
}
|
|
924
918
|
|
|
925
|
-
async saveBatchAsDBM(
|
|
919
|
+
async saveBatchAsDBM(
|
|
920
|
+
dbms: DBM[],
|
|
921
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
922
|
+
): Promise<Saved<DBM>[]> {
|
|
926
923
|
if (!dbms.length) return []
|
|
927
924
|
this.requireWriteAccess()
|
|
928
925
|
const table = opt.table || this.cfg.table
|
|
929
|
-
let rows = dbms
|
|
926
|
+
let rows = dbms as Saved<DBM>[]
|
|
930
927
|
if (!opt.raw) {
|
|
931
928
|
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
932
|
-
rows = this.anyToDBMs(dbms, opt)
|
|
929
|
+
rows = this.anyToDBMs(dbms as Saved<DBM>[], opt)
|
|
933
930
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
934
931
|
}
|
|
935
932
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
@@ -990,7 +987,7 @@ export class CommonDao<
|
|
|
990
987
|
const { batchSize = 500, batchConcurrency = 16, errorMode } = opt
|
|
991
988
|
|
|
992
989
|
return [
|
|
993
|
-
transformMap<BM, DBM
|
|
990
|
+
transformMap<BM, Saved<DBM>>(
|
|
994
991
|
async bm => {
|
|
995
992
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
996
993
|
|
|
@@ -1083,7 +1080,7 @@ export class CommonDao<
|
|
|
1083
1080
|
|
|
1084
1081
|
await _pipeline([
|
|
1085
1082
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
1086
|
-
transformMapSimple<
|
|
1083
|
+
transformMapSimple<ObjectWithId, string>(r => r.id, {
|
|
1087
1084
|
errorMode: ErrorMode.SUPPRESS,
|
|
1088
1085
|
}),
|
|
1089
1086
|
transformBuffer<string>({ batchSize }),
|
|
@@ -1147,13 +1144,13 @@ export class CommonDao<
|
|
|
1147
1144
|
// CONVERSIONS
|
|
1148
1145
|
|
|
1149
1146
|
async dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1150
|
-
async dbmToBM(_dbm?: DBM
|
|
1151
|
-
async dbmToBM(_dbm?: DBM
|
|
1147
|
+
async dbmToBM(_dbm?: Saved<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>>
|
|
1148
|
+
async dbmToBM(_dbm?: Saved<DBM>, opt: CommonDaoOptions = {}): Promise<Saved<BM> | undefined> {
|
|
1152
1149
|
if (!_dbm) return
|
|
1153
1150
|
|
|
1154
1151
|
// optimization: no need to run full joi DBM validation, cause BM validation will be run
|
|
1155
1152
|
// const dbm = this.anyToDBM(_dbm, opt)
|
|
1156
|
-
let dbm: DBM = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1153
|
+
let dbm: Saved<DBM> = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1157
1154
|
|
|
1158
1155
|
if (opt.anonymize) {
|
|
1159
1156
|
dbm = this.cfg.hooks!.anonymize!(dbm)
|
|
@@ -1167,7 +1164,7 @@ export class CommonDao<
|
|
|
1167
1164
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1168
1165
|
}
|
|
1169
1166
|
|
|
1170
|
-
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1167
|
+
async dbmsToBM(dbms: Saved<DBM>[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1171
1168
|
return await pMap(dbms, async dbm => await this.dbmToBM(dbm, opt))
|
|
1172
1169
|
}
|
|
1173
1170
|
|
|
@@ -1176,8 +1173,8 @@ export class CommonDao<
|
|
|
1176
1173
|
* Returns DBM (new reference).
|
|
1177
1174
|
*/
|
|
1178
1175
|
async bmToDBM(bm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1179
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM
|
|
1180
|
-
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM | undefined> {
|
|
1176
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM>>
|
|
1177
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM> | undefined> {
|
|
1181
1178
|
if (bm === undefined) return
|
|
1182
1179
|
|
|
1183
1180
|
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
@@ -1196,14 +1193,14 @@ export class CommonDao<
|
|
|
1196
1193
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1197
1194
|
}
|
|
1198
1195
|
|
|
1199
|
-
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
1196
|
+
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
1200
1197
|
// try/catch?
|
|
1201
1198
|
return await pMap(bms, async bm => await this.bmToDBM(bm, opt))
|
|
1202
1199
|
}
|
|
1203
1200
|
|
|
1204
1201
|
anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined
|
|
1205
|
-
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM
|
|
1206
|
-
anyToDBM(dbm?: DBM
|
|
1202
|
+
anyToDBM(dbm?: any, opt?: CommonDaoOptions): Saved<DBM>
|
|
1203
|
+
anyToDBM(dbm?: Saved<DBM>, opt: CommonDaoOptions = {}): Saved<DBM> | undefined {
|
|
1207
1204
|
if (!dbm) return
|
|
1208
1205
|
|
|
1209
1206
|
// this shouldn't be happening on load! but should on save!
|
|
@@ -1219,7 +1216,7 @@ export class CommonDao<
|
|
|
1219
1216
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1220
1217
|
}
|
|
1221
1218
|
|
|
1222
|
-
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}): DBM[] {
|
|
1219
|
+
anyToDBMs(entities: Saved<DBM>[], opt: CommonDaoOptions = {}): Saved<DBM>[] {
|
|
1223
1220
|
return entities.map(entity => this.anyToDBM(entity, opt))
|
|
1224
1221
|
}
|
|
1225
1222
|
|
|
@@ -1234,7 +1231,7 @@ export class CommonDao<
|
|
|
1234
1231
|
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1235
1232
|
|
|
1236
1233
|
// BM > TM
|
|
1237
|
-
const tm = this.cfg.hooks!.beforeBMToTM!(bm
|
|
1234
|
+
const tm = this.cfg.hooks!.beforeBMToTM!(bm)
|
|
1238
1235
|
|
|
1239
1236
|
// Validate/convert DBM
|
|
1240
1237
|
return this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
@@ -1327,7 +1324,7 @@ export class CommonDao<
|
|
|
1327
1324
|
|
|
1328
1325
|
async createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void> {
|
|
1329
1326
|
this.requireWriteAccess()
|
|
1330
|
-
await this.cfg.db.createTable(this.cfg.table, schema
|
|
1327
|
+
await this.cfg.db.createTable(this.cfg.table, schema, opt)
|
|
1331
1328
|
}
|
|
1332
1329
|
|
|
1333
1330
|
/**
|
|
@@ -1347,7 +1344,7 @@ export class CommonDao<
|
|
|
1347
1344
|
try {
|
|
1348
1345
|
await fn(daoTx)
|
|
1349
1346
|
} catch (err) {
|
|
1350
|
-
await daoTx.rollback()
|
|
1347
|
+
await daoTx.rollback() // graceful rollback that "never throws"
|
|
1351
1348
|
throw err
|
|
1352
1349
|
}
|
|
1353
1350
|
}, opt)
|
|
@@ -1439,7 +1436,7 @@ export class CommonDaoTransaction {
|
|
|
1439
1436
|
}
|
|
1440
1437
|
}
|
|
1441
1438
|
|
|
1442
|
-
async getById<BM extends
|
|
1439
|
+
async getById<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1443
1440
|
dao: CommonDao<BM, DBM, any>,
|
|
1444
1441
|
id?: string | null,
|
|
1445
1442
|
opt?: CommonDaoOptions,
|
|
@@ -1448,7 +1445,7 @@ export class CommonDaoTransaction {
|
|
|
1448
1445
|
return (await this.getByIds(dao, [id], opt))[0] || null
|
|
1449
1446
|
}
|
|
1450
1447
|
|
|
1451
|
-
async getByIds<BM extends
|
|
1448
|
+
async getByIds<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1452
1449
|
dao: CommonDao<BM, DBM, any>,
|
|
1453
1450
|
ids: string[],
|
|
1454
1451
|
opt?: CommonDaoOptions,
|
|
@@ -1457,7 +1454,7 @@ export class CommonDaoTransaction {
|
|
|
1457
1454
|
}
|
|
1458
1455
|
|
|
1459
1456
|
// todo: Queries inside Transaction are not supported yet
|
|
1460
|
-
// async runQuery<BM extends
|
|
1457
|
+
// async runQuery<BM extends PartialObjectWithId, DBM extends ObjectWithId>(
|
|
1461
1458
|
// dao: CommonDao<BM, DBM, any>,
|
|
1462
1459
|
// q: DBQuery<DBM>,
|
|
1463
1460
|
// opt?: CommonDaoOptions,
|
|
@@ -1470,17 +1467,17 @@ export class CommonDaoTransaction {
|
|
|
1470
1467
|
// }
|
|
1471
1468
|
// }
|
|
1472
1469
|
|
|
1473
|
-
async save<BM extends
|
|
1470
|
+
async save<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1474
1471
|
dao: CommonDao<BM, DBM, any>,
|
|
1475
|
-
bm:
|
|
1472
|
+
bm: BM,
|
|
1476
1473
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1477
1474
|
): Promise<Saved<BM>> {
|
|
1478
1475
|
return (await this.saveBatch(dao, [bm], opt))[0]!
|
|
1479
1476
|
}
|
|
1480
1477
|
|
|
1481
|
-
async saveBatch<BM extends
|
|
1478
|
+
async saveBatch<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1482
1479
|
dao: CommonDao<BM, DBM, any>,
|
|
1483
|
-
bms:
|
|
1480
|
+
bms: BM[],
|
|
1484
1481
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1485
1482
|
): Promise<Saved<BM>[]> {
|
|
1486
1483
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx })
|