@naturalcycles/db-lib 9.2.1 → 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 +24 -25
- package/dist/commondao/common.dao.js +10 -10
- 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 +68 -66
- 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,
|
|
@@ -76,8 +76,8 @@ const isCI = !!process.env['CI']
|
|
|
76
76
|
* TM = Transport model (optimized to be sent over the wire)
|
|
77
77
|
*/
|
|
78
78
|
export class CommonDao<
|
|
79
|
-
BM extends
|
|
80
|
-
DBM extends
|
|
79
|
+
BM extends PartialObjectWithId,
|
|
80
|
+
DBM extends PartialObjectWithId = BM,
|
|
81
81
|
TM extends AnyObject = BM,
|
|
82
82
|
> {
|
|
83
83
|
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
@@ -88,8 +88,8 @@ export class CommonDao<
|
|
|
88
88
|
logLevel: isGAE || isCI ? CommonDaoLogLevel.NONE : CommonDaoLogLevel.OPERATIONS,
|
|
89
89
|
createId: true,
|
|
90
90
|
assignGeneratedIds: false,
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
useCreatedProperty: true,
|
|
92
|
+
useUpdatedProperty: true,
|
|
93
93
|
logger: console,
|
|
94
94
|
...cfg,
|
|
95
95
|
hooks: {
|
|
@@ -116,7 +116,7 @@ export class CommonDao<
|
|
|
116
116
|
create(part: Partial<BM> = {}, opt: CommonDaoOptions = {}): Saved<BM> {
|
|
117
117
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
118
118
|
// First assignIdCreatedUpdated, then validate!
|
|
119
|
-
this.assignIdCreatedUpdated(bm as
|
|
119
|
+
this.assignIdCreatedUpdated(bm as BM, opt)
|
|
120
120
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
121
121
|
}
|
|
122
122
|
|
|
@@ -154,17 +154,17 @@ export class CommonDao<
|
|
|
154
154
|
id: string,
|
|
155
155
|
part: Partial<BM> = {},
|
|
156
156
|
opt?: CommonDaoOptions,
|
|
157
|
-
): Promise<DBM
|
|
157
|
+
): Promise<Saved<DBM>> {
|
|
158
158
|
const dbm = await this.getByIdAsDBM(id, opt)
|
|
159
159
|
if (dbm) return dbm
|
|
160
160
|
|
|
161
|
-
const bm
|
|
161
|
+
const bm = this.create({ ...part, id }, opt)
|
|
162
162
|
return await this.bmToDBM(bm, opt)
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
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> {
|
|
166
|
+
async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<Saved<DBM> | null>
|
|
167
|
+
async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<Saved<DBM> | null> {
|
|
168
168
|
if (!id) return null
|
|
169
169
|
const op = `getByIdAsDBM(${id})`
|
|
170
170
|
const table = opt.table || this.cfg.table
|
|
@@ -220,7 +220,7 @@ export class CommonDao<
|
|
|
220
220
|
return bms
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
223
|
+
async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
224
224
|
if (!ids.length) return []
|
|
225
225
|
const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
226
226
|
const table = opt.table || this.cfg.table
|
|
@@ -244,7 +244,7 @@ export class CommonDao<
|
|
|
244
244
|
return r
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<DBM
|
|
247
|
+
async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<Saved<DBM>> {
|
|
248
248
|
const r = await this.getByIdAsDBM(id, opt)
|
|
249
249
|
if (!r) {
|
|
250
250
|
this.throwRequiredError(id, opt)
|
|
@@ -282,7 +282,7 @@ export class CommonDao<
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
private async ensureUniqueId(table: string, dbm: DBM): Promise<void> {
|
|
285
|
+
private async ensureUniqueId(table: string, dbm: Saved<DBM>): Promise<void> {
|
|
286
286
|
// todo: retry N times
|
|
287
287
|
const existing = await this.cfg.db.getByIds<DBM>(table, [dbm.id])
|
|
288
288
|
if (existing.length) {
|
|
@@ -366,7 +366,7 @@ export class CommonDao<
|
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]> {
|
|
369
|
+
async runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<DBM>[]> {
|
|
370
370
|
const { rows } = await this.runQueryExtendedAsDBM(q, opt)
|
|
371
371
|
return rows
|
|
372
372
|
}
|
|
@@ -374,7 +374,7 @@ export class CommonDao<
|
|
|
374
374
|
async runQueryExtendedAsDBM(
|
|
375
375
|
q: DBQuery<DBM>,
|
|
376
376
|
opt: CommonDaoOptions = {},
|
|
377
|
-
): Promise<RunQueryResult<DBM
|
|
377
|
+
): Promise<RunQueryResult<Saved<DBM>>> {
|
|
378
378
|
q.table = opt.table || q.table
|
|
379
379
|
const op = `runQueryAsDBM(${q.pretty()})`
|
|
380
380
|
const started = this.logStarted(op, q.table)
|
|
@@ -448,7 +448,7 @@ export class CommonDao<
|
|
|
448
448
|
|
|
449
449
|
await _pipeline([
|
|
450
450
|
this.cfg.db.streamQuery<DBM>(q, opt),
|
|
451
|
-
transformMap<DBM
|
|
451
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
452
452
|
async dbm => {
|
|
453
453
|
count++
|
|
454
454
|
if (partialQuery || opt.raw) return dbm as any
|
|
@@ -548,7 +548,7 @@ export class CommonDao<
|
|
|
548
548
|
return stream
|
|
549
549
|
.on('error', err => stream.emit('error', err))
|
|
550
550
|
.pipe(
|
|
551
|
-
transformMap<any, DBM
|
|
551
|
+
transformMap<any, Saved<DBM>>(
|
|
552
552
|
async dbm => {
|
|
553
553
|
if (this.cfg.hooks!.afterLoad) {
|
|
554
554
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -593,7 +593,7 @@ export class CommonDao<
|
|
|
593
593
|
// .pipe(transformMap<DBM, Saved<BM>>(dbm => this.dbmToBM(dbm, opt), safeOpt))
|
|
594
594
|
.on('error', err => stream.emit('error', err))
|
|
595
595
|
.pipe(
|
|
596
|
-
transformMap<DBM
|
|
596
|
+
transformMap<Saved<DBM>, Saved<BM>>(
|
|
597
597
|
async dbm => {
|
|
598
598
|
if (this.cfg.hooks!.afterLoad) {
|
|
599
599
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -627,7 +627,7 @@ export class CommonDao<
|
|
|
627
627
|
.streamQuery<DBM>(q.select(['id']), opt)
|
|
628
628
|
.on('error', err => stream.emit('error', err))
|
|
629
629
|
.pipe(
|
|
630
|
-
transformMapSimple<DBM
|
|
630
|
+
transformMapSimple<Saved<DBM>, string>(r => r.id, {
|
|
631
631
|
errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
|
|
632
632
|
}),
|
|
633
633
|
)
|
|
@@ -649,9 +649,9 @@ export class CommonDao<
|
|
|
649
649
|
|
|
650
650
|
await _pipeline([
|
|
651
651
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
652
|
-
transformMapSimple<DBM
|
|
652
|
+
transformMapSimple<Saved<DBM>, string>(r => {
|
|
653
653
|
count++
|
|
654
|
-
return
|
|
654
|
+
return r.id
|
|
655
655
|
}),
|
|
656
656
|
transformMap<string, void>(mapper, {
|
|
657
657
|
...opt,
|
|
@@ -674,17 +674,19 @@ export class CommonDao<
|
|
|
674
674
|
* Mutates!
|
|
675
675
|
* "Returns", just to have a type of "Saved"
|
|
676
676
|
*/
|
|
677
|
-
assignIdCreatedUpdated(obj: DBM
|
|
678
|
-
assignIdCreatedUpdated(obj: BM
|
|
679
|
-
assignIdCreatedUpdated(
|
|
680
|
-
|
|
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>> {
|
|
681
683
|
const now = Math.floor(Date.now() / 1000)
|
|
682
684
|
|
|
683
|
-
if (this.cfg.
|
|
685
|
+
if (this.cfg.useCreatedProperty) {
|
|
684
686
|
;(obj as any)['created'] ||= (obj as any)['updated'] || now
|
|
685
687
|
}
|
|
686
688
|
|
|
687
|
-
if (this.cfg.
|
|
689
|
+
if (this.cfg.useUpdatedProperty) {
|
|
688
690
|
;(obj as any)['updated'] =
|
|
689
691
|
opt.preserveUpdatedCreated && (obj as any)['updated'] ? (obj as any)['updated'] : now
|
|
690
692
|
}
|
|
@@ -700,7 +702,7 @@ export class CommonDao<
|
|
|
700
702
|
/**
|
|
701
703
|
* Mutates with id, created, updated
|
|
702
704
|
*/
|
|
703
|
-
async save(bm:
|
|
705
|
+
async save(bm: BM, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<Saved<BM>> {
|
|
704
706
|
this.requireWriteAccess()
|
|
705
707
|
|
|
706
708
|
if (opt.skipIfEquals && _deepJsonEquals(bm, opt.skipIfEquals)) {
|
|
@@ -710,7 +712,7 @@ export class CommonDao<
|
|
|
710
712
|
|
|
711
713
|
const idWasGenerated = !bm.id && this.cfg.createId
|
|
712
714
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
713
|
-
let dbm = await this.bmToDBM(bm
|
|
715
|
+
let dbm = await this.bmToDBM(bm, opt)
|
|
714
716
|
|
|
715
717
|
if (this.cfg.hooks!.beforeSave) {
|
|
716
718
|
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
@@ -734,11 +736,11 @@ export class CommonDao<
|
|
|
734
736
|
})
|
|
735
737
|
|
|
736
738
|
if (assignGeneratedIds) {
|
|
737
|
-
bm.id = dbm.id
|
|
739
|
+
bm.id = dbm.id
|
|
738
740
|
}
|
|
739
741
|
|
|
740
742
|
this.logSaveResult(started, op, table)
|
|
741
|
-
return bm as
|
|
743
|
+
return bm as Saved<BM>
|
|
742
744
|
}
|
|
743
745
|
|
|
744
746
|
/**
|
|
@@ -835,13 +837,13 @@ export class CommonDao<
|
|
|
835
837
|
return await this.save(bm, opt)
|
|
836
838
|
}
|
|
837
839
|
|
|
838
|
-
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM
|
|
840
|
+
async saveAsDBM(dbm: DBM, opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<DBM>> {
|
|
839
841
|
this.requireWriteAccess()
|
|
840
842
|
const table = opt.table || this.cfg.table
|
|
841
843
|
|
|
842
844
|
// assigning id in case it misses the id
|
|
843
845
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
844
|
-
let row = dbm
|
|
846
|
+
let row = dbm as Saved<DBM>
|
|
845
847
|
if (!opt.raw) {
|
|
846
848
|
const idWasGenerated = !dbm.id && this.cfg.createId
|
|
847
849
|
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
@@ -858,7 +860,7 @@ export class CommonDao<
|
|
|
858
860
|
|
|
859
861
|
if (this.cfg.hooks!.beforeSave) {
|
|
860
862
|
row = (await this.cfg.hooks!.beforeSave(row))!
|
|
861
|
-
if (row === null) return dbm
|
|
863
|
+
if (row === null) return dbm as Saved<DBM>
|
|
862
864
|
}
|
|
863
865
|
|
|
864
866
|
await this.cfg.db.saveBatch(table, [row], {
|
|
@@ -875,15 +877,12 @@ export class CommonDao<
|
|
|
875
877
|
return row
|
|
876
878
|
}
|
|
877
879
|
|
|
878
|
-
async saveBatch(
|
|
879
|
-
bms: Unsaved<BM>[],
|
|
880
|
-
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
881
|
-
): Promise<Saved<BM>[]> {
|
|
880
|
+
async saveBatch(bms: BM[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<Saved<BM>[]> {
|
|
882
881
|
if (!bms.length) return []
|
|
883
882
|
this.requireWriteAccess()
|
|
884
883
|
const table = opt.table || this.cfg.table
|
|
885
884
|
bms.forEach(bm => this.assignIdCreatedUpdated(bm, opt))
|
|
886
|
-
let dbms = await this.bmsToDBM(bms
|
|
885
|
+
let dbms = await this.bmsToDBM(bms, opt)
|
|
887
886
|
|
|
888
887
|
if (this.cfg.hooks!.beforeSave && dbms.length) {
|
|
889
888
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.beforeSave!(dbm))).filter(
|
|
@@ -914,22 +913,25 @@ export class CommonDao<
|
|
|
914
913
|
})
|
|
915
914
|
|
|
916
915
|
if (assignGeneratedIds) {
|
|
917
|
-
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id
|
|
916
|
+
dbms.forEach((dbm, i) => (bms[i]!.id = dbm.id))
|
|
918
917
|
}
|
|
919
918
|
|
|
920
919
|
this.logSaveResult(started, op, table)
|
|
921
920
|
|
|
922
|
-
return bms as
|
|
921
|
+
return bms as Saved<BM>[]
|
|
923
922
|
}
|
|
924
923
|
|
|
925
|
-
async saveBatchAsDBM(
|
|
924
|
+
async saveBatchAsDBM(
|
|
925
|
+
dbms: DBM[],
|
|
926
|
+
opt: CommonDaoSaveBatchOptions<DBM> = {},
|
|
927
|
+
): Promise<Saved<DBM>[]> {
|
|
926
928
|
if (!dbms.length) return []
|
|
927
929
|
this.requireWriteAccess()
|
|
928
930
|
const table = opt.table || this.cfg.table
|
|
929
|
-
let rows = dbms
|
|
931
|
+
let rows = dbms as Saved<DBM>[]
|
|
930
932
|
if (!opt.raw) {
|
|
931
933
|
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
932
|
-
rows = this.anyToDBMs(dbms, opt)
|
|
934
|
+
rows = this.anyToDBMs(dbms as Saved<DBM>[], opt)
|
|
933
935
|
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
934
936
|
}
|
|
935
937
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
@@ -990,7 +992,7 @@ export class CommonDao<
|
|
|
990
992
|
const { batchSize = 500, batchConcurrency = 16, errorMode } = opt
|
|
991
993
|
|
|
992
994
|
return [
|
|
993
|
-
transformMap<BM, DBM
|
|
995
|
+
transformMap<BM, Saved<DBM>>(
|
|
994
996
|
async bm => {
|
|
995
997
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
996
998
|
|
|
@@ -1083,7 +1085,7 @@ export class CommonDao<
|
|
|
1083
1085
|
|
|
1084
1086
|
await _pipeline([
|
|
1085
1087
|
this.cfg.db.streamQuery<DBM>(q.select(['id']), opt),
|
|
1086
|
-
transformMapSimple<
|
|
1088
|
+
transformMapSimple<ObjectWithId, string>(r => r.id, {
|
|
1087
1089
|
errorMode: ErrorMode.SUPPRESS,
|
|
1088
1090
|
}),
|
|
1089
1091
|
transformBuffer<string>({ batchSize }),
|
|
@@ -1147,13 +1149,13 @@ export class CommonDao<
|
|
|
1147
1149
|
// CONVERSIONS
|
|
1148
1150
|
|
|
1149
1151
|
async dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>
|
|
1150
|
-
async dbmToBM(_dbm?: DBM
|
|
1151
|
-
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> {
|
|
1152
1154
|
if (!_dbm) return
|
|
1153
1155
|
|
|
1154
1156
|
// optimization: no need to run full joi DBM validation, cause BM validation will be run
|
|
1155
1157
|
// const dbm = this.anyToDBM(_dbm, opt)
|
|
1156
|
-
let dbm: DBM = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1158
|
+
let dbm: Saved<DBM> = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
|
|
1157
1159
|
|
|
1158
1160
|
if (opt.anonymize) {
|
|
1159
1161
|
dbm = this.cfg.hooks!.anonymize!(dbm)
|
|
@@ -1167,7 +1169,7 @@ export class CommonDao<
|
|
|
1167
1169
|
return this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1168
1170
|
}
|
|
1169
1171
|
|
|
1170
|
-
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1172
|
+
async dbmsToBM(dbms: Saved<DBM>[], opt: CommonDaoOptions = {}): Promise<Saved<BM>[]> {
|
|
1171
1173
|
return await pMap(dbms, async dbm => await this.dbmToBM(dbm, opt))
|
|
1172
1174
|
}
|
|
1173
1175
|
|
|
@@ -1176,8 +1178,8 @@ export class CommonDao<
|
|
|
1176
1178
|
* Returns DBM (new reference).
|
|
1177
1179
|
*/
|
|
1178
1180
|
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> {
|
|
1181
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM>>
|
|
1182
|
+
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<Saved<DBM> | undefined> {
|
|
1181
1183
|
if (bm === undefined) return
|
|
1182
1184
|
|
|
1183
1185
|
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
@@ -1196,14 +1198,14 @@ export class CommonDao<
|
|
|
1196
1198
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1197
1199
|
}
|
|
1198
1200
|
|
|
1199
|
-
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
1201
|
+
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<Saved<DBM>[]> {
|
|
1200
1202
|
// try/catch?
|
|
1201
1203
|
return await pMap(bms, async bm => await this.bmToDBM(bm, opt))
|
|
1202
1204
|
}
|
|
1203
1205
|
|
|
1204
1206
|
anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined
|
|
1205
|
-
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM
|
|
1206
|
-
anyToDBM(dbm?: DBM
|
|
1207
|
+
anyToDBM(dbm?: any, opt?: CommonDaoOptions): Saved<DBM>
|
|
1208
|
+
anyToDBM(dbm?: Saved<DBM>, opt: CommonDaoOptions = {}): Saved<DBM> | undefined {
|
|
1207
1209
|
if (!dbm) return
|
|
1208
1210
|
|
|
1209
1211
|
// this shouldn't be happening on load! but should on save!
|
|
@@ -1219,7 +1221,7 @@ export class CommonDao<
|
|
|
1219
1221
|
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1220
1222
|
}
|
|
1221
1223
|
|
|
1222
|
-
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}): DBM[] {
|
|
1224
|
+
anyToDBMs(entities: Saved<DBM>[], opt: CommonDaoOptions = {}): Saved<DBM>[] {
|
|
1223
1225
|
return entities.map(entity => this.anyToDBM(entity, opt))
|
|
1224
1226
|
}
|
|
1225
1227
|
|
|
@@ -1234,7 +1236,7 @@ export class CommonDao<
|
|
|
1234
1236
|
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1235
1237
|
|
|
1236
1238
|
// BM > TM
|
|
1237
|
-
const tm = this.cfg.hooks!.beforeBMToTM!(bm
|
|
1239
|
+
const tm = this.cfg.hooks!.beforeBMToTM!(bm)
|
|
1238
1240
|
|
|
1239
1241
|
// Validate/convert DBM
|
|
1240
1242
|
return this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
@@ -1327,7 +1329,7 @@ export class CommonDao<
|
|
|
1327
1329
|
|
|
1328
1330
|
async createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void> {
|
|
1329
1331
|
this.requireWriteAccess()
|
|
1330
|
-
await this.cfg.db.createTable(this.cfg.table, schema
|
|
1332
|
+
await this.cfg.db.createTable(this.cfg.table, schema, opt)
|
|
1331
1333
|
}
|
|
1332
1334
|
|
|
1333
1335
|
/**
|
|
@@ -1347,7 +1349,7 @@ export class CommonDao<
|
|
|
1347
1349
|
try {
|
|
1348
1350
|
await fn(daoTx)
|
|
1349
1351
|
} catch (err) {
|
|
1350
|
-
await daoTx.rollback()
|
|
1352
|
+
await daoTx.rollback() // graceful rollback that "never throws"
|
|
1351
1353
|
throw err
|
|
1352
1354
|
}
|
|
1353
1355
|
}, opt)
|
|
@@ -1439,7 +1441,7 @@ export class CommonDaoTransaction {
|
|
|
1439
1441
|
}
|
|
1440
1442
|
}
|
|
1441
1443
|
|
|
1442
|
-
async getById<BM extends
|
|
1444
|
+
async getById<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1443
1445
|
dao: CommonDao<BM, DBM, any>,
|
|
1444
1446
|
id?: string | null,
|
|
1445
1447
|
opt?: CommonDaoOptions,
|
|
@@ -1448,7 +1450,7 @@ export class CommonDaoTransaction {
|
|
|
1448
1450
|
return (await this.getByIds(dao, [id], opt))[0] || null
|
|
1449
1451
|
}
|
|
1450
1452
|
|
|
1451
|
-
async getByIds<BM extends
|
|
1453
|
+
async getByIds<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1452
1454
|
dao: CommonDao<BM, DBM, any>,
|
|
1453
1455
|
ids: string[],
|
|
1454
1456
|
opt?: CommonDaoOptions,
|
|
@@ -1457,7 +1459,7 @@ export class CommonDaoTransaction {
|
|
|
1457
1459
|
}
|
|
1458
1460
|
|
|
1459
1461
|
// todo: Queries inside Transaction are not supported yet
|
|
1460
|
-
// async runQuery<BM extends
|
|
1462
|
+
// async runQuery<BM extends PartialObjectWithId, DBM extends ObjectWithId>(
|
|
1461
1463
|
// dao: CommonDao<BM, DBM, any>,
|
|
1462
1464
|
// q: DBQuery<DBM>,
|
|
1463
1465
|
// opt?: CommonDaoOptions,
|
|
@@ -1470,17 +1472,17 @@ export class CommonDaoTransaction {
|
|
|
1470
1472
|
// }
|
|
1471
1473
|
// }
|
|
1472
1474
|
|
|
1473
|
-
async save<BM extends
|
|
1475
|
+
async save<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1474
1476
|
dao: CommonDao<BM, DBM, any>,
|
|
1475
|
-
bm:
|
|
1477
|
+
bm: BM,
|
|
1476
1478
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1477
1479
|
): Promise<Saved<BM>> {
|
|
1478
1480
|
return (await this.saveBatch(dao, [bm], opt))[0]!
|
|
1479
1481
|
}
|
|
1480
1482
|
|
|
1481
|
-
async saveBatch<BM extends
|
|
1483
|
+
async saveBatch<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
|
|
1482
1484
|
dao: CommonDao<BM, DBM, any>,
|
|
1483
|
-
bms:
|
|
1485
|
+
bms: BM[],
|
|
1484
1486
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1485
1487
|
): Promise<Saved<BM>[]> {
|
|
1486
1488
|
return await dao.saveBatch(bms, { ...opt, tx: this.tx })
|
package/src/db.model.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PartialObjectWithId } from '@naturalcycles/js-lib'
|
|
2
2
|
import { CommonDB } from './common.db'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -55,7 +55,7 @@ export interface CommonDBOptions {
|
|
|
55
55
|
/**
|
|
56
56
|
* All properties default to undefined.
|
|
57
57
|
*/
|
|
58
|
-
export interface CommonDBSaveOptions<ROW extends
|
|
58
|
+
export interface CommonDBSaveOptions<ROW extends PartialObjectWithId = any>
|
|
59
59
|
extends CommonDBOptions {
|
|
60
60
|
excludeFromIndexes?: (keyof ROW)[]
|
|
61
61
|
|
|
@@ -91,7 +91,7 @@ export interface RunQueryResult<T> {
|
|
|
91
91
|
|
|
92
92
|
export type DBOperation = DBSaveBatchOperation | DBDeleteByIdsOperation
|
|
93
93
|
|
|
94
|
-
export interface DBSaveBatchOperation<ROW extends
|
|
94
|
+
export interface DBSaveBatchOperation<ROW extends PartialObjectWithId = any> {
|
|
95
95
|
type: 'saveBatch'
|
|
96
96
|
table: string
|
|
97
97
|
rows: ROW[]
|
|
@@ -131,6 +131,6 @@ export class DBIncrement {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
export type DBPatch<ROW extends
|
|
134
|
+
export type DBPatch<ROW extends PartialObjectWithId> = Partial<
|
|
135
135
|
Record<keyof ROW, ROW[keyof ROW] | DBIncrement>
|
|
136
136
|
>
|