@naturalcycles/db-lib 8.35.0 → 8.37.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 (37) hide show
  1. package/dist/adapter/cachedb/cache.db.d.ts +9 -9
  2. package/dist/adapter/cachedb/cache.db.js +3 -1
  3. package/dist/adapter/cachedb/cache.db.model.d.ts +5 -3
  4. package/dist/adapter/file/file.db.d.ts +3 -3
  5. package/dist/adapter/file/file.db.js +1 -0
  6. package/dist/adapter/inmemory/inMemory.db.d.ts +3 -3
  7. package/dist/adapter/inmemory/inMemory.db.js +14 -11
  8. package/dist/base.common.db.d.ts +3 -3
  9. package/dist/common.db.d.ts +7 -4
  10. package/dist/commondao/common.dao.d.ts +24 -23
  11. package/dist/commondao/common.dao.js +13 -9
  12. package/dist/commondao/common.dao.model.d.ts +23 -23
  13. package/dist/db.model.d.ts +16 -18
  14. package/dist/index.d.ts +3 -3
  15. package/dist/model.util.d.ts +2 -3
  16. package/dist/model.util.js +1 -7
  17. package/dist/query/dbQuery.d.ts +6 -6
  18. package/dist/testing/dbTest.d.ts +2 -0
  19. package/dist/testing/dbTest.js +16 -1
  20. package/dist/validation/index.d.ts +3 -3
  21. package/package.json +1 -1
  22. package/src/adapter/cachedb/cache.db.model.ts +8 -7
  23. package/src/adapter/cachedb/cache.db.ts +21 -18
  24. package/src/adapter/file/file.db.ts +8 -5
  25. package/src/adapter/inmemory/inMemory.db.ts +22 -15
  26. package/src/base.common.db.ts +3 -3
  27. package/src/common.db.ts +11 -4
  28. package/src/commondao/common.dao.model.ts +32 -25
  29. package/src/commondao/common.dao.ts +58 -65
  30. package/src/db.model.ts +18 -19
  31. package/src/index.ts +4 -20
  32. package/src/model.util.ts +3 -9
  33. package/src/query/dbQuery.ts +8 -7
  34. package/src/testing/dbTest.ts +22 -0
  35. package/dist/adapter/inmemory/index.d.ts +0 -3
  36. package/dist/adapter/inmemory/index.js +0 -8
  37. package/src/adapter/inmemory/index.ts +0 -9
@@ -5,7 +5,7 @@ import { BaseCommonDB } from '../../base.common.db';
5
5
  import { CommonDB } from '../../common.db';
6
6
  import { RunQueryResult } from '../../db.model';
7
7
  import { DBQuery } from '../../query/dbQuery';
8
- import { CacheDBCfg, CacheDBCreateOptions, CacheDBOptions, CacheDBStreamOptions } from './cache.db.model';
8
+ import { CacheDBCfg, CacheDBCreateOptions, CacheDBOptions, CacheDBSaveOptions, CacheDBStreamOptions } from './cache.db.model';
9
9
  /**
10
10
  * CommonDB implementation that proxies requests to downstream CommonDB
11
11
  * and does in-memory caching.
@@ -21,12 +21,12 @@ export declare class CacheDB extends BaseCommonDB implements CommonDB {
21
21
  */
22
22
  getTables(): Promise<string[]>;
23
23
  getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
24
- createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CacheDBCreateOptions<ROW>): Promise<void>;
25
- getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: CacheDBOptions<ROW>): Promise<ROW[]>;
26
- deleteByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: CacheDBOptions<ROW>): Promise<number>;
27
- saveBatch<ROW extends ObjectWithId>(table: string, rows: ROW[], opt?: CacheDBOptions<ROW>): Promise<void>;
28
- runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions<ROW>): Promise<RunQueryResult<ROW>>;
29
- runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions<ROW>): Promise<number>;
30
- streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBStreamOptions<ROW>): Readable;
31
- deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions<ROW>): Promise<number>;
24
+ createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CacheDBCreateOptions): Promise<void>;
25
+ getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CacheDBSaveOptions<ROW>): Promise<ROW[]>;
26
+ deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CacheDBOptions): Promise<number>;
27
+ saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CacheDBSaveOptions<ROW>): Promise<void>;
28
+ runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBSaveOptions<ROW>): Promise<RunQueryResult<ROW>>;
29
+ runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
30
+ streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBStreamOptions): Readable;
31
+ deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
32
32
  }
@@ -81,7 +81,9 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
81
81
  }
82
82
  }
83
83
  if (!opt.skipCache && !this.cfg.skipCache) {
84
- const cacheResult = this.cfg.cacheDB.deleteByIds(table, ids, opt).then(deletedFromCache => {
84
+ const cacheResult = this.cfg.cacheDB
85
+ .deleteByIds(table, ids, opt)
86
+ .then(deletedFromCache => {
85
87
  if (this.cfg.logCached) {
86
88
  this.cfg.logger?.log(`${table}.deleteByIds ${deletedFromCache} rows from cache`);
87
89
  }
@@ -37,7 +37,7 @@ export interface CacheDBCfg {
37
37
  */
38
38
  logger?: CommonLogger;
39
39
  }
40
- export interface CacheDBOptions<ROW extends ObjectWithId> extends CommonDBSaveOptions<ROW> {
40
+ export interface CacheDBOptions {
41
41
  /**
42
42
  * @default false
43
43
  */
@@ -47,7 +47,9 @@ export interface CacheDBOptions<ROW extends ObjectWithId> extends CommonDBSaveOp
47
47
  */
48
48
  onlyCache?: boolean;
49
49
  }
50
- export interface CacheDBStreamOptions<ROW extends ObjectWithId> extends CacheDBOptions<ROW>, CommonDBStreamOptions {
50
+ export interface CacheDBSaveOptions<ROW extends Partial<ObjectWithId>> extends CacheDBOptions, CommonDBSaveOptions<ROW> {
51
51
  }
52
- export interface CacheDBCreateOptions<ROW extends ObjectWithId> extends CacheDBOptions<ROW>, CommonDBCreateOptions {
52
+ export interface CacheDBStreamOptions extends CacheDBOptions, CommonDBStreamOptions {
53
+ }
54
+ export interface CacheDBCreateOptions extends CacheDBOptions, CommonDBCreateOptions {
53
55
  }
@@ -21,8 +21,8 @@ export declare class FileDB extends BaseCommonDB implements CommonDB {
21
21
  cfg: FileDBCfg;
22
22
  ping(): Promise<void>;
23
23
  getTables(): Promise<string[]>;
24
- getByIds<ROW extends ObjectWithId>(table: string, ids: string[], _opt?: CommonDBOptions): Promise<ROW[]>;
25
- saveBatch<ROW extends ObjectWithId>(table: string, rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
24
+ getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
25
+ saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
26
26
  /**
27
27
  * Implementation is optimized for loading/saving _whole files_.
28
28
  */
@@ -30,7 +30,7 @@ export declare class FileDB extends BaseCommonDB implements CommonDB {
30
30
  runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
31
31
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
32
32
  streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
33
- deleteByIds<ROW extends ObjectWithId>(table: string, ids: string[], _opt?: CommonDBOptions): Promise<number>;
33
+ deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<number>;
34
34
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
35
35
  getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
36
36
  loadFile<ROW extends ObjectWithId>(table: string): Promise<ROW[]>;
@@ -46,6 +46,7 @@ class FileDB extends __1.BaseCommonDB {
46
46
  // 2. Merge with new data (using ids)
47
47
  let saved = 0;
48
48
  rows.forEach(r => {
49
+ (0, js_lib_1._assert)(r.id, 'FileDB: row.id is required');
49
50
  if (!(0, js_lib_1._deepEquals)(byId[r.id], r)) {
50
51
  byId[r.id] = r;
51
52
  saved++;
@@ -52,9 +52,9 @@ export declare class InMemoryDB implements CommonDB {
52
52
  getTables(): Promise<string[]>;
53
53
  getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<JsonSchemaRootObject<ROW>>;
54
54
  createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
55
- getByIds<ROW extends ObjectWithId>(_table: string, ids: string[], _opt?: CommonDBOptions): Promise<ROW[]>;
56
- saveBatch<ROW extends ObjectWithId>(_table: string, rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
57
- deleteByIds(_table: string, ids: string[], _opt?: CommonDBOptions): Promise<number>;
55
+ getByIds<ROW extends ObjectWithId>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
56
+ saveBatch<ROW extends Partial<ObjectWithId>>(_table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
57
+ deleteByIds<ROW extends ObjectWithId>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<number>;
58
58
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
59
59
  runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
60
60
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
@@ -58,37 +58,40 @@ class InMemoryDB {
58
58
  };
59
59
  }
60
60
  async createTable(_table, _schema, opt = {}) {
61
+ var _a;
61
62
  const table = this.cfg.tablesPrefix + _table;
62
63
  if (opt.dropIfExists) {
63
64
  this.data[table] = {};
64
65
  }
65
66
  else {
66
- this.data[table] = this.data[table] || {};
67
+ (_a = this.data)[table] || (_a[table] = {});
67
68
  }
68
69
  }
69
70
  async getByIds(_table, ids, _opt) {
71
+ var _a;
70
72
  const table = this.cfg.tablesPrefix + _table;
71
- this.data[table] = this.data[table] || {};
73
+ (_a = this.data)[table] || (_a[table] = {});
72
74
  return ids.map(id => this.data[table][id]).filter(Boolean);
73
75
  }
74
- async saveBatch(_table, rows, _opt) {
76
+ async saveBatch(_table, rows, opt = {}) {
77
+ var _a;
75
78
  const table = this.cfg.tablesPrefix + _table;
76
- this.data[table] = this.data[table] || {};
79
+ (_a = this.data)[table] || (_a[table] = {});
77
80
  rows.forEach(r => {
78
81
  if (!r.id) {
79
82
  this.cfg.logger?.warn({ rows });
80
- throw new Error(`InMemoryDB: id doesn't exist for row`);
83
+ throw new Error(`InMemoryDB doesn't support id auto-generation in saveBatch, row without id was given`);
84
+ }
85
+ if (opt.saveMethod === 'insert' && this.data[table][r.id]) {
86
+ throw new Error(`InMemoryDB: INSERT failed, entity exists: ${table}.${r.id}`);
87
+ }
88
+ if (opt.saveMethod === 'update' && !this.data[table][r.id]) {
89
+ throw new Error(`InMemoryDB: UPDATE failed, entity doesn't exist: ${table}.${r.id}`);
81
90
  }
82
91
  // JSON parse/stringify (deep clone) is to:
83
92
  // 1. Not store values "by reference" (avoid mutation bugs)
84
93
  // 2. Simulate real DB that would do something like that in a transport layer anyway
85
94
  this.data[table][r.id] = JSON.parse(JSON.stringify(r), nodejs_lib_1.bufferReviver);
86
- // special treatment for Buffers (assign them raw, without JSON parse/stringify)
87
- // Object.entries(r).forEach(([k, v]) => {
88
- // if (Buffer.isBuffer(v)) {
89
- // this.data[table]![r.id]![k] = v
90
- // }
91
- // })
92
95
  });
93
96
  }
94
97
  async deleteByIds(_table, ids, _opt) {
@@ -13,12 +13,12 @@ export declare class BaseCommonDB implements CommonDB {
13
13
  getTables(): Promise<string[]>;
14
14
  getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
15
15
  createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>): Promise<void>;
16
- deleteByIds(_table: string, _ids: string[]): Promise<number>;
16
+ deleteByIds<ROW extends ObjectWithId>(_table: string, _ids: ROW['id'][]): Promise<number>;
17
17
  deleteByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
18
- getByIds<ROW extends ObjectWithId>(_table: string, _ids: string[]): Promise<ROW[]>;
18
+ getByIds<ROW extends ObjectWithId>(_table: string, _ids: ROW['id'][]): Promise<ROW[]>;
19
19
  runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
20
20
  runQueryCount<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
21
- saveBatch<ROW extends ObjectWithId>(_table: string, _rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
21
+ saveBatch<ROW extends Partial<ObjectWithId>>(_table: string, _rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
22
22
  streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): ReadableTyped<ROW>;
23
23
  /**
24
24
  * Naive implementation.
@@ -31,19 +31,22 @@ export interface CommonDB {
31
31
  * Order of items returned is not guaranteed to match order of ids.
32
32
  * (Such limitation exists because Datastore doesn't support it).
33
33
  */
34
- getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: CommonDBOptions): Promise<ROW[]>;
34
+ getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions): Promise<ROW[]>;
35
35
  /**
36
36
  * Order by 'id' is not supported by all implementations (for example, Datastore doesn't support it).
37
37
  */
38
38
  runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
39
39
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
40
40
  streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
41
- saveBatch<ROW extends ObjectWithId>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
42
41
  /**
43
- * @returns number of deleted items.
42
+ * rows can have missing ids only if DB supports auto-generating them (like mysql auto_increment).
43
+ */
44
+ saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
45
+ /**
46
+ * Returns number of deleted items.
44
47
  * Not supported by all implementations (e.g Datastore will always return same number as number of ids).
45
48
  */
46
- deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number>;
49
+ deleteByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions): Promise<number>;
47
50
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
48
51
  /**
49
52
  * Should be implemented as a Transaction (best effort), which means that
@@ -1,4 +1,4 @@
1
- import { AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Saved } from '@naturalcycles/js-lib';
1
+ import { AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Saved, Unsaved } from '@naturalcycles/js-lib';
2
2
  import { AjvSchema, ObjectSchemaTyped, ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { DBModelType, RunQueryResult } from '../db.model';
4
4
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
@@ -10,22 +10,22 @@ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOp
10
10
  * BM = Backend model (optimized for API access)
11
11
  * TM = Transport model (optimized to be sent over the wire)
12
12
  */
13
- export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId = Saved<BM>, TM = BM> {
14
- cfg: CommonDaoCfg<BM, DBM, TM>;
15
- constructor(cfg: CommonDaoCfg<BM, DBM, TM>);
13
+ export declare class CommonDao<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID> = Saved<BM>, TM = BM, ID extends string | number = DBM['id']> {
14
+ cfg: CommonDaoCfg<BM, DBM, TM, ID>;
15
+ constructor(cfg: CommonDaoCfg<BM, DBM, TM, ID>);
16
16
  create(part?: Partial<BM>, opt?: CommonDaoOptions): Saved<BM>;
17
17
  getById(id: undefined, opt?: CommonDaoOptions): Promise<null>;
18
- getById(id?: string, opt?: CommonDaoOptions): Promise<Saved<BM> | null>;
19
- getByIdOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<Saved<BM>>;
20
- getByIdAsDBMOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
18
+ getById(id?: ID, opt?: CommonDaoOptions): Promise<Saved<BM> | null>;
19
+ getByIdOrEmpty(id: ID, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<Saved<BM>>;
20
+ getByIdAsDBMOrEmpty(id: ID, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
21
21
  getByIdAsDBM(id: undefined, opt?: CommonDaoOptions): Promise<null>;
22
- getByIdAsDBM(id?: string, opt?: CommonDaoOptions): Promise<DBM | null>;
22
+ getByIdAsDBM(id?: ID, opt?: CommonDaoOptions): Promise<DBM | null>;
23
23
  getByIdAsTM(id: undefined, opt?: CommonDaoOptions): Promise<null>;
24
- getByIdAsTM(id?: string, opt?: CommonDaoOptions): Promise<TM | null>;
25
- getByIds(ids: string[], opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
26
- getByIdsAsDBM(ids: string[], opt?: CommonDaoOptions): Promise<DBM[]>;
27
- requireById(id: string, opt?: CommonDaoOptions): Promise<Saved<BM>>;
28
- requireByIdAsDBM(id: string, opt?: CommonDaoOptions): Promise<DBM>;
24
+ getByIdAsTM(id?: ID, opt?: CommonDaoOptions): Promise<TM | null>;
25
+ getByIds(ids: ID[], opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
26
+ getByIdsAsDBM(ids: ID[], opt?: CommonDaoOptions): Promise<DBM[]>;
27
+ requireById(id: ID, opt?: CommonDaoOptions): Promise<Saved<BM>>;
28
+ requireByIdAsDBM(id: ID, opt?: CommonDaoOptions): Promise<DBM>;
29
29
  private throwRequiredError;
30
30
  /**
31
31
  * Throws if readOnly is true
@@ -41,7 +41,7 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
41
41
  /**
42
42
  * Pass `table` to override table
43
43
  */
44
- query(table?: string): RunnableDBQuery<BM, DBM, TM>;
44
+ query(table?: string): RunnableDBQuery<BM, DBM, TM, ID>;
45
45
  runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
46
46
  runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]>;
47
47
  /**
@@ -72,19 +72,20 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
72
72
  * You can do `.pipe(transformNoOp)` to make it "valid again".
73
73
  */
74
74
  streamQuery(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions): ReadableTyped<Saved<BM>>;
75
- queryIds(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<string[]>;
76
- streamQueryIds(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions): ReadableTyped<string>;
77
- streamQueryIdsForEach(q: DBQuery<DBM>, mapper: AsyncMapper<string, void>, opt?: CommonDaoStreamForEachOptions<string>): Promise<void>;
75
+ queryIds(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<ID[]>;
76
+ streamQueryIds(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions): ReadableTyped<ID>;
77
+ streamQueryIdsForEach(q: DBQuery<DBM>, mapper: AsyncMapper<ID, void>, opt?: CommonDaoStreamForEachOptions<ID>): Promise<void>;
78
78
  /**
79
79
  * Mutates!
80
80
  * "Returns", just to have a type of "Saved"
81
81
  */
82
82
  assignIdCreatedUpdated(obj: DBM, opt?: CommonDaoOptions): DBM;
83
83
  assignIdCreatedUpdated(obj: BM, opt?: CommonDaoOptions): Saved<BM>;
84
+ assignIdCreatedUpdated(obj: Unsaved<BM>, opt?: CommonDaoOptions): Saved<BM>;
84
85
  /**
85
86
  * Mutates with id, created, updated
86
87
  */
87
- save(bm: BM, opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>>;
88
+ save(bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>>;
88
89
  private ensureImmutableDontExist;
89
90
  private ensureUniqueId;
90
91
  private throwIfObjectExists;
@@ -96,17 +97,17 @@ export declare class CommonDao<BM extends Partial<ObjectWithId>, DBM extends Obj
96
97
  *
97
98
  * Convenience method to replace 3 operations (loading+patching+saving) with one.
98
99
  */
99
- patch(id: string, patch: Partial<BM>, opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>>;
100
- patchAsDBM(id: string, patch: Partial<DBM>, opt?: CommonDaoSaveOptions<DBM>): Promise<DBM>;
100
+ patch(id: ID, patch: Partial<BM>, opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>>;
101
+ patchAsDBM(id: ID, patch: Partial<DBM>, opt?: CommonDaoSaveOptions<DBM>): Promise<DBM>;
101
102
  saveAsDBM(dbm: DBM, opt?: CommonDaoSaveOptions<DBM>): Promise<DBM>;
102
- saveBatch(bms: BM[], opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>[]>;
103
+ saveBatch(bms: Unsaved<BM>[], opt?: CommonDaoSaveOptions<DBM>): Promise<Saved<BM>[]>;
103
104
  saveBatchAsDBM(dbms: DBM[], opt?: CommonDaoSaveOptions<DBM>): Promise<DBM[]>;
104
105
  /**
105
106
  * @returns number of deleted items
106
107
  */
107
108
  deleteById(id: undefined, opt?: CommonDaoOptions): Promise<0>;
108
- deleteById(id?: string, opt?: CommonDaoOptions): Promise<number>;
109
- deleteByIds(ids: string[], opt?: CommonDaoOptions): Promise<number>;
109
+ deleteById(id?: ID, opt?: CommonDaoOptions): Promise<number>;
110
+ deleteByIds(ids: ID[], opt?: CommonDaoOptions): Promise<number>;
110
111
  /**
111
112
  * Pass `stream: true` option to use Streaming: it will Stream the query, batch by 500, and execute
112
113
  * `deleteByIds` for each batch concurrently (infinite concurrency).
@@ -19,18 +19,20 @@ const isCI = !!process.env['CI'];
19
19
  */
20
20
  class CommonDao {
21
21
  constructor(cfg) {
22
+ var _a;
22
23
  this.cfg = cfg;
23
24
  this.cfg = {
24
25
  // Default is to NOT log in AppEngine and in CI,
25
26
  // otherwise to log Operations
26
27
  // e.g in Dev (local machine), Test - it will log operations (useful for debugging)
27
28
  logLevel: isGAE || isCI ? common_dao_model_1.CommonDaoLogLevel.NONE : common_dao_model_1.CommonDaoLogLevel.OPERATIONS,
29
+ idType: 'string',
30
+ createId: true,
28
31
  created: true,
29
32
  updated: true,
30
33
  logger: console,
31
34
  ...cfg,
32
35
  hooks: {
33
- createId: () => (0, nodejs_lib_1.stringId)(),
34
36
  parseNaturalId: () => ({}),
35
37
  beforeCreate: bm => bm,
36
38
  beforeDBMValidate: dbm => dbm,
@@ -43,12 +45,18 @@ class CommonDao {
43
45
  ...cfg.hooks,
44
46
  },
45
47
  };
48
+ if (this.cfg.createId) {
49
+ (0, js_lib_1._assert)(this.cfg.idType === 'string', 'db-lib: automatic generation of non-string ids is not supported');
50
+ (_a = this.cfg.hooks).createId || (_a.createId = () => (0, nodejs_lib_1.stringId)());
51
+ }
52
+ else {
53
+ delete this.cfg.hooks.createId;
54
+ }
46
55
  }
47
56
  // CREATE
48
57
  create(part = {}, opt = {}) {
49
58
  let bm = this.cfg.hooks.beforeCreate(part);
50
59
  bm = this.validateAndConvert(bm, this.cfg.bmSchema, db_model_1.DBModelType.BM, opt);
51
- // If no SCHEMA - return as is
52
60
  return this.assignIdCreatedUpdated(bm, opt);
53
61
  }
54
62
  async getById(id, opt = {}) {
@@ -416,16 +424,12 @@ class CommonDao {
416
424
  }
417
425
  assignIdCreatedUpdated(obj, opt = {}) {
418
426
  const now = Math.floor(Date.now() / 1000);
419
- obj.id = obj.id || this.cfg.hooks.createId(obj);
427
+ obj.id || (obj.id = this.cfg.hooks.createId?.(obj));
420
428
  if (this.cfg.created) {
421
- Object.assign(obj, {
422
- created: obj.created || obj.updated || now,
423
- });
429
+ obj['created'] || (obj['created'] = obj['updated'] || now);
424
430
  }
425
431
  if (this.cfg.updated) {
426
- Object.assign(obj, {
427
- updated: opt.preserveUpdatedCreated && obj.updated ? obj.updated : now,
428
- });
432
+ obj['updated'] = opt.preserveUpdatedCreated && obj['updated'] ? obj['updated'] : now;
429
433
  }
430
434
  return obj;
431
435
  }
@@ -2,25 +2,16 @@ import { CommonLogger, ErrorMode, ObjectWithId, Saved } from '@naturalcycles/js-
2
2
  import { AjvSchema, AjvValidationError, JoiValidationError, ObjectSchemaTyped, TransformLogProgressOptions, TransformMapOptions } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDB } from '../common.db';
4
4
  import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model';
5
- export declare type CommonDaoCreateIdHook<BM, DBM> = (obj: DBM | BM) => string;
6
- export declare type CommonDaoParseNaturalIdHook<DBM> = (id: string) => Partial<DBM>;
7
- export declare type CommonDaoBeforeCreateHook<BM> = (bm: Partial<BM>) => Partial<BM>;
8
- export declare type CommonDaoBeforeDBMValidateHook<DBM> = (dbm: Partial<DBM>) => Partial<DBM>;
9
- export declare type CommonDaoBeforeDBMToBMHook<BM, DBM> = (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>;
10
- export declare type CommonDaoBeforeBMToDBMHook<BM, DBM> = (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>;
11
- export declare type CommonDaoBeforeTMToBMHook<BM, TM> = (tm: TM) => Partial<BM>;
12
- export declare type CommonDaoBeforeBMToTMHook<BM, TM> = (bm: BM) => Partial<TM>;
13
- export declare type CommonDaoAnonymizeHook<DBM> = (dbm: DBM) => DBM;
14
- interface CommonDaoHooks<BM, DBM, TM> {
15
- createId: CommonDaoCreateIdHook<BM, DBM>;
16
- parseNaturalId: CommonDaoParseNaturalIdHook<DBM>;
17
- beforeCreate: CommonDaoBeforeCreateHook<BM>;
18
- beforeDBMValidate: CommonDaoBeforeDBMValidateHook<DBM>;
19
- beforeDBMToBM: CommonDaoBeforeDBMToBMHook<BM, DBM>;
20
- beforeBMToDBM: CommonDaoBeforeBMToDBMHook<BM, DBM>;
21
- beforeTMToBM: CommonDaoBeforeTMToBMHook<BM, TM>;
22
- beforeBMToTM: CommonDaoBeforeBMToTMHook<BM, TM>;
23
- anonymize: CommonDaoAnonymizeHook<DBM>;
5
+ export interface CommonDaoHooks<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID>, TM, ID extends string | number> {
6
+ createId: (obj: DBM | BM) => ID;
7
+ parseNaturalId: (id: ID) => Partial<DBM>;
8
+ beforeCreate: (bm: Partial<BM>) => Partial<BM>;
9
+ beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>;
10
+ beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>;
11
+ beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>;
12
+ beforeTMToBM: (tm: TM) => Partial<BM>;
13
+ beforeBMToTM: (bm: BM) => Partial<TM>;
14
+ anonymize: (dbm: DBM) => DBM;
24
15
  /**
25
16
  * If hook is defined - allows to prevent or modify the error thrown.
26
17
  * Return `false` to prevent throwing an error.
@@ -47,7 +38,7 @@ export declare enum CommonDaoLogLevel {
47
38
  */
48
39
  DATA_FULL = 30
49
40
  }
50
- export interface CommonDaoCfg<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId = Saved<BM>, TM = BM> {
41
+ export interface CommonDaoCfg<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID> = Saved<BM>, TM = BM, ID extends string | number = DBM['id']> {
51
42
  db: CommonDB;
52
43
  table: string;
53
44
  /**
@@ -83,7 +74,17 @@ export interface CommonDaoCfg<BM extends Partial<ObjectWithId>, DBM extends Obje
83
74
  * @default false
84
75
  */
85
76
  logStarted?: boolean;
86
- hooks?: Partial<CommonDaoHooks<BM, DBM, TM>>;
77
+ hooks?: Partial<CommonDaoHooks<BM, DBM, TM, ID>>;
78
+ /**
79
+ * Defaults to 'string'
80
+ */
81
+ idType?: 'string' | 'number';
82
+ /**
83
+ * Defaults to true.
84
+ * Set to false to disable auto-generation of `id`.
85
+ * Useful e.g when your DB is generating ids by itself (e.g mysql auto_increment).
86
+ */
87
+ createId?: boolean;
87
88
  /**
88
89
  * Defaults to true
89
90
  * Set to false to disable `created` field management.
@@ -164,7 +165,7 @@ export interface CommonDaoOptions extends CommonDBOptions {
164
165
  /**
165
166
  * All properties default to undefined.
166
167
  */
167
- export interface CommonDaoSaveOptions<DBM extends ObjectWithId> extends CommonDaoOptions, CommonDBSaveOptions<DBM> {
168
+ export interface CommonDaoSaveOptions<DBM extends Partial<ObjectWithId>> extends CommonDaoOptions, CommonDBSaveOptions<DBM> {
168
169
  /**
169
170
  * @default false
170
171
  *
@@ -194,4 +195,3 @@ export interface CommonDaoStreamOptions extends CommonDaoOptions {
194
195
  errorMode?: ErrorMode;
195
196
  }
196
197
  export declare type CommonDaoCreateOptions = CommonDBCreateOptions;
197
- export {};
@@ -1,18 +1,31 @@
1
1
  import { AnyObjectWithId, ObjectWithId } from '@naturalcycles/js-lib';
2
- import { CommonDB } from './common.db';
2
+ /**
3
+ * Similar to SQL INSERT, UPDATE.
4
+ * Insert will fail if row already exists.
5
+ * Update will fail if row is missing.
6
+ * Upsert will auto-detect and use Insert or Update to not fail.
7
+ *
8
+ * Default is Upsert.
9
+ */
10
+ export declare type CommonDBSaveMethod = 'upsert' | 'insert' | 'update';
3
11
  export interface CommonDBOptions {
4
12
  }
5
13
  /**
6
14
  * All properties default to undefined.
7
15
  */
8
- export interface CommonDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId> extends CommonDBOptions {
16
+ export interface CommonDBSaveOptions<ROW extends Partial<ObjectWithId> = AnyObjectWithId> extends CommonDBOptions {
9
17
  excludeFromIndexes?: (keyof ROW)[];
18
+ /**
19
+ * Default is `upsert`
20
+ */
21
+ saveMethod?: CommonDBSaveMethod;
10
22
  }
11
23
  export declare type CommonDBStreamOptions = CommonDBOptions;
12
24
  export interface CommonDBCreateOptions extends CommonDBOptions {
13
25
  /**
14
- * @default false
15
26
  * Caution! If set to true - will actually DROP the table!
27
+ *
28
+ * @default false
16
29
  */
17
30
  dropIfExists?: boolean;
18
31
  }
@@ -40,18 +53,3 @@ export declare enum DBModelType {
40
53
  BM = "BM",
41
54
  TM = "TM"
42
55
  }
43
- /**
44
- * Interface for a module (lib) that implements CommonDB.
45
- *
46
- * Example:
47
- *
48
- * const lib: CommonDBModule = require('mysql-lib')
49
- * const db = lib.getDB()
50
- */
51
- export interface CommonDBAdapter {
52
- /**
53
- * @param cfg was read from SECRET_DB${i} by secret('SECRET_DB${i}') method and passed there.
54
- * It's a string that can contain e.g JSON.stringified configuration object (depends on the adapter).
55
- */
56
- getDBAdapter(cfg?: string): CommonDB;
57
- }
package/dist/index.d.ts CHANGED
@@ -5,8 +5,8 @@ import { BaseCommonDB } from './base.common.db';
5
5
  import { DBLibError } from './cnst';
6
6
  import { CommonDB } from './common.db';
7
7
  import { CommonDao } from './commondao/common.dao';
8
- import { CommonDaoAnonymizeHook, CommonDaoBeforeBMToDBMHook, CommonDaoBeforeBMToTMHook, CommonDaoBeforeCreateHook, CommonDaoBeforeDBMToBMHook, CommonDaoBeforeDBMValidateHook, CommonDaoBeforeTMToBMHook, CommonDaoCfg, CommonDaoCreateIdHook, CommonDaoCreateOptions, CommonDaoLogLevel, CommonDaoOptions, CommonDaoParseNaturalIdHook, CommonDaoSaveOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions } from './commondao/common.dao.model';
9
- import { CommonDBAdapter, CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, DBDeleteByIdsOperation, DBModelType, DBOperation, DBRelation, DBSaveBatchOperation, RunQueryResult } from './db.model';
8
+ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoLogLevel, CommonDaoOptions, CommonDaoSaveOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoHooks } from './commondao/common.dao.model';
9
+ import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveMethod, CommonDBSaveOptions, CommonDBStreamOptions, DBDeleteByIdsOperation, DBModelType, DBOperation, DBRelation, DBSaveBatchOperation, RunQueryResult } from './db.model';
10
10
  import { CommonKeyValueDao, CommonKeyValueDaoCfg } from './kv/commonKeyValueDao';
11
11
  import { CommonKeyValueDB, KeyValueDBTuple } from './kv/commonKeyValueDB';
12
12
  import { createdUpdatedFields, createdUpdatedIdFields, deserializeJsonField, serializeJsonField } from './model.util';
@@ -17,5 +17,5 @@ import { DBQuery, DBQueryFilter, DBQueryFilterOperator, dbQueryFilterOperatorVal
17
17
  import { DBTransaction, RunnableDBTransaction } from './transaction/dbTransaction';
18
18
  import { commitDBTransactionSimple, mergeDBOperations } from './transaction/dbTransaction.util';
19
19
  export * from './kv/commonKeyValueDaoMemoCache';
20
- export type { DBQueryFilterOperator, DBQueryFilter, DBQueryOrder, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBCreateOptions, CommonDB, RunQueryResult, CommonDaoCfg, CommonDaoCreateIdHook, CommonDaoParseNaturalIdHook, CommonDaoBeforeCreateHook, CommonDaoBeforeDBMValidateHook, CommonDaoBeforeDBMToBMHook, CommonDaoBeforeBMToDBMHook, CommonDaoBeforeTMToBMHook, CommonDaoBeforeBMToTMHook, CommonDaoAnonymizeHook, InMemoryDBCfg, InMemoryKeyValueDBCfg, DBPipelineBackupOptions, DBPipelineRestoreOptions, DBPipelineCopyOptions, CommonDBAdapter, DBOperation, DBSaveBatchOperation, DBDeleteByIdsOperation, CommonKeyValueDB, CommonKeyValueDaoCfg, KeyValueDBTuple, };
20
+ export type { DBQueryFilterOperator, DBQueryFilter, DBQueryOrder, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoHooks, CommonDBOptions, CommonDBSaveOptions, CommonDBSaveMethod, CommonDBStreamOptions, CommonDBCreateOptions, CommonDB, RunQueryResult, CommonDaoCfg, InMemoryDBCfg, InMemoryKeyValueDBCfg, DBPipelineBackupOptions, DBPipelineRestoreOptions, DBPipelineCopyOptions, DBOperation, DBSaveBatchOperation, DBDeleteByIdsOperation, CommonKeyValueDB, CommonKeyValueDaoCfg, KeyValueDBTuple, };
21
21
  export { DBQuery, dbQueryFilterOperatorValues, RunnableDBQuery, CommonDaoLogLevel, DBRelation, DBModelType, CommonDao, createdUpdatedFields, createdUpdatedIdFields, InMemoryDB, InMemoryKeyValueDB, queryInMemory, serializeJsonField, deserializeJsonField, dbPipelineBackup, dbPipelineRestore, dbPipelineCopy, DBLibError, BaseCommonDB, DBTransaction, RunnableDBTransaction, mergeDBOperations, commitDBTransactionSimple, CommonKeyValueDao, };
@@ -1,6 +1,5 @@
1
- import { CreatedUpdated, CreatedUpdatedId, ObjectWithId } from '@naturalcycles/js-lib';
1
+ import { CreatedUpdated, CreatedUpdatedId } from '@naturalcycles/js-lib';
2
2
  export declare function createdUpdatedFields(existingObject?: Partial<CreatedUpdated> | null): CreatedUpdated;
3
- export declare function createdUpdatedIdFields(existingObject?: Partial<CreatedUpdatedId> | null): CreatedUpdatedId;
4
- export declare function idField(existingObject?: Partial<CreatedUpdatedId> | null): ObjectWithId;
3
+ export declare function createdUpdatedIdFields(existingObject?: Partial<CreatedUpdatedId<string>> | null): CreatedUpdatedId<string>;
5
4
  export declare function deserializeJsonField<T = any>(f?: string): T;
6
5
  export declare function serializeJsonField(f: any): string | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serializeJsonField = exports.deserializeJsonField = exports.idField = exports.createdUpdatedIdFields = exports.createdUpdatedFields = void 0;
3
+ exports.serializeJsonField = exports.deserializeJsonField = exports.createdUpdatedIdFields = exports.createdUpdatedFields = void 0;
4
4
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
5
5
  function createdUpdatedFields(existingObject) {
6
6
  const now = Math.floor(Date.now() / 1000);
@@ -19,12 +19,6 @@ function createdUpdatedIdFields(existingObject) {
19
19
  };
20
20
  }
21
21
  exports.createdUpdatedIdFields = createdUpdatedIdFields;
22
- function idField(existingObject) {
23
- return {
24
- id: existingObject?.id || (0, nodejs_lib_1.stringId)(),
25
- };
26
- }
27
- exports.idField = idField;
28
22
  function deserializeJsonField(f) {
29
23
  return JSON.parse(f || '{}');
30
24
  }
@@ -83,12 +83,12 @@ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
83
83
  /**
84
84
  * DBQuery that has additional method to support Fluent API style.
85
85
  */
86
- export declare class RunnableDBQuery<BM extends Partial<ObjectWithId>, DBM extends ObjectWithId, TM> extends DBQuery<DBM> {
87
- dao: CommonDao<BM, DBM, TM>;
86
+ export declare class RunnableDBQuery<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID>, TM, ID extends string | number> extends DBQuery<DBM> {
87
+ dao: CommonDao<BM, DBM, TM, ID>;
88
88
  /**
89
89
  * Pass `table` to override table.
90
90
  */
91
- constructor(dao: CommonDao<BM, DBM, TM>, table?: string);
91
+ constructor(dao: CommonDao<BM, DBM, TM, ID>, table?: string);
92
92
  runQuery(opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
93
93
  runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
94
94
  runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
@@ -101,9 +101,9 @@ export declare class RunnableDBQuery<BM extends Partial<ObjectWithId>, DBM exten
101
101
  streamQueryAsDBMForEach(mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
102
102
  streamQuery(opt?: CommonDaoStreamOptions): ReadableTyped<Saved<BM>>;
103
103
  streamQueryAsDBM(opt?: CommonDaoStreamOptions): ReadableTyped<DBM>;
104
- queryIds(opt?: CommonDaoOptions): Promise<string[]>;
105
- streamQueryIds(opt?: CommonDaoStreamOptions): ReadableTyped<string>;
106
- streamQueryIdsForEach(mapper: AsyncMapper<string, void>, opt?: CommonDaoStreamForEachOptions<string>): Promise<void>;
104
+ queryIds(opt?: CommonDaoOptions): Promise<ID[]>;
105
+ streamQueryIds(opt?: CommonDaoStreamOptions): ReadableTyped<ID>;
106
+ streamQueryIdsForEach(mapper: AsyncMapper<ID, void>, opt?: CommonDaoStreamForEachOptions<ID>): Promise<void>;
107
107
  deleteByQuery(opt?: CommonDaoStreamForEachOptions<DBM> & {
108
108
  stream?: boolean;
109
109
  }): Promise<number>;
@@ -8,6 +8,8 @@ export interface CommonDBImplementationFeatures {
8
8
  dbQueryFilterIn?: boolean;
9
9
  dbQueryOrder?: boolean;
10
10
  dbQuerySelectFields?: boolean;
11
+ insert?: boolean;
12
+ update?: boolean;
11
13
  createTable?: boolean;
12
14
  tableSchemas?: boolean;
13
15
  /**
@@ -12,7 +12,7 @@ const test_util_1 = require("./test.util");
12
12
  function runCommonDBTest(db, features = {}, quirks = {}) {
13
13
  const { querying = true, tableSchemas = true, createTable = true, dbQueryFilter = true,
14
14
  // dbQueryFilterIn = true,
15
- dbQueryOrder = true, dbQuerySelectFields = true, streaming = true, strongConsistency = true, bufferSupport = true, nullValues = true, documentDB = true, } = features;
15
+ dbQueryOrder = true, dbQuerySelectFields = true, insert = true, update = true, streaming = true, strongConsistency = true, bufferSupport = true, nullValues = true, documentDB = true, } = features;
16
16
  // const {
17
17
  // allowExtraPropertiesInResponse,
18
18
  // allowBooleansAsUndefined,
@@ -87,9 +87,24 @@ function runCommonDBTest(db, features = {}, quirks = {}) {
87
87
  expect(Object.keys(item3Loaded)).not.toContain('k2');
88
88
  });
89
89
  }
90
+ if (update) {
91
+ test('saveBatch UPDATE method should throw', async () => {
92
+ await expect(db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'update' })).rejects.toThrow();
93
+ });
94
+ }
90
95
  test('saveBatch test items', async () => {
91
96
  await db.saveBatch(test_model_1.TEST_TABLE, items);
92
97
  });
98
+ if (insert) {
99
+ test('saveBatch INSERT method should throw', async () => {
100
+ await expect(db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'insert' })).rejects.toThrow();
101
+ });
102
+ }
103
+ if (update) {
104
+ test('saveBatch UPDATE method should pass', async () => {
105
+ await db.saveBatch(test_model_1.TEST_TABLE, items, { saveMethod: 'update' });
106
+ });
107
+ }
93
108
  // GET not empty
94
109
  test('getByIds all items', async () => {
95
110
  const rows = await db.getByIds(test_model_1.TEST_TABLE, items.map(i => i.id).concat('abcd'));