@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.
Files changed (36) hide show
  1. package/dist/adapter/cachedb/cache.db.d.ts +11 -12
  2. package/dist/adapter/cachedb/cache.db.model.d.ts +2 -2
  3. package/dist/adapter/file/file.db.d.ts +12 -12
  4. package/dist/adapter/file/file.db.model.d.ts +2 -2
  5. package/dist/adapter/file/localFile.persistence.plugin.d.ts +3 -3
  6. package/dist/adapter/file/noop.persistence.plugin.d.ts +2 -2
  7. package/dist/adapter/inmemory/inMemory.db.d.ts +12 -12
  8. package/dist/adapter/inmemory/queryInMemory.d.ts +2 -2
  9. package/dist/base.common.db.d.ts +10 -10
  10. package/dist/common.db.d.ts +10 -10
  11. package/dist/commondao/common.dao.d.ts +24 -25
  12. package/dist/commondao/common.dao.js +10 -10
  13. package/dist/commondao/common.dao.model.d.ts +13 -13
  14. package/dist/db.model.d.ts +4 -4
  15. package/dist/query/dbQuery.d.ts +9 -9
  16. package/dist/testing/test.model.d.ts +3 -4
  17. package/dist/testing/test.model.js +1 -1
  18. package/dist/transaction/dbTransaction.util.d.ts +3 -3
  19. package/dist/validation/index.d.ts +2 -2
  20. package/package.json +1 -1
  21. package/src/adapter/cachedb/cache.db.model.ts +2 -2
  22. package/src/adapter/cachedb/cache.db.ts +18 -16
  23. package/src/adapter/file/file.db.model.ts +2 -2
  24. package/src/adapter/file/file.db.ts +17 -15
  25. package/src/adapter/file/localFile.persistence.plugin.ts +4 -4
  26. package/src/adapter/file/noop.persistence.plugin.ts +2 -2
  27. package/src/adapter/inmemory/inMemory.db.ts +20 -18
  28. package/src/adapter/inmemory/queryInMemory.ts +5 -2
  29. package/src/base.common.db.ts +20 -10
  30. package/src/common.db.ts +20 -13
  31. package/src/commondao/common.dao.model.ts +21 -15
  32. package/src/commondao/common.dao.ts +68 -66
  33. package/src/db.model.ts +4 -4
  34. package/src/query/dbQuery.ts +13 -11
  35. package/src/testing/test.model.ts +4 -6
  36. package/src/transaction/dbTransaction.util.ts +3 -3
package/src/common.db.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib'
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 ObjectWithId>(table: string) => Promise<JsonSchemaRootObject<ROW>>
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 ObjectWithId>(
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 ObjectWithId>(
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 ObjectWithId>(
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 ObjectWithId>(
106
+ runQueryCount: <ROW extends PartialObjectWithId>(
100
107
  q: DBQuery<ROW>,
101
108
  opt?: CommonDBOptions,
102
109
  ) => Promise<number>
103
110
 
104
- streamQuery: <ROW extends ObjectWithId>(
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 Partial<ObjectWithId>>(
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 ObjectWithId>(
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 ObjectWithId>(
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
- ObjectWithId,
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<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId, TM> {
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 Partial<ObjectWithId>,
136
- DBM extends ObjectWithId = Saved<BM>,
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
- created?: boolean
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
- updated?: boolean
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<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>
280
- extends CommonDaoSaveBatchOptions<DBM> {
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 ObjectWithId>
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 ObjectWithId>
316
+ export interface CommonDaoStreamDeleteOptions<DBM extends PartialObjectWithId>
311
317
  extends CommonDaoStreamOptions<DBM> {}
312
318
 
313
- export interface CommonDaoStreamSaveOptions<DBM extends ObjectWithId>
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 Partial<ObjectWithId>,
80
- DBM extends ObjectWithId = Saved<BM>,
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
- created: true,
92
- updated: true,
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 any, opt)
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: BM = this.create({ ...part, id }, opt) as any
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, Saved<BM>>(
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, Saved<BM>>(
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, string>(objectWithId => objectWithId.id, {
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, string>(objectWithId => {
652
+ transformMapSimple<Saved<DBM>, string>(r => {
653
653
  count++
654
- return objectWithId.id
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, opt?: CommonDaoOptions): DBM
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> {
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.created) {
685
+ if (this.cfg.useCreatedProperty) {
684
686
  ;(obj as any)['created'] ||= (obj as any)['updated'] || now
685
687
  }
686
688
 
687
- if (this.cfg.updated) {
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: Unsaved<BM>, opt: CommonDaoSaveOptions<BM, DBM> = {}): Promise<Saved<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 as BM, opt)
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 as any
739
+ bm.id = dbm.id
738
740
  }
739
741
 
740
742
  this.logSaveResult(started, op, table)
741
- return bm as any
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 as BM[], opt)
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 as any))
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 any[]
921
+ return bms as Saved<BM>[]
923
922
  }
924
923
 
925
- async saveBatchAsDBM(dbms: DBM[], opt: CommonDaoSaveBatchOptions<DBM> = {}): Promise<DBM[]> {
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<DBM, string>(objectWithId => objectWithId.id, {
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, opt?: CommonDaoOptions): Promise<Saved<BM>>
1151
- async dbmToBM(_dbm?: DBM, opt: CommonDaoOptions = {}): Promise<Saved<BM> | undefined> {
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, opt: CommonDaoOptions = {}): DBM | undefined {
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 as any)
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 as any, opt)
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 Partial<ObjectWithId>, DBM extends ObjectWithId>(
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 Partial<ObjectWithId>, DBM extends ObjectWithId>(
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 Partial<ObjectWithId>, DBM extends ObjectWithId>(
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 Partial<ObjectWithId>, DBM extends ObjectWithId>(
1475
+ async save<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
1474
1476
  dao: CommonDao<BM, DBM, any>,
1475
- bm: Unsaved<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 Partial<ObjectWithId>, DBM extends ObjectWithId>(
1483
+ async saveBatch<BM extends PartialObjectWithId, DBM extends PartialObjectWithId>(
1482
1484
  dao: CommonDao<BM, DBM, any>,
1483
- bms: Unsaved<BM>[],
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 { ObjectWithId } from '@naturalcycles/js-lib'
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 Partial<ObjectWithId> = any>
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 Partial<ObjectWithId> = any> {
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 Partial<ObjectWithId>> = Partial<
134
+ export type DBPatch<ROW extends PartialObjectWithId> = Partial<
135
135
  Record<keyof ROW, ROW[keyof ROW] | DBIncrement>
136
136
  >