@naturalcycles/db-lib 8.60.0 → 9.0.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 (52) hide show
  1. package/dist/adapter/cachedb/cache.db.d.ts +3 -4
  2. package/dist/adapter/cachedb/cache.db.js +5 -4
  3. package/dist/adapter/cachedb/cache.db.model.d.ts +2 -2
  4. package/dist/adapter/file/file.db.d.ts +15 -7
  5. package/dist/adapter/file/file.db.js +93 -57
  6. package/dist/adapter/file/localFile.persistence.plugin.js +3 -3
  7. package/dist/adapter/inmemory/inMemory.db.d.ts +30 -4
  8. package/dist/adapter/inmemory/inMemory.db.js +89 -33
  9. package/dist/base.common.db.d.ts +7 -10
  10. package/dist/base.common.db.js +11 -7
  11. package/dist/common.db.d.ts +56 -4
  12. package/dist/common.db.js +23 -0
  13. package/dist/commondao/common.dao.d.ts +17 -9
  14. package/dist/commondao/common.dao.js +82 -69
  15. package/dist/commondao/common.dao.model.d.ts +0 -10
  16. package/dist/db.model.d.ts +12 -1
  17. package/dist/index.d.ts +0 -1
  18. package/dist/index.js +0 -1
  19. package/dist/pipeline/dbPipelineBackup.js +4 -4
  20. package/dist/pipeline/dbPipelineRestore.js +2 -2
  21. package/dist/testing/daoTest.d.ts +2 -2
  22. package/dist/testing/daoTest.js +29 -39
  23. package/dist/testing/dbTest.d.ts +1 -39
  24. package/dist/testing/dbTest.js +40 -49
  25. package/dist/testing/index.d.ts +2 -2
  26. package/dist/timeseries/commonTimeSeriesDao.js +5 -6
  27. package/dist/transaction/dbTransaction.util.d.ts +17 -4
  28. package/dist/transaction/dbTransaction.util.js +46 -22
  29. package/dist/validation/index.js +2 -2
  30. package/package.json +1 -1
  31. package/src/adapter/cachedb/cache.db.model.ts +7 -2
  32. package/src/adapter/cachedb/cache.db.ts +7 -8
  33. package/src/adapter/file/file.db.ts +121 -69
  34. package/src/adapter/file/localFile.persistence.plugin.ts +4 -5
  35. package/src/adapter/inmemory/inMemory.db.ts +106 -33
  36. package/src/base.common.db.ts +20 -11
  37. package/src/common.db.ts +80 -3
  38. package/src/commondao/common.dao.model.ts +0 -11
  39. package/src/commondao/common.dao.ts +103 -89
  40. package/src/db.model.ts +15 -2
  41. package/src/index.ts +0 -1
  42. package/src/pipeline/dbPipelineBackup.ts +5 -8
  43. package/src/pipeline/dbPipelineRestore.ts +3 -4
  44. package/src/testing/daoTest.ts +32 -52
  45. package/src/testing/dbTest.ts +42 -119
  46. package/src/testing/index.ts +2 -12
  47. package/src/timeseries/commonTimeSeriesDao.ts +5 -6
  48. package/src/transaction/dbTransaction.util.ts +61 -22
  49. package/src/validation/index.ts +2 -2
  50. package/dist/transaction/dbTransaction.d.ts +0 -27
  51. package/dist/transaction/dbTransaction.js +0 -64
  52. package/src/transaction/dbTransaction.ts +0 -67
@@ -18,7 +18,6 @@ import {
18
18
  JsonSchemaRootObject,
19
19
  ObjectWithId,
20
20
  pMap,
21
- Promisable,
22
21
  Saved,
23
22
  SKIP,
24
23
  UnixTimestampMillisNumber,
@@ -43,16 +42,8 @@ import {
43
42
  writableVoid,
44
43
  } from '@naturalcycles/nodejs-lib'
45
44
  import { DBLibError } from '../cnst'
46
- import {
47
- DBDeleteByIdsOperation,
48
- DBModelType,
49
- DBOperation,
50
- DBPatch,
51
- DBSaveBatchOperation,
52
- RunQueryResult,
53
- } from '../db.model'
45
+ import { DBModelType, DBPatch, DBTransaction, RunQueryResult } from '../db.model'
54
46
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
55
- import { DBTransaction } from '../transaction/dbTransaction'
56
47
  import {
57
48
  CommonDaoCfg,
58
49
  CommonDaoCreateOptions,
@@ -698,68 +689,6 @@ export class CommonDao<
698
689
  return obj as any
699
690
  }
700
691
 
701
- tx = {
702
- save: async (
703
- bm: Unsaved<BM>,
704
- opt: CommonDaoSaveBatchOptions<DBM> = {},
705
- ): Promise<DBSaveBatchOperation | undefined> => {
706
- // .save actually returns DBM (not BM) when it detects `opt.tx === true`
707
- const row: DBM | null = (await this.save(bm, { ...opt, tx: true })) as any
708
- if (row === null) return
709
-
710
- return {
711
- type: 'saveBatch',
712
- table: this.cfg.table,
713
- rows: [row],
714
- opt: {
715
- excludeFromIndexes: this.cfg.excludeFromIndexes,
716
- ...opt,
717
- },
718
- }
719
- },
720
- saveBatch: async (
721
- bms: Unsaved<BM>[],
722
- opt: CommonDaoSaveBatchOptions<DBM> = {},
723
- ): Promise<DBSaveBatchOperation | undefined> => {
724
- const rows: DBM[] = (await this.saveBatch(bms, { ...opt, tx: true })) as any
725
- if (!rows.length) return
726
-
727
- return {
728
- type: 'saveBatch',
729
- table: this.cfg.table,
730
- rows,
731
- opt: {
732
- excludeFromIndexes: this.cfg.excludeFromIndexes,
733
- ...opt,
734
- },
735
- }
736
- },
737
- deleteByIds: async (
738
- ids: string[],
739
- opt: CommonDaoOptions = {},
740
- ): Promise<DBDeleteByIdsOperation | undefined> => {
741
- if (!ids.length) return
742
- return {
743
- type: 'deleteByIds',
744
- table: this.cfg.table,
745
- ids,
746
- opt,
747
- }
748
- },
749
- deleteById: async (
750
- id: string | null | undefined,
751
- opt: CommonDaoOptions = {},
752
- ): Promise<DBDeleteByIdsOperation | undefined> => {
753
- if (!id) return
754
- return {
755
- type: 'deleteByIds',
756
- table: this.cfg.table,
757
- ids: [id],
758
- opt,
759
- }
760
- },
761
- }
762
-
763
692
  // SAVE
764
693
  /**
765
694
  * Mutates with id, created, updated
@@ -778,12 +707,7 @@ export class CommonDao<
778
707
 
779
708
  if (this.cfg.hooks!.beforeSave) {
780
709
  dbm = (await this.cfg.hooks!.beforeSave(dbm))!
781
- if (dbm === null && !opt.tx) return bm as any
782
- }
783
-
784
- if (opt.tx) {
785
- // May return `null`, in which case it'll be skipped
786
- return dbm as any
710
+ if (dbm === null) return bm as any
787
711
  }
788
712
 
789
713
  const table = opt.table || this.cfg.table
@@ -960,10 +884,6 @@ export class CommonDao<
960
884
  )
961
885
  }
962
886
 
963
- if (opt.tx) {
964
- return dbms as any
965
- }
966
-
967
887
  if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
968
888
  if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
969
889
  opt = { ...opt, saveMethod: 'insert' }
@@ -1071,7 +991,7 @@ export class CommonDao<
1071
991
 
1072
992
  if (beforeSave) {
1073
993
  dbm = (await beforeSave(dbm))!
1074
- if (dbm === null && !opt.tx) return SKIP
994
+ if (dbm === null) return SKIP
1075
995
  }
1076
996
 
1077
997
  return dbm
@@ -1118,7 +1038,7 @@ export class CommonDao<
1118
1038
  const op = `deleteById(${id})`
1119
1039
  const table = opt.table || this.cfg.table
1120
1040
  const started = this.logStarted(op, table)
1121
- const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterEq('id', id))
1041
+ const count = await this.cfg.db.deleteByIds(table, [id], opt)
1122
1042
  this.logSaveResult(started, op, table)
1123
1043
  return count
1124
1044
  }
@@ -1130,7 +1050,7 @@ export class CommonDao<
1130
1050
  const op = `deleteByIds(${ids.join(', ')})`
1131
1051
  const table = opt.table || this.cfg.table
1132
1052
  const started = this.logStarted(op, table)
1133
- const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterIn('id', ids))
1053
+ const count = await this.cfg.db.deleteByIds(table, ids, opt)
1134
1054
  this.logSaveResult(started, op, table)
1135
1055
  return count
1136
1056
  }
@@ -1410,11 +1330,22 @@ export class CommonDao<
1410
1330
  await this.cfg.db.ping()
1411
1331
  }
1412
1332
 
1413
- async runInTransaction(ops: Promisable<DBOperation | undefined>[]): Promise<void> {
1414
- const resolvedOps = (await Promise.all(ops)).filter(_isTruthy)
1415
- if (!resolvedOps.length) return
1333
+ async useTransaction(fn: (tx: CommonDaoTransaction) => Promise<void>): Promise<void> {
1334
+ const tx = await this.cfg.db.createTransaction()
1335
+ const daoTx = new CommonDaoTransaction(tx)
1416
1336
 
1417
- await this.cfg.db.commitTransaction(DBTransaction.create(resolvedOps))
1337
+ try {
1338
+ await fn(daoTx)
1339
+ await daoTx.commit()
1340
+ } catch (err) {
1341
+ await daoTx.rollback()
1342
+ throw err
1343
+ }
1344
+ }
1345
+
1346
+ async createTransaction(): Promise<CommonDaoTransaction> {
1347
+ const tx = await this.cfg.db.createTransaction()
1348
+ return new CommonDaoTransaction(tx)
1418
1349
  }
1419
1350
 
1420
1351
  protected logResult(started: number, op: string, res: any, table: string): void {
@@ -1473,3 +1404,86 @@ export class CommonDao<
1473
1404
  return Date.now()
1474
1405
  }
1475
1406
  }
1407
+
1408
+ export class CommonDaoTransaction {
1409
+ constructor(private tx: DBTransaction) {}
1410
+
1411
+ async commit(): Promise<void> {
1412
+ await this.tx.commit()
1413
+ }
1414
+ async rollback(): Promise<void> {
1415
+ try {
1416
+ await this.tx.rollback()
1417
+ } catch (err) {
1418
+ console.log(err)
1419
+ }
1420
+ }
1421
+
1422
+ async getById<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1423
+ dao: CommonDao<BM, DBM, any>,
1424
+ id: string,
1425
+ opt?: CommonDaoOptions,
1426
+ ): Promise<Saved<BM> | null> {
1427
+ return (await this.getByIds(dao, [id], opt))[0] || null
1428
+ }
1429
+
1430
+ async getByIds<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1431
+ dao: CommonDao<BM, DBM, any>,
1432
+ ids: string[],
1433
+ opt?: CommonDaoOptions,
1434
+ ): Promise<Saved<BM>[]> {
1435
+ try {
1436
+ return await dao.getByIds(ids, { ...opt, tx: this.tx })
1437
+ } catch (err) {
1438
+ await this.rollback()
1439
+ throw err
1440
+ }
1441
+ }
1442
+
1443
+ async runQuery<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1444
+ dao: CommonDao<BM, DBM, any>,
1445
+ q: DBQuery<DBM>,
1446
+ opt?: CommonDaoOptions,
1447
+ ): Promise<Saved<BM>[]> {
1448
+ try {
1449
+ return await dao.runQuery(q, { ...opt, tx: this.tx })
1450
+ } catch (err) {
1451
+ await this.rollback()
1452
+ throw err
1453
+ }
1454
+ }
1455
+
1456
+ async save<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1457
+ dao: CommonDao<BM, DBM, any>,
1458
+ bm: Unsaved<BM>,
1459
+ opt?: CommonDaoSaveBatchOptions<DBM>,
1460
+ ): Promise<Saved<BM>> {
1461
+ return (await this.saveBatch(dao, [bm], opt))[0]!
1462
+ }
1463
+
1464
+ async saveBatch<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1465
+ dao: CommonDao<BM, DBM, any>,
1466
+ bms: Unsaved<BM>[],
1467
+ opt?: CommonDaoSaveBatchOptions<DBM>,
1468
+ ): Promise<Saved<BM>[]> {
1469
+ try {
1470
+ return await dao.saveBatch(bms, { ...opt, tx: this.tx })
1471
+ } catch (err) {
1472
+ await this.rollback()
1473
+ throw err
1474
+ }
1475
+ }
1476
+
1477
+ async deleteById(dao: CommonDao<any>, id: string, opt?: CommonDaoOptions): Promise<number> {
1478
+ return await this.deleteByIds(dao, [id], opt)
1479
+ }
1480
+
1481
+ async deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number> {
1482
+ try {
1483
+ return await dao.deleteByIds(ids, { ...opt, tx: this.tx })
1484
+ } catch (err) {
1485
+ await this.rollback()
1486
+ throw err
1487
+ }
1488
+ }
1489
+ }
package/src/db.model.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ObjectWithId } from '@naturalcycles/js-lib'
1
+ import type { ObjectWithId } from '@naturalcycles/js-lib'
2
2
 
3
3
  /**
4
4
  * Similar to SQL INSERT, UPDATE.
@@ -10,7 +10,20 @@ import { ObjectWithId } from '@naturalcycles/js-lib'
10
10
  */
11
11
  export type CommonDBSaveMethod = 'upsert' | 'insert' | 'update'
12
12
 
13
- export interface CommonDBOptions {}
13
+ export interface DBTransaction {
14
+ commit: () => Promise<void>
15
+ rollback: () => Promise<void>
16
+ }
17
+
18
+ export interface CommonDBOptions {
19
+ /**
20
+ * If passed - the operation will be performed in the context of that DBTransaction.
21
+ * Note that not every type of operation supports Transaction
22
+ * (e.g in Datastore queries cannot be executed inside a Transaction).
23
+ * Also, not every CommonDB implementation supports Transactions.
24
+ */
25
+ tx?: DBTransaction
26
+ }
14
27
 
15
28
  /**
16
29
  * All properties default to undefined.
package/src/index.ts CHANGED
@@ -13,6 +13,5 @@ export * from './pipeline/dbPipelineBackup'
13
13
  export * from './pipeline/dbPipelineCopy'
14
14
  export * from './pipeline/dbPipelineRestore'
15
15
  export * from './query/dbQuery'
16
- export * from './transaction/dbTransaction'
17
16
  export * from './transaction/dbTransaction.util'
18
17
  export * from './kv/commonKeyValueDaoMemoCache'
@@ -20,14 +20,11 @@ import {
20
20
  transformTap,
21
21
  transformToNDJson,
22
22
  _pipeline,
23
- _ensureDirSync,
24
- _pathExistsSync,
25
- _ensureFileSync,
26
- _writeJson,
27
23
  boldWhite,
28
24
  dimWhite,
29
25
  grey,
30
26
  yellow,
27
+ fs2,
31
28
  } from '@naturalcycles/nodejs-lib'
32
29
  import { CommonDB } from '../common.db'
33
30
  import { DBQuery } from '../index'
@@ -180,7 +177,7 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
180
177
 
181
178
  console.log(`>> ${dimWhite('dbPipelineBackup')} started in ${grey(outputDirPath)}...`)
182
179
 
183
- _ensureDirSync(outputDirPath)
180
+ fs2.ensureDir(outputDirPath)
184
181
 
185
182
  tables ||= await db.getTables()
186
183
 
@@ -213,20 +210,20 @@ export async function dbPipelineBackup(opt: DBPipelineBackupOptions): Promise<ND
213
210
  const filePath = `${outputDirPath}/${table}.ndjson` + (gzip ? '.gz' : '')
214
211
  const schemaFilePath = `${outputDirPath}/${table}.schema.json`
215
212
 
216
- if (protectFromOverwrite && _pathExistsSync(filePath)) {
213
+ if (protectFromOverwrite && fs2.pathExists(filePath)) {
217
214
  throw new AppError(`dbPipelineBackup: output file exists: ${filePath}`)
218
215
  }
219
216
 
220
217
  const started = Date.now()
221
218
  let rows = 0
222
219
 
223
- _ensureFileSync(filePath)
220
+ fs2.ensureFile(filePath)
224
221
 
225
222
  // console.log(`>> ${grey(filePath)} started...`)
226
223
 
227
224
  if (emitSchemaFromDB) {
228
225
  const schema = await db.getTableSchema(table)
229
- await _writeJson(schemaFilePath, schema, { spaces: 2 })
226
+ await fs2.writeJsonAsync(schemaFilePath, schema, { spaces: 2 })
230
227
  console.log(`>> ${grey(schemaFilePath)} saved (generated from DB)`)
231
228
  }
232
229
 
@@ -25,12 +25,11 @@ import {
25
25
  transformTap,
26
26
  writableForEach,
27
27
  _pipeline,
28
- _ensureDirSync,
29
- _readJson,
30
28
  boldWhite,
31
29
  dimWhite,
32
30
  grey,
33
31
  yellow,
32
+ fs2,
34
33
  } from '@naturalcycles/nodejs-lib'
35
34
  import { CommonDB } from '../common.db'
36
35
  import { CommonDBSaveOptions } from '../index'
@@ -145,7 +144,7 @@ export async function dbPipelineRestore(opt: DBPipelineRestoreOptions): Promise<
145
144
  `>> ${dimWhite('dbPipelineRestore')} started in ${grey(inputDirPath)}...${sinceUpdatedStr}`,
146
145
  )
147
146
 
148
- _ensureDirSync(inputDirPath)
147
+ fs2.ensureDir(inputDirPath)
149
148
 
150
149
  const tablesToGzip = new Set<string>()
151
150
  const sizeByTable: Record<string, number> = {}
@@ -185,7 +184,7 @@ export async function dbPipelineRestore(opt: DBPipelineRestoreOptions): Promise<
185
184
  return
186
185
  }
187
186
 
188
- const schema = await _readJson<JsonSchemaObject<any>>(schemaFilePath)
187
+ const schema = await fs2.readJsonAsync<JsonSchemaObject<any>>(schemaFilePath)
189
188
  await db.createTable(table, schema, { dropIfExists: true })
190
189
  })
191
190
  }
@@ -1,10 +1,10 @@
1
1
  import { Readable } from 'node:stream'
2
- import { pDelay, _deepCopy, _pick, _sortBy, _omit, localTimeNow } from '@naturalcycles/js-lib'
2
+ import { _deepCopy, _pick, _sortBy, _omit, localTimeNow } from '@naturalcycles/js-lib'
3
3
  import { _pipeline, readableToArray, transformNoOp } from '@naturalcycles/nodejs-lib'
4
4
  import { CommonDaoLogLevel, DBQuery } from '..'
5
5
  import { CommonDB } from '../common.db'
6
6
  import { CommonDao } from '../commondao/common.dao'
7
- import { CommonDBImplementationFeatures, CommonDBImplementationQuirks, expectMatch } from './dbTest'
7
+ import { CommonDBImplementationQuirks, expectMatch } from './dbTest'
8
8
  import {
9
9
  createTestItemsBM,
10
10
  testItemBMSchema,
@@ -16,11 +16,8 @@ import {
16
16
  } from './test.model'
17
17
  import { TestItemBM } from '.'
18
18
 
19
- export function runCommonDaoTest(
20
- db: CommonDB,
21
- features: CommonDBImplementationFeatures = {},
22
- quirks: CommonDBImplementationQuirks = {},
23
- ): void {
19
+ export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQuirks = {}): void {
20
+ const { support } = db
24
21
  const dao = new CommonDao({
25
22
  table: TEST_TABLE,
26
23
  db,
@@ -31,26 +28,6 @@ export function runCommonDaoTest(
31
28
  logLevel: CommonDaoLogLevel.DATA_FULL,
32
29
  })
33
30
 
34
- const {
35
- querying = true,
36
- // tableSchemas = true,
37
- createTable = true,
38
- dbQueryFilter = true,
39
- // dbQueryFilterIn = true,
40
- dbQueryOrder = true,
41
- dbQuerySelectFields = true,
42
- streaming = true,
43
- strongConsistency = true,
44
- nullValues = true,
45
- transactions = true,
46
- } = features
47
-
48
- // const {
49
- // allowExtraPropertiesInResponse,
50
- // allowBooleansAsUndefined,
51
- // } = quirks
52
- const eventualConsistencyDelay = !strongConsistency && quirks.eventualConsistencyDelay
53
-
54
31
  const items = createTestItemsBM(3)
55
32
  const itemsClone = _deepCopy(items)
56
33
  // deepFreeze(items) // mutation of id/created/updated is allowed now! (even expected)
@@ -66,13 +43,13 @@ export function runCommonDaoTest(
66
43
  })
67
44
 
68
45
  // CREATE TABLE, DROP
69
- if (createTable) {
46
+ if (support.createTable) {
70
47
  test('createTable, dropIfExists=true', async () => {
71
48
  await dao.createTable(testItemDBMJsonSchema, { dropIfExists: true })
72
49
  })
73
50
  }
74
51
 
75
- if (querying) {
52
+ if (support.queries) {
76
53
  // DELETE ALL initially
77
54
  test('deleteByIds test items', async () => {
78
55
  const rows = await dao.query().select(['id']).runQuery()
@@ -87,7 +64,6 @@ export function runCommonDaoTest(
87
64
 
88
65
  // QUERY empty
89
66
  test('runQuery(all), runQueryCount should return empty', async () => {
90
- if (eventualConsistencyDelay) await pDelay(eventualConsistencyDelay)
91
67
  expect(await dao.query().runQuery()).toEqual([])
92
68
  expect(await dao.query().runQueryCount()).toBe(0)
93
69
  })
@@ -109,7 +85,7 @@ export function runCommonDaoTest(
109
85
  })
110
86
 
111
87
  // SAVE
112
- if (nullValues) {
88
+ if (support.nullValues) {
113
89
  test('should allow to save and load null values', async () => {
114
90
  const item3 = {
115
91
  ...createTestItemBM(3),
@@ -168,15 +144,14 @@ export function runCommonDaoTest(
168
144
  })
169
145
 
170
146
  // QUERY
171
- if (querying) {
147
+ if (support.queries) {
172
148
  test('runQuery(all) should return all items', async () => {
173
- if (eventualConsistencyDelay) await pDelay(eventualConsistencyDelay)
174
149
  let rows = await dao.query().runQuery()
175
150
  rows = _sortBy(rows, r => r.id)
176
151
  expectMatch(expectedItems, rows, quirks)
177
152
  })
178
153
 
179
- if (dbQueryFilter) {
154
+ if (support.dbQueryFilter) {
180
155
  test('query even=true', async () => {
181
156
  let rows = await dao.query().filter('even', '==', true).runQuery()
182
157
  rows = _sortBy(rows, r => r.id)
@@ -188,14 +163,14 @@ export function runCommonDaoTest(
188
163
  })
189
164
  }
190
165
 
191
- if (dbQueryOrder) {
166
+ if (support.dbQueryOrder) {
192
167
  test('query order by k1 desc', async () => {
193
168
  const rows = await dao.query().order('k1', true).runQuery()
194
169
  expectMatch([...expectedItems].reverse(), rows, quirks)
195
170
  })
196
171
  }
197
172
 
198
- if (dbQuerySelectFields) {
173
+ if (support.dbQuerySelectFields) {
199
174
  test('projection query with only ids', async () => {
200
175
  let rows = await dao.query().select(['id']).runQuery()
201
176
  rows = _sortBy(rows, r => r.id)
@@ -213,7 +188,7 @@ export function runCommonDaoTest(
213
188
  }
214
189
 
215
190
  // STREAM
216
- if (streaming) {
191
+ if (support.streaming) {
217
192
  test('streamQueryForEach all', async () => {
218
193
  let rows: TestItemBM[] = []
219
194
  await dao.query().streamQueryForEach(bm => void rows.push(bm))
@@ -269,11 +244,10 @@ export function runCommonDaoTest(
269
244
  }
270
245
 
271
246
  // DELETE BY
272
- if (querying) {
247
+ if (support.queries) {
273
248
  test('deleteByQuery even=false', async () => {
274
249
  const deleted = await dao.query().filter('even', '==', false).deleteByQuery()
275
250
  expect(deleted).toBe(items.filter(item => !item.even).length)
276
- if (eventualConsistencyDelay) await pDelay(eventualConsistencyDelay)
277
251
  expect(await dao.query().runQueryCount()).toBe(1)
278
252
  })
279
253
 
@@ -283,14 +257,18 @@ export function runCommonDaoTest(
283
257
  })
284
258
  }
285
259
 
286
- if (transactions) {
260
+ if (support.transactions) {
287
261
  test('transaction happy path', async () => {
288
262
  // cleanup
289
263
  await dao.query().deleteByQuery()
290
264
 
291
265
  // Test that id, created, updated are created
292
266
  const now = localTimeNow().unix()
293
- await dao.runInTransaction([dao.tx.save(_omit(item1, ['id', 'created', 'updated']))])
267
+
268
+ await dao.useTransaction(async tx => {
269
+ const row = _omit(item1, ['id', 'created', 'updated'])
270
+ await tx.save(dao, row)
271
+ })
294
272
 
295
273
  const loaded = await dao.query().runQuery()
296
274
  expect(loaded.length).toBe(1)
@@ -298,17 +276,19 @@ export function runCommonDaoTest(
298
276
  expect(loaded[0]!.created).toBeGreaterThanOrEqual(now)
299
277
  expect(loaded[0]!.updated).toBe(loaded[0]!.created)
300
278
 
301
- await dao.runInTransaction([dao.tx.deleteById(loaded[0]!.id)])
279
+ await dao.useTransaction(async tx => {
280
+ await tx.deleteById(dao, loaded[0]!.id)
281
+ })
302
282
 
303
283
  // saveBatch [item1, 2, 3]
304
284
  // save item3 with k1: k1_mod
305
285
  // delete item2
306
286
  // remaining: item1, item3_with_k1_mod
307
- await dao.runInTransaction([
308
- dao.tx.saveBatch(items),
309
- dao.tx.save({ ...items[2]!, k1: 'k1_mod' }),
310
- dao.tx.deleteById(items[1]!.id),
311
- ])
287
+ await dao.useTransaction(async tx => {
288
+ await tx.saveBatch(dao, items)
289
+ await tx.save(dao, { ...items[2]!, k1: 'k1_mod' })
290
+ await tx.deleteById(dao, items[1]!.id)
291
+ })
312
292
 
313
293
  const rows = await dao.query().runQuery()
314
294
  const expected = [items[0], { ...items[2]!, k1: 'k1_mod' }]
@@ -317,10 +297,10 @@ export function runCommonDaoTest(
317
297
 
318
298
  test('transaction rollback', async () => {
319
299
  await expect(
320
- dao.runInTransaction([
321
- dao.tx.deleteById(items[2]!.id),
322
- dao.tx.save({ ...items[0]!, k1: 5 as any }), // it should fail here
323
- ]),
300
+ dao.useTransaction(async tx => {
301
+ await tx.deleteById(dao, items[2]!.id)
302
+ await tx.save(dao, { ...items[0]!, k1: 5 as any }) // it should fail here
303
+ }),
324
304
  ).rejects.toThrow()
325
305
 
326
306
  const rows = await dao.query().runQuery()
@@ -328,7 +308,7 @@ export function runCommonDaoTest(
328
308
  expectMatch(expected, rows, quirks)
329
309
  })
330
310
 
331
- if (querying) {
311
+ if (support.queries) {
332
312
  test('transaction cleanup', async () => {
333
313
  await dao.query().deleteByQuery()
334
314
  })