@naturalcycles/db-lib 8.60.1 → 9.1.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 (46) 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 +4 -7
  5. package/dist/adapter/file/file.db.js +102 -56
  6. package/dist/adapter/inmemory/inMemory.db.d.ts +32 -3
  7. package/dist/adapter/inmemory/inMemory.db.js +76 -25
  8. package/dist/base.common.db.d.ts +7 -10
  9. package/dist/base.common.db.js +13 -7
  10. package/dist/common.db.d.ts +60 -4
  11. package/dist/common.db.js +23 -0
  12. package/dist/commondao/common.dao.d.ts +28 -9
  13. package/dist/commondao/common.dao.js +72 -71
  14. package/dist/commondao/common.dao.model.d.ts +0 -10
  15. package/dist/db.model.d.ts +29 -1
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +0 -1
  18. package/dist/testing/daoTest.d.ts +2 -2
  19. package/dist/testing/daoTest.js +29 -39
  20. package/dist/testing/dbTest.d.ts +1 -39
  21. package/dist/testing/dbTest.js +41 -50
  22. package/dist/testing/index.d.ts +2 -2
  23. package/dist/timeseries/commonTimeSeriesDao.js +9 -10
  24. package/dist/transaction/dbTransaction.util.d.ts +14 -4
  25. package/dist/transaction/dbTransaction.util.js +49 -22
  26. package/dist/validation/index.js +2 -2
  27. package/package.json +1 -1
  28. package/src/adapter/cachedb/cache.db.model.ts +7 -2
  29. package/src/adapter/cachedb/cache.db.ts +7 -8
  30. package/src/adapter/file/file.db.ts +120 -74
  31. package/src/adapter/inmemory/inMemory.db.ts +101 -24
  32. package/src/base.common.db.ts +22 -11
  33. package/src/common.db.ts +84 -3
  34. package/src/commondao/common.dao.model.ts +0 -11
  35. package/src/commondao/common.dao.ts +102 -91
  36. package/src/db.model.ts +34 -2
  37. package/src/index.ts +0 -1
  38. package/src/testing/daoTest.ts +32 -52
  39. package/src/testing/dbTest.ts +43 -120
  40. package/src/testing/index.ts +2 -12
  41. package/src/timeseries/commonTimeSeriesDao.ts +9 -12
  42. package/src/transaction/dbTransaction.util.ts +61 -23
  43. package/src/validation/index.ts +2 -2
  44. package/dist/transaction/dbTransaction.d.ts +0 -27
  45. package/dist/transaction/dbTransaction.js +0 -64
  46. package/src/transaction/dbTransaction.ts +0 -67
@@ -13,12 +13,12 @@ import {
13
13
  AnyObject,
14
14
  AppError,
15
15
  AsyncMapper,
16
+ CommonLogger,
16
17
  ErrorMode,
17
18
  JsonSchemaObject,
18
19
  JsonSchemaRootObject,
19
20
  ObjectWithId,
20
21
  pMap,
21
- Promisable,
22
22
  Saved,
23
23
  SKIP,
24
24
  UnixTimestampMillisNumber,
@@ -43,16 +43,8 @@ import {
43
43
  writableVoid,
44
44
  } from '@naturalcycles/nodejs-lib'
45
45
  import { DBLibError } from '../cnst'
46
- import {
47
- DBDeleteByIdsOperation,
48
- DBModelType,
49
- DBOperation,
50
- DBPatch,
51
- DBSaveBatchOperation,
52
- RunQueryResult,
53
- } from '../db.model'
46
+ import { DBModelType, DBPatch, DBTransaction, RunQueryResult } from '../db.model'
54
47
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
55
- import { DBTransaction } from '../transaction/dbTransaction'
56
48
  import {
57
49
  CommonDaoCfg,
58
50
  CommonDaoCreateOptions,
@@ -210,7 +202,7 @@ export class CommonDao<
210
202
  const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
211
203
  const table = opt.table || this.cfg.table
212
204
  const started = this.logStarted(op, table)
213
- let dbms = await this.cfg.db.getByIds<DBM>(table, ids)
205
+ let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
214
206
  if (!opt.raw && this.cfg.hooks!.afterLoad && dbms.length) {
215
207
  dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
216
208
  _isTruthy,
@@ -698,68 +690,6 @@ export class CommonDao<
698
690
  return obj as any
699
691
  }
700
692
 
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
693
  // SAVE
764
694
  /**
765
695
  * Mutates with id, created, updated
@@ -778,12 +708,7 @@ export class CommonDao<
778
708
 
779
709
  if (this.cfg.hooks!.beforeSave) {
780
710
  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
711
+ if (dbm === null) return bm as any
787
712
  }
788
713
 
789
714
  const table = opt.table || this.cfg.table
@@ -960,10 +885,6 @@ export class CommonDao<
960
885
  )
961
886
  }
962
887
 
963
- if (opt.tx) {
964
- return dbms as any
965
- }
966
-
967
888
  if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
968
889
  if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
969
890
  opt = { ...opt, saveMethod: 'insert' }
@@ -980,7 +901,7 @@ export class CommonDao<
980
901
  const { excludeFromIndexes } = this.cfg
981
902
  const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds
982
903
 
983
- await this.cfg.db.saveBatch(table, dbms, {
904
+ await (opt.tx || this.cfg.db).saveBatch(table, dbms, {
984
905
  excludeFromIndexes,
985
906
  assignGeneratedIds,
986
907
  ...opt,
@@ -1071,7 +992,7 @@ export class CommonDao<
1071
992
 
1072
993
  if (beforeSave) {
1073
994
  dbm = (await beforeSave(dbm))!
1074
- if (dbm === null && !opt.tx) return SKIP
995
+ if (dbm === null) return SKIP
1075
996
  }
1076
997
 
1077
998
  return dbm
@@ -1118,7 +1039,7 @@ export class CommonDao<
1118
1039
  const op = `deleteById(${id})`
1119
1040
  const table = opt.table || this.cfg.table
1120
1041
  const started = this.logStarted(op, table)
1121
- const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterEq('id', id))
1042
+ const count = await this.cfg.db.deleteByIds(table, [id], opt)
1122
1043
  this.logSaveResult(started, op, table)
1123
1044
  return count
1124
1045
  }
@@ -1130,7 +1051,7 @@ export class CommonDao<
1130
1051
  const op = `deleteByIds(${ids.join(', ')})`
1131
1052
  const table = opt.table || this.cfg.table
1132
1053
  const started = this.logStarted(op, table)
1133
- const count = await this.cfg.db.deleteByQuery(DBQuery.create(table).filterIn('id', ids))
1054
+ const count = await (opt.tx || this.cfg.db).deleteByIds(table, ids, opt)
1134
1055
  this.logSaveResult(started, op, table)
1135
1056
  return count
1136
1057
  }
@@ -1410,11 +1331,17 @@ export class CommonDao<
1410
1331
  await this.cfg.db.ping()
1411
1332
  }
1412
1333
 
1413
- async runInTransaction(ops: Promisable<DBOperation | undefined>[]): Promise<void> {
1414
- const resolvedOps = (await Promise.all(ops)).filter(_isTruthy)
1415
- if (!resolvedOps.length) return
1334
+ async runInTransaction(fn: CommonDaoTransactionFn): Promise<void> {
1335
+ await this.cfg.db.runInTransaction(async tx => {
1336
+ const daoTx = new CommonDaoTransaction(tx, this.cfg.logger!)
1416
1337
 
1417
- await this.cfg.db.commitTransaction(DBTransaction.create(resolvedOps))
1338
+ try {
1339
+ await fn(daoTx)
1340
+ } catch (err) {
1341
+ await daoTx.rollback()
1342
+ throw err
1343
+ }
1344
+ })
1418
1345
  }
1419
1346
 
1420
1347
  protected logResult(started: number, op: string, res: any, table: string): void {
@@ -1473,3 +1400,87 @@ export class CommonDao<
1473
1400
  return Date.now()
1474
1401
  }
1475
1402
  }
1403
+
1404
+ /**
1405
+ * Transaction is committed when the function returns resolved Promise (aka "returns normally").
1406
+ *
1407
+ * Transaction is rolled back when the function returns rejected Promise (aka "throws").
1408
+ */
1409
+ export type CommonDaoTransactionFn = (tx: CommonDaoTransaction) => Promise<void>
1410
+
1411
+ /**
1412
+ * Transaction context.
1413
+ * Has similar API than CommonDao, but all operations are performed in the context of the transaction.
1414
+ */
1415
+ export class CommonDaoTransaction {
1416
+ constructor(
1417
+ private tx: DBTransaction,
1418
+ private logger: CommonLogger,
1419
+ ) {}
1420
+
1421
+ /**
1422
+ * Perform a graceful rollback without throwing/re-throwing any error.
1423
+ */
1424
+ async rollback(): Promise<void> {
1425
+ try {
1426
+ await this.tx.rollback()
1427
+ } catch (err) {
1428
+ // graceful rollback without re-throw
1429
+ this.logger.error(err)
1430
+ }
1431
+ }
1432
+
1433
+ async getById<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1434
+ dao: CommonDao<BM, DBM, any>,
1435
+ id: string,
1436
+ opt?: CommonDaoOptions,
1437
+ ): Promise<Saved<BM> | null> {
1438
+ return (await this.getByIds(dao, [id], opt))[0] || null
1439
+ }
1440
+
1441
+ async getByIds<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1442
+ dao: CommonDao<BM, DBM, any>,
1443
+ ids: string[],
1444
+ opt?: CommonDaoOptions,
1445
+ ): Promise<Saved<BM>[]> {
1446
+ return await dao.getByIds(ids, { ...opt, tx: this.tx })
1447
+ }
1448
+
1449
+ // todo: Queries inside Transaction are not supported yet
1450
+ // async runQuery<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1451
+ // dao: CommonDao<BM, DBM, any>,
1452
+ // q: DBQuery<DBM>,
1453
+ // opt?: CommonDaoOptions,
1454
+ // ): Promise<Saved<BM>[]> {
1455
+ // try {
1456
+ // return await dao.runQuery(q, { ...opt, tx: this.tx })
1457
+ // } catch (err) {
1458
+ // await this.rollback()
1459
+ // throw err
1460
+ // }
1461
+ // }
1462
+
1463
+ async save<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1464
+ dao: CommonDao<BM, DBM, any>,
1465
+ bm: Unsaved<BM>,
1466
+ opt?: CommonDaoSaveBatchOptions<DBM>,
1467
+ ): Promise<Saved<BM>> {
1468
+ return (await this.saveBatch(dao, [bm], opt))[0]!
1469
+ }
1470
+
1471
+ async saveBatch<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1472
+ dao: CommonDao<BM, DBM, any>,
1473
+ bms: Unsaved<BM>[],
1474
+ opt?: CommonDaoSaveBatchOptions<DBM>,
1475
+ ): Promise<Saved<BM>[]> {
1476
+ return await dao.saveBatch(bms, { ...opt, tx: this.tx })
1477
+ }
1478
+
1479
+ async deleteById(dao: CommonDao<any>, id: string, opt?: CommonDaoOptions): Promise<number> {
1480
+ return await this.deleteByIds(dao, [id], opt)
1481
+ }
1482
+
1483
+ async deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number> {
1484
+ return await dao.deleteByIds(ids, { ...opt, tx: this.tx })
1485
+ }
1486
+ }
package/src/db.model.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { ObjectWithId } from '@naturalcycles/js-lib'
1
+ import type { ObjectWithId } from '@naturalcycles/js-lib'
2
+ import { CommonDB } from './common.db'
2
3
 
3
4
  /**
4
5
  * Similar to SQL INSERT, UPDATE.
@@ -10,7 +11,38 @@ import { ObjectWithId } from '@naturalcycles/js-lib'
10
11
  */
11
12
  export type CommonDBSaveMethod = 'upsert' | 'insert' | 'update'
12
13
 
13
- export interface CommonDBOptions {}
14
+ /**
15
+ * Transaction is committed when the function returns resolved Promise (aka "returns normally").
16
+ *
17
+ * Transaction is rolled back when the function returns rejected Promise (aka "throws").
18
+ */
19
+ export type DBTransactionFn = (tx: DBTransaction) => Promise<void>
20
+
21
+ /**
22
+ * Transaction context.
23
+ * Has similar API than CommonDB, but all operations are performed in the context of the transaction.
24
+ */
25
+ export interface DBTransaction {
26
+ getByIds: CommonDB['getByIds']
27
+ saveBatch: CommonDB['saveBatch']
28
+ deleteByIds: CommonDB['deleteByIds']
29
+
30
+ /**
31
+ * Perform a graceful rollback.
32
+ * It'll rollback the transaction and won't throw/re-throw any errors.
33
+ */
34
+ rollback: () => Promise<void>
35
+ }
36
+
37
+ export interface CommonDBOptions {
38
+ /**
39
+ * If passed - the operation will be performed in the context of that DBTransaction.
40
+ * Note that not every type of operation supports Transaction
41
+ * (e.g in Datastore queries cannot be executed inside a Transaction).
42
+ * Also, not every CommonDB implementation supports Transactions.
43
+ */
44
+ tx?: DBTransaction
45
+ }
14
46
 
15
47
  /**
16
48
  * 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'
@@ -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.runInTransaction(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.runInTransaction(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.runInTransaction(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.runInTransaction(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
  })