@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
package/dist/common.db.js CHANGED
@@ -1,2 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.commonDBFullSupport = exports.CommonDBType = void 0;
4
+ var CommonDBType;
5
+ (function (CommonDBType) {
6
+ CommonDBType["document"] = "document";
7
+ CommonDBType["relational"] = "relational";
8
+ })(CommonDBType || (exports.CommonDBType = CommonDBType = {}));
9
+ exports.commonDBFullSupport = {
10
+ queries: true,
11
+ dbQueryFilter: true,
12
+ dbQueryFilterIn: true,
13
+ dbQueryOrder: true,
14
+ dbQuerySelectFields: true,
15
+ insertSaveMethod: true,
16
+ updateSaveMethod: true,
17
+ updateByQuery: true,
18
+ dbIncrement: true,
19
+ createTable: true,
20
+ tableSchemas: true,
21
+ streaming: true,
22
+ bufferValues: true,
23
+ nullValues: true,
24
+ transactions: true,
25
+ };
@@ -1,8 +1,8 @@
1
1
  /// <reference types="node" />
2
2
  import { Transform } from 'node:stream';
3
- import { AnyObject, AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Promisable, Saved, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
3
+ import { AnyObject, AsyncMapper, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Saved, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
4
4
  import { AjvSchema, ObjectSchema, ReadableTyped } from '@naturalcycles/nodejs-lib';
5
- import { DBDeleteByIdsOperation, DBModelType, DBOperation, DBPatch, DBSaveBatchOperation, RunQueryResult } from '../db.model';
5
+ import { DBModelType, DBPatch, DBTransaction, RunQueryResult } from '../db.model';
6
6
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
7
7
  import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveBatchOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
8
8
  /**
@@ -85,12 +85,6 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
85
85
  assignIdCreatedUpdated(obj: DBM, opt?: CommonDaoOptions): DBM;
86
86
  assignIdCreatedUpdated(obj: BM, opt?: CommonDaoOptions): Saved<BM>;
87
87
  assignIdCreatedUpdated(obj: Unsaved<BM>, opt?: CommonDaoOptions): Saved<BM>;
88
- tx: {
89
- save: (bm: Unsaved<BM>, opt?: CommonDaoSaveBatchOptions<DBM>) => Promise<DBSaveBatchOperation | undefined>;
90
- saveBatch: (bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>) => Promise<DBSaveBatchOperation | undefined>;
91
- deleteByIds: (ids: string[], opt?: CommonDaoOptions) => Promise<DBDeleteByIdsOperation | undefined>;
92
- deleteById: (id: string | null | undefined, opt?: CommonDaoOptions) => Promise<DBDeleteByIdsOperation | undefined>;
93
- };
94
88
  /**
95
89
  * Mutates with id, created, updated
96
90
  */
@@ -175,9 +169,34 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
175
169
  * Proxy to this.cfg.db.ping
176
170
  */
177
171
  ping(): Promise<void>;
178
- runInTransaction(ops: Promisable<DBOperation | undefined>[]): Promise<void>;
172
+ runInTransaction(fn: CommonDaoTransactionFn): Promise<void>;
179
173
  protected logResult(started: number, op: string, res: any, table: string): void;
180
174
  protected logSaveResult(started: number, op: string, table: string): void;
181
175
  protected logStarted(op: string, table: string, force?: boolean): UnixTimestampMillisNumber;
182
176
  protected logSaveStarted(op: string, items: any, table: string): UnixTimestampMillisNumber;
183
177
  }
178
+ /**
179
+ * Transaction is committed when the function returns resolved Promise (aka "returns normally").
180
+ *
181
+ * Transaction is rolled back when the function returns rejected Promise (aka "throws").
182
+ */
183
+ export type CommonDaoTransactionFn = (tx: CommonDaoTransaction) => Promise<void>;
184
+ /**
185
+ * Transaction context.
186
+ * Has similar API than CommonDao, but all operations are performed in the context of the transaction.
187
+ */
188
+ export declare class CommonDaoTransaction {
189
+ private tx;
190
+ private logger;
191
+ constructor(tx: DBTransaction, logger: CommonLogger);
192
+ /**
193
+ * Perform a graceful rollback without throwing/re-throwing any error.
194
+ */
195
+ rollback(): Promise<void>;
196
+ getById<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(dao: CommonDao<BM, DBM, any>, id: string, opt?: CommonDaoOptions): Promise<Saved<BM> | null>;
197
+ getByIds<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(dao: CommonDao<BM, DBM, any>, ids: string[], opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
198
+ save<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(dao: CommonDao<BM, DBM, any>, bm: Unsaved<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>>;
199
+ saveBatch<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(dao: CommonDao<BM, DBM, any>, bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<Saved<BM>[]>;
200
+ deleteById(dao: CommonDao<any>, id: string, opt?: CommonDaoOptions): Promise<number>;
201
+ deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number>;
202
+ }
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CommonDao = void 0;
3
+ exports.CommonDaoTransaction = exports.CommonDao = void 0;
4
4
  const js_lib_1 = require("@naturalcycles/js-lib");
5
5
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
6
6
  const cnst_1 = require("../cnst");
7
7
  const db_model_1 = require("../db.model");
8
8
  const dbQuery_1 = require("../query/dbQuery");
9
- const dbTransaction_1 = require("../transaction/dbTransaction");
10
9
  const common_dao_model_1 = require("./common.dao.model");
11
10
  const isGAE = !!process.env['GAE_INSTANCE'];
12
11
  const isCI = !!process.env['CI'];
@@ -20,57 +19,6 @@ const isCI = !!process.env['CI'];
20
19
  class CommonDao {
21
20
  constructor(cfg) {
22
21
  this.cfg = cfg;
23
- this.tx = {
24
- save: async (bm, opt = {}) => {
25
- // .save actually returns DBM (not BM) when it detects `opt.tx === true`
26
- const row = (await this.save(bm, { ...opt, tx: true }));
27
- if (row === null)
28
- return;
29
- return {
30
- type: 'saveBatch',
31
- table: this.cfg.table,
32
- rows: [row],
33
- opt: {
34
- excludeFromIndexes: this.cfg.excludeFromIndexes,
35
- ...opt,
36
- },
37
- };
38
- },
39
- saveBatch: async (bms, opt = {}) => {
40
- const rows = (await this.saveBatch(bms, { ...opt, tx: true }));
41
- if (!rows.length)
42
- return;
43
- return {
44
- type: 'saveBatch',
45
- table: this.cfg.table,
46
- rows,
47
- opt: {
48
- excludeFromIndexes: this.cfg.excludeFromIndexes,
49
- ...opt,
50
- },
51
- };
52
- },
53
- deleteByIds: async (ids, opt = {}) => {
54
- if (!ids.length)
55
- return;
56
- return {
57
- type: 'deleteByIds',
58
- table: this.cfg.table,
59
- ids,
60
- opt,
61
- };
62
- },
63
- deleteById: async (id, opt = {}) => {
64
- if (!id)
65
- return;
66
- return {
67
- type: 'deleteByIds',
68
- table: this.cfg.table,
69
- ids: [id],
70
- opt,
71
- };
72
- },
73
- };
74
22
  this.cfg = {
75
23
  // Default is to NOT log in AppEngine and in CI,
76
24
  // otherwise to log Operations
@@ -176,7 +124,7 @@ class CommonDao {
176
124
  const op = `getByIds ${ids.length} id(s) (${(0, js_lib_1._truncate)(ids.slice(0, 10).join(', '), 50)})`;
177
125
  const table = opt.table || this.cfg.table;
178
126
  const started = this.logStarted(op, table);
179
- let dbms = await this.cfg.db.getByIds(table, ids);
127
+ let dbms = await (opt.tx || this.cfg.db).getByIds(table, ids);
180
128
  if (!opt.raw && this.cfg.hooks.afterLoad && dbms.length) {
181
129
  dbms = (await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
182
130
  }
@@ -562,13 +510,9 @@ class CommonDao {
562
510
  let dbm = await this.bmToDBM(bm, opt);
563
511
  if (this.cfg.hooks.beforeSave) {
564
512
  dbm = (await this.cfg.hooks.beforeSave(dbm));
565
- if (dbm === null && !opt.tx)
513
+ if (dbm === null)
566
514
  return bm;
567
515
  }
568
- if (opt.tx) {
569
- // May return `null`, in which case it'll be skipped
570
- return dbm;
571
- }
572
516
  const table = opt.table || this.cfg.table;
573
517
  if (opt.ensureUniqueId && idWasGenerated)
574
518
  await this.ensureUniqueId(table, dbm);
@@ -706,9 +650,6 @@ class CommonDao {
706
650
  if (this.cfg.hooks.beforeSave && dbms.length) {
707
651
  dbms = (await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.cfg.hooks.beforeSave(dbm))).filter(js_lib_1._isTruthy);
708
652
  }
709
- if (opt.tx) {
710
- return dbms;
711
- }
712
653
  if (opt.ensureUniqueId)
713
654
  throw new js_lib_1.AppError('ensureUniqueId is not supported in saveBatch');
714
655
  if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
@@ -721,7 +662,7 @@ class CommonDao {
721
662
  const started = this.logSaveStarted(op, bms, table);
722
663
  const { excludeFromIndexes } = this.cfg;
723
664
  const assignGeneratedIds = opt.assignGeneratedIds || this.cfg.assignGeneratedIds;
724
- await this.cfg.db.saveBatch(table, dbms, {
665
+ await (opt.tx || this.cfg.db).saveBatch(table, dbms, {
725
666
  excludeFromIndexes,
726
667
  assignGeneratedIds,
727
668
  ...opt,
@@ -792,7 +733,7 @@ class CommonDao {
792
733
  let dbm = await this.bmToDBM(bm, opt);
793
734
  if (beforeSave) {
794
735
  dbm = (await beforeSave(dbm));
795
- if (dbm === null && !opt.tx)
736
+ if (dbm === null)
796
737
  return js_lib_1.SKIP;
797
738
  }
798
739
  return dbm;
@@ -828,7 +769,7 @@ class CommonDao {
828
769
  const op = `deleteById(${id})`;
829
770
  const table = opt.table || this.cfg.table;
830
771
  const started = this.logStarted(op, table);
831
- const count = await this.cfg.db.deleteByQuery(dbQuery_1.DBQuery.create(table).filterEq('id', id));
772
+ const count = await this.cfg.db.deleteByIds(table, [id], opt);
832
773
  this.logSaveResult(started, op, table);
833
774
  return count;
834
775
  }
@@ -840,7 +781,7 @@ class CommonDao {
840
781
  const op = `deleteByIds(${ids.join(', ')})`;
841
782
  const table = opt.table || this.cfg.table;
842
783
  const started = this.logStarted(op, table);
843
- const count = await this.cfg.db.deleteByQuery(dbQuery_1.DBQuery.create(table).filterIn('id', ids));
784
+ const count = await (opt.tx || this.cfg.db).deleteByIds(table, ids, opt);
844
785
  this.logSaveResult(started, op, table);
845
786
  return count;
846
787
  }
@@ -1050,11 +991,17 @@ class CommonDao {
1050
991
  async ping() {
1051
992
  await this.cfg.db.ping();
1052
993
  }
1053
- async runInTransaction(ops) {
1054
- const resolvedOps = (await Promise.all(ops)).filter(js_lib_1._isTruthy);
1055
- if (!resolvedOps.length)
1056
- return;
1057
- await this.cfg.db.commitTransaction(dbTransaction_1.DBTransaction.create(resolvedOps));
994
+ async runInTransaction(fn) {
995
+ await this.cfg.db.runInTransaction(async (tx) => {
996
+ const daoTx = new CommonDaoTransaction(tx, this.cfg.logger);
997
+ try {
998
+ await fn(daoTx);
999
+ }
1000
+ catch (err) {
1001
+ await daoTx.rollback();
1002
+ throw err;
1003
+ }
1004
+ });
1058
1005
  }
1059
1006
  logResult(started, op, res, table) {
1060
1007
  if (!this.cfg.logLevel)
@@ -1111,3 +1058,57 @@ class CommonDao {
1111
1058
  }
1112
1059
  }
1113
1060
  exports.CommonDao = CommonDao;
1061
+ /**
1062
+ * Transaction context.
1063
+ * Has similar API than CommonDao, but all operations are performed in the context of the transaction.
1064
+ */
1065
+ class CommonDaoTransaction {
1066
+ constructor(tx, logger) {
1067
+ this.tx = tx;
1068
+ this.logger = logger;
1069
+ }
1070
+ /**
1071
+ * Perform a graceful rollback without throwing/re-throwing any error.
1072
+ */
1073
+ async rollback() {
1074
+ try {
1075
+ await this.tx.rollback();
1076
+ }
1077
+ catch (err) {
1078
+ // graceful rollback without re-throw
1079
+ this.logger.error(err);
1080
+ }
1081
+ }
1082
+ async getById(dao, id, opt) {
1083
+ return (await this.getByIds(dao, [id], opt))[0] || null;
1084
+ }
1085
+ async getByIds(dao, ids, opt) {
1086
+ return await dao.getByIds(ids, { ...opt, tx: this.tx });
1087
+ }
1088
+ // todo: Queries inside Transaction are not supported yet
1089
+ // async runQuery<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId>(
1090
+ // dao: CommonDao<BM, DBM, any>,
1091
+ // q: DBQuery<DBM>,
1092
+ // opt?: CommonDaoOptions,
1093
+ // ): Promise<Saved<BM>[]> {
1094
+ // try {
1095
+ // return await dao.runQuery(q, { ...opt, tx: this.tx })
1096
+ // } catch (err) {
1097
+ // await this.rollback()
1098
+ // throw err
1099
+ // }
1100
+ // }
1101
+ async save(dao, bm, opt) {
1102
+ return (await this.saveBatch(dao, [bm], opt))[0];
1103
+ }
1104
+ async saveBatch(dao, bms, opt) {
1105
+ return await dao.saveBatch(bms, { ...opt, tx: this.tx });
1106
+ }
1107
+ async deleteById(dao, id, opt) {
1108
+ return await this.deleteByIds(dao, [id], opt);
1109
+ }
1110
+ async deleteByIds(dao, ids, opt) {
1111
+ return await dao.deleteByIds(ids, { ...opt, tx: this.tx });
1112
+ }
1113
+ }
1114
+ exports.CommonDaoTransaction = CommonDaoTransaction;
@@ -222,16 +222,6 @@ export interface CommonDaoOptions extends CommonDBOptions {
222
222
  * Useful e.g in AirtableDB where you can have one Dao to control multiple tables.
223
223
  */
224
224
  table?: string;
225
- /**
226
- * If passed - operation will not be performed immediately, but instead "added" to the transaction.
227
- * In the end - transaction needs to be committed (by calling `commit`).
228
- * This API is inspired by Datastore API.
229
- *
230
- * Only applicable to save* and delete* operations
231
- *
232
- * @experimental
233
- */
234
- tx?: boolean;
235
225
  }
236
226
  export interface CommonDaoSaveOptions<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId> extends CommonDaoSaveBatchOptions<DBM> {
237
227
  /**
@@ -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
  * Similar to SQL INSERT, UPDATE.
4
5
  * Insert will fail if row already exists.
@@ -8,7 +9,34 @@ import { ObjectWithId } from '@naturalcycles/js-lib';
8
9
  * Default is Upsert.
9
10
  */
10
11
  export type CommonDBSaveMethod = 'upsert' | 'insert' | 'update';
12
+ /**
13
+ * Transaction is committed when the function returns resolved Promise (aka "returns normally").
14
+ *
15
+ * Transaction is rolled back when the function returns rejected Promise (aka "throws").
16
+ */
17
+ export type DBTransactionFn = (tx: DBTransaction) => Promise<void>;
18
+ /**
19
+ * Transaction context.
20
+ * Has similar API than CommonDB, but all operations are performed in the context of the transaction.
21
+ */
22
+ export interface DBTransaction {
23
+ getByIds: CommonDB['getByIds'];
24
+ saveBatch: CommonDB['saveBatch'];
25
+ deleteByIds: CommonDB['deleteByIds'];
26
+ /**
27
+ * Perform a graceful rollback.
28
+ * It'll rollback the transaction and won't throw/re-throw any errors.
29
+ */
30
+ rollback: () => Promise<void>;
31
+ }
11
32
  export interface CommonDBOptions {
33
+ /**
34
+ * If passed - the operation will be performed in the context of that DBTransaction.
35
+ * Note that not every type of operation supports Transaction
36
+ * (e.g in Datastore queries cannot be executed inside a Transaction).
37
+ * Also, not every CommonDB implementation supports Transactions.
38
+ */
39
+ tx?: DBTransaction;
12
40
  }
13
41
  /**
14
42
  * All properties default to undefined.
package/dist/index.d.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';
package/dist/index.js CHANGED
@@ -16,6 +16,5 @@ tslib_1.__exportStar(require("./pipeline/dbPipelineBackup"), exports);
16
16
  tslib_1.__exportStar(require("./pipeline/dbPipelineCopy"), exports);
17
17
  tslib_1.__exportStar(require("./pipeline/dbPipelineRestore"), exports);
18
18
  tslib_1.__exportStar(require("./query/dbQuery"), exports);
19
- tslib_1.__exportStar(require("./transaction/dbTransaction"), exports);
20
19
  tslib_1.__exportStar(require("./transaction/dbTransaction.util"), exports);
21
20
  tslib_1.__exportStar(require("./kv/commonKeyValueDaoMemoCache"), exports);
@@ -1,3 +1,3 @@
1
1
  import { CommonDB } from '../common.db';
2
- import { CommonDBImplementationFeatures, CommonDBImplementationQuirks } from './dbTest';
3
- export declare function runCommonDaoTest(db: CommonDB, features?: CommonDBImplementationFeatures, quirks?: CommonDBImplementationQuirks): void;
2
+ import { CommonDBImplementationQuirks } from './dbTest';
3
+ export declare function runCommonDaoTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): void;
@@ -8,7 +8,8 @@ const __1 = require("..");
8
8
  const common_dao_1 = require("../commondao/common.dao");
9
9
  const dbTest_1 = require("./dbTest");
10
10
  const test_model_1 = require("./test.model");
11
- function runCommonDaoTest(db, features = {}, quirks = {}) {
11
+ function runCommonDaoTest(db, quirks = {}) {
12
+ const { support } = db;
12
13
  const dao = new common_dao_1.CommonDao({
13
14
  table: test_model_1.TEST_TABLE,
14
15
  db,
@@ -18,16 +19,6 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
18
19
  logStarted: true,
19
20
  logLevel: __1.CommonDaoLogLevel.DATA_FULL,
20
21
  });
21
- const { querying = true,
22
- // tableSchemas = true,
23
- createTable = true, dbQueryFilter = true,
24
- // dbQueryFilterIn = true,
25
- dbQueryOrder = true, dbQuerySelectFields = true, streaming = true, strongConsistency = true, nullValues = true, transactions = true, } = features;
26
- // const {
27
- // allowExtraPropertiesInResponse,
28
- // allowBooleansAsUndefined,
29
- // } = quirks
30
- const eventualConsistencyDelay = !strongConsistency && quirks.eventualConsistencyDelay;
31
22
  const items = (0, test_model_1.createTestItemsBM)(3);
32
23
  const itemsClone = (0, js_lib_1._deepCopy)(items);
33
24
  // deepFreeze(items) // mutation of id/created/updated is allowed now! (even expected)
@@ -40,12 +31,12 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
40
31
  await dao.ping();
41
32
  });
42
33
  // CREATE TABLE, DROP
43
- if (createTable) {
34
+ if (support.createTable) {
44
35
  test('createTable, dropIfExists=true', async () => {
45
36
  await dao.createTable(test_model_1.testItemDBMJsonSchema, { dropIfExists: true });
46
37
  });
47
38
  }
48
- if (querying) {
39
+ if (support.queries) {
49
40
  // DELETE ALL initially
50
41
  test('deleteByIds test items', async () => {
51
42
  const rows = await dao.query().select(['id']).runQuery();
@@ -53,8 +44,6 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
53
44
  });
54
45
  // QUERY empty
55
46
  test('runQuery(all), runQueryCount should return empty', async () => {
56
- if (eventualConsistencyDelay)
57
- await (0, js_lib_1.pDelay)(eventualConsistencyDelay);
58
47
  expect(await dao.query().runQuery()).toEqual([]);
59
48
  expect(await dao.query().runQueryCount()).toBe(0);
60
49
  });
@@ -72,7 +61,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
72
61
  expect(await dao.getByIds(['abc', 'abcd'])).toEqual([]);
73
62
  });
74
63
  // SAVE
75
- if (nullValues) {
64
+ if (support.nullValues) {
76
65
  test('should allow to save and load null values', async () => {
77
66
  const item3 = {
78
67
  ...(0, test_model_1.createTestItemBM)(3),
@@ -118,28 +107,26 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
118
107
  (0, dbTest_1.expectMatch)(expectedItems, (0, js_lib_1._sortBy)(rows, r => r.id), quirks);
119
108
  });
120
109
  // QUERY
121
- if (querying) {
110
+ if (support.queries) {
122
111
  test('runQuery(all) should return all items', async () => {
123
- if (eventualConsistencyDelay)
124
- await (0, js_lib_1.pDelay)(eventualConsistencyDelay);
125
112
  let rows = await dao.query().runQuery();
126
113
  rows = (0, js_lib_1._sortBy)(rows, r => r.id);
127
114
  (0, dbTest_1.expectMatch)(expectedItems, rows, quirks);
128
115
  });
129
- if (dbQueryFilter) {
116
+ if (support.dbQueryFilter) {
130
117
  test('query even=true', async () => {
131
118
  let rows = await dao.query().filter('even', '==', true).runQuery();
132
119
  rows = (0, js_lib_1._sortBy)(rows, r => r.id);
133
120
  (0, dbTest_1.expectMatch)(expectedItems.filter(i => i.even), rows, quirks);
134
121
  });
135
122
  }
136
- if (dbQueryOrder) {
123
+ if (support.dbQueryOrder) {
137
124
  test('query order by k1 desc', async () => {
138
125
  const rows = await dao.query().order('k1', true).runQuery();
139
126
  (0, dbTest_1.expectMatch)([...expectedItems].reverse(), rows, quirks);
140
127
  });
141
128
  }
142
- if (dbQuerySelectFields) {
129
+ if (support.dbQuerySelectFields) {
143
130
  test('projection query with only ids', async () => {
144
131
  let rows = await dao.query().select(['id']).runQuery();
145
132
  rows = (0, js_lib_1._sortBy)(rows, r => r.id);
@@ -151,7 +138,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
151
138
  });
152
139
  }
153
140
  // STREAM
154
- if (streaming) {
141
+ if (support.streaming) {
155
142
  test('streamQueryForEach all', async () => {
156
143
  let rows = [];
157
144
  await dao.query().streamQueryForEach(bm => void rows.push(bm));
@@ -187,12 +174,10 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
187
174
  });
188
175
  }
189
176
  // DELETE BY
190
- if (querying) {
177
+ if (support.queries) {
191
178
  test('deleteByQuery even=false', async () => {
192
179
  const deleted = await dao.query().filter('even', '==', false).deleteByQuery();
193
180
  expect(deleted).toBe(items.filter(item => !item.even).length);
194
- if (eventualConsistencyDelay)
195
- await (0, js_lib_1.pDelay)(eventualConsistencyDelay);
196
181
  expect(await dao.query().runQueryCount()).toBe(1);
197
182
  });
198
183
  test('cleanup', async () => {
@@ -200,42 +185,47 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
200
185
  await dao.query().deleteByQuery();
201
186
  });
202
187
  }
203
- if (transactions) {
188
+ if (support.transactions) {
204
189
  test('transaction happy path', async () => {
205
190
  // cleanup
206
191
  await dao.query().deleteByQuery();
207
192
  // Test that id, created, updated are created
208
193
  const now = (0, js_lib_1.localTimeNow)().unix();
209
- await dao.runInTransaction([dao.tx.save((0, js_lib_1._omit)(item1, ['id', 'created', 'updated']))]);
194
+ await dao.runInTransaction(async (tx) => {
195
+ const row = (0, js_lib_1._omit)(item1, ['id', 'created', 'updated']);
196
+ await tx.save(dao, row);
197
+ });
210
198
  const loaded = await dao.query().runQuery();
211
199
  expect(loaded.length).toBe(1);
212
200
  expect(loaded[0].id).toBeDefined();
213
201
  expect(loaded[0].created).toBeGreaterThanOrEqual(now);
214
202
  expect(loaded[0].updated).toBe(loaded[0].created);
215
- await dao.runInTransaction([dao.tx.deleteById(loaded[0].id)]);
203
+ await dao.runInTransaction(async (tx) => {
204
+ await tx.deleteById(dao, loaded[0].id);
205
+ });
216
206
  // saveBatch [item1, 2, 3]
217
207
  // save item3 with k1: k1_mod
218
208
  // delete item2
219
209
  // remaining: item1, item3_with_k1_mod
220
- await dao.runInTransaction([
221
- dao.tx.saveBatch(items),
222
- dao.tx.save({ ...items[2], k1: 'k1_mod' }),
223
- dao.tx.deleteById(items[1].id),
224
- ]);
210
+ await dao.runInTransaction(async (tx) => {
211
+ await tx.saveBatch(dao, items);
212
+ await tx.save(dao, { ...items[2], k1: 'k1_mod' });
213
+ await tx.deleteById(dao, items[1].id);
214
+ });
225
215
  const rows = await dao.query().runQuery();
226
216
  const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
227
217
  (0, dbTest_1.expectMatch)(expected, rows, quirks);
228
218
  });
229
219
  test('transaction rollback', async () => {
230
- await expect(dao.runInTransaction([
231
- dao.tx.deleteById(items[2].id),
232
- dao.tx.save({ ...items[0], k1: 5 }), // it should fail here
233
- ])).rejects.toThrow();
220
+ await expect(dao.runInTransaction(async (tx) => {
221
+ await tx.deleteById(dao, items[2].id);
222
+ await tx.save(dao, { ...items[0], k1: 5 }); // it should fail here
223
+ })).rejects.toThrow();
234
224
  const rows = await dao.query().runQuery();
235
225
  const expected = [items[0], { ...items[2], k1: 'k1_mod' }];
236
226
  (0, dbTest_1.expectMatch)(expected, rows, quirks);
237
227
  });
238
- if (querying) {
228
+ if (support.queries) {
239
229
  test('transaction cleanup', async () => {
240
230
  await dao.query().deleteByQuery();
241
231
  });
@@ -1,43 +1,8 @@
1
1
  import { CommonDB } from '../common.db';
2
- export interface CommonDBImplementationFeatures {
3
- /**
4
- * All querying functionality.
5
- */
6
- querying?: boolean;
7
- dbQueryFilter?: boolean;
8
- dbQueryFilterIn?: boolean;
9
- dbQueryOrder?: boolean;
10
- dbQuerySelectFields?: boolean;
11
- insert?: boolean;
12
- update?: boolean;
13
- updateByQuery?: boolean;
14
- dbIncrement?: boolean;
15
- createTable?: boolean;
16
- tableSchemas?: boolean;
17
- /**
18
- * Queries should return fresh results immediately.
19
- * Datastore is the one known to NOT have strong consistency for queries (not for getById though).
20
- */
21
- strongConsistency?: boolean;
22
- streaming?: boolean;
23
- bufferSupport?: boolean;
24
- nullValues?: boolean;
25
- /**
26
- * Set false for SQL (relational) databases,
27
- * they will return `null` for all missing properties.
28
- */
29
- documentDB?: boolean;
30
- transactions?: boolean;
31
- }
32
2
  /**
33
3
  * All options default to `false`.
34
4
  */
35
5
  export interface CommonDBImplementationQuirks {
36
- /**
37
- * Applicable to e.g Datastore.
38
- * Time in milliseconds to wait for eventual consistency to propagate.
39
- */
40
- eventualConsistencyDelay?: number;
41
6
  /**
42
7
  * Example: airtableId
43
8
  */
@@ -47,8 +12,5 @@ export interface CommonDBImplementationQuirks {
47
12
  */
48
13
  allowBooleansAsUndefined?: boolean;
49
14
  }
50
- /**
51
- * All unclaimed features will default to 'true'
52
- */
53
- export declare function runCommonDBTest(db: CommonDB, features?: CommonDBImplementationFeatures, quirks?: CommonDBImplementationQuirks): void;
15
+ export declare function runCommonDBTest(db: CommonDB, quirks?: CommonDBImplementationQuirks): void;
54
16
  export declare function expectMatch(expected: any[], actual: any[], quirks: CommonDBImplementationQuirks): void;