@naturalcycles/db-lib 9.21.0 → 9.22.1

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 (43) hide show
  1. package/dist/adapter/cachedb/cache.db.d.ts +2 -2
  2. package/dist/adapter/cachedb/cache.db.js +4 -3
  3. package/dist/adapter/file/file.db.js +2 -1
  4. package/dist/adapter/inmemory/inMemory.db.d.ts +7 -6
  5. package/dist/adapter/inmemory/inMemory.db.js +15 -13
  6. package/dist/adapter/inmemory/inMemoryKeyValueDB.d.ts +8 -8
  7. package/dist/adapter/inmemory/inMemoryKeyValueDB.js +8 -7
  8. package/dist/base.common.db.d.ts +4 -3
  9. package/dist/base.common.db.js +5 -2
  10. package/dist/common.db.d.ts +23 -14
  11. package/dist/common.db.js +2 -2
  12. package/dist/commondao/common.dao.d.ts +16 -5
  13. package/dist/commondao/common.dao.js +37 -8
  14. package/dist/db.model.d.ts +0 -13
  15. package/dist/db.model.js +1 -17
  16. package/dist/kv/commonKeyValueDB.d.ts +18 -10
  17. package/dist/kv/commonKeyValueDao.d.ts +17 -25
  18. package/dist/kv/commonKeyValueDao.js +32 -54
  19. package/dist/kv/commonKeyValueDaoMemoCache.d.ts +2 -2
  20. package/dist/query/dbQuery.d.ts +2 -2
  21. package/dist/query/dbQuery.js +2 -2
  22. package/dist/testing/daoTest.js +26 -0
  23. package/dist/testing/dbTest.js +21 -23
  24. package/dist/testing/keyValueDBTest.js +22 -7
  25. package/dist/testing/keyValueDaoTest.d.ts +2 -2
  26. package/dist/testing/keyValueDaoTest.js +31 -8
  27. package/package.json +1 -1
  28. package/src/adapter/cachedb/cache.db.ts +6 -5
  29. package/src/adapter/file/file.db.ts +2 -1
  30. package/src/adapter/inmemory/inMemory.db.ts +29 -18
  31. package/src/adapter/inmemory/inMemoryKeyValueDB.ts +16 -16
  32. package/src/base.common.db.ts +18 -5
  33. package/src/common.db.ts +36 -17
  34. package/src/commondao/common.dao.ts +46 -11
  35. package/src/db.model.ts +0 -19
  36. package/src/kv/commonKeyValueDB.ts +19 -11
  37. package/src/kv/commonKeyValueDao.ts +53 -86
  38. package/src/kv/commonKeyValueDaoMemoCache.ts +2 -2
  39. package/src/query/dbQuery.ts +2 -3
  40. package/src/testing/daoTest.ts +28 -0
  41. package/src/testing/dbTest.ts +22 -28
  42. package/src/testing/keyValueDBTest.ts +31 -14
  43. package/src/testing/keyValueDaoTest.ts +37 -12
@@ -2,7 +2,7 @@ import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcy
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { BaseCommonDB } from '../../base.common.db';
4
4
  import { CommonDB, CommonDBSupport } from '../../common.db';
5
- import { DBPatch, RunQueryResult } from '../../db.model';
5
+ import { RunQueryResult } from '../../db.model';
6
6
  import { DBQuery } from '../../query/dbQuery';
7
7
  import { CacheDBCfg, CacheDBCreateOptions, CacheDBOptions, CacheDBSaveOptions, CacheDBStreamOptions } from './cache.db.model';
8
8
  /**
@@ -28,5 +28,5 @@ export declare class CacheDB extends BaseCommonDB implements CommonDB {
28
28
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
29
29
  streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBStreamOptions): ReadableTyped<ROW>;
30
30
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CacheDBOptions): Promise<number>;
31
- updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CacheDBOptions): Promise<number>;
31
+ patchByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>, opt?: CacheDBOptions): Promise<number>;
32
32
  }
@@ -17,6 +17,7 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
17
17
  this.support = {
18
18
  ...common_db_1.commonDBFullSupport,
19
19
  transactions: false,
20
+ increment: false,
20
21
  };
21
22
  this.cfg = {
22
23
  logger: console,
@@ -180,13 +181,13 @@ class CacheDB extends base_common_db_1.BaseCommonDB {
180
181
  }
181
182
  return deletedIds;
182
183
  }
183
- async updateByQuery(q, patch, opt = {}) {
184
+ async patchByQuery(q, patch, opt = {}) {
184
185
  let updated;
185
186
  if (!opt.onlyCache && !this.cfg.onlyCache) {
186
- updated = await this.cfg.downstreamDB.updateByQuery(q, patch, opt);
187
+ updated = await this.cfg.downstreamDB.patchByQuery(q, patch, opt);
187
188
  }
188
189
  if (!opt.skipCache && !this.cfg.skipCache) {
189
- const cacheResult = this.cfg.cacheDB.updateByQuery(q, patch, opt);
190
+ const cacheResult = this.cfg.cacheDB.patchByQuery(q, patch, opt);
190
191
  if (this.cfg.awaitCache)
191
192
  updated ??= await cacheResult;
192
193
  }
@@ -22,9 +22,10 @@ class FileDB extends __1.BaseCommonDB {
22
22
  bufferValues: false, // todo: implement
23
23
  insertSaveMethod: false,
24
24
  updateSaveMethod: false,
25
- updateByQuery: false,
25
+ patchByQuery: false,
26
26
  createTable: false,
27
27
  transactions: false, // todo
28
+ increment: false,
28
29
  };
29
30
  this.cfg = {
30
31
  sortObjects: true,
@@ -1,6 +1,6 @@
1
- import { CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
1
+ import { AnyObjectWithId, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
- import { CommonDB, CommonDBTransactionOptions, CommonDBType, DBOperation, DBPatch, DBTransactionFn } from '../..';
3
+ import { CommonDB, CommonDBTransactionOptions, CommonDBType, DBOperation, DBTransactionFn } from '../..';
4
4
  import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, DBTransaction, RunQueryResult } from '../../db.model';
5
5
  import { DBQuery } from '../../query/dbQuery';
6
6
  export interface InMemoryDBCfg {
@@ -55,8 +55,8 @@ export declare class InMemoryDB implements CommonDB {
55
55
  dbQuerySelectFields?: boolean;
56
56
  insertSaveMethod?: boolean;
57
57
  updateSaveMethod?: boolean;
58
- updateByQuery?: boolean;
59
- dbIncrement?: boolean;
58
+ patchByQuery?: boolean;
59
+ increment?: boolean;
60
60
  createTable?: boolean;
61
61
  tableSchemas?: boolean;
62
62
  streaming?: boolean;
@@ -66,7 +66,7 @@ export declare class InMemoryDB implements CommonDB {
66
66
  };
67
67
  constructor(cfg?: Partial<InMemoryDBCfg>);
68
68
  cfg: InMemoryDBCfg;
69
- data: StringMap<StringMap<ObjectWithId>>;
69
+ data: StringMap<StringMap<AnyObjectWithId>>;
70
70
  /**
71
71
  * Returns internal "Data snapshot".
72
72
  * Deterministic - jsonSorted.
@@ -84,11 +84,12 @@ export declare class InMemoryDB implements CommonDB {
84
84
  saveBatch<ROW extends ObjectWithId>(_table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
85
85
  deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
86
86
  deleteByIds(_table: string, ids: string[], _opt?: CommonDBOptions): Promise<number>;
87
- updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>): Promise<number>;
87
+ patchByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>): Promise<number>;
88
88
  runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
89
89
  runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
90
90
  streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): ReadableTyped<ROW>;
91
91
  runInTransaction(fn: DBTransactionFn, opt?: CommonDBTransactionOptions): Promise<void>;
92
+ incrementBatch(table: string, prop: string, incrementMap: StringMap<number>, _opt?: CommonDBOptions): Promise<StringMap<number>>;
92
93
  /**
93
94
  * Flushes all tables (all namespaces) at once.
94
95
  */
@@ -113,22 +113,12 @@ class InMemoryDB {
113
113
  });
114
114
  return count;
115
115
  }
116
- async updateByQuery(q, patch) {
117
- const patchEntries = Object.entries(patch);
118
- if (!patchEntries.length)
116
+ async patchByQuery(q, patch) {
117
+ if ((0, js_lib_1._isEmptyObject)(patch))
119
118
  return 0;
120
119
  const table = this.cfg.tablesPrefix + q.table;
121
120
  const rows = (0, __1.queryInMemory)(q, Object.values(this.data[table] || {}));
122
- rows.forEach((row) => {
123
- patchEntries.forEach(([k, v]) => {
124
- if (v instanceof __1.DBIncrement) {
125
- row[k] = (row[k] || 0) + v.amount;
126
- }
127
- else {
128
- row[k] = v;
129
- }
130
- });
131
- });
121
+ rows.forEach(row => Object.assign(row, patch));
132
122
  return rows.length;
133
123
  }
134
124
  async runQuery(q, _opt) {
@@ -157,6 +147,18 @@ class InMemoryDB {
157
147
  throw err;
158
148
  }
159
149
  }
150
+ async incrementBatch(table, prop, incrementMap, _opt) {
151
+ const tbl = this.cfg.tablesPrefix + table;
152
+ this.data[tbl] ||= {};
153
+ const result = {};
154
+ for (const [id, by] of (0, js_lib_1._stringMapEntries)(incrementMap)) {
155
+ this.data[tbl][id] ||= { id };
156
+ const newValue = (this.data[tbl][id][prop] || 0) + by;
157
+ this.data[tbl][id][prop] = newValue;
158
+ result[id] = newValue;
159
+ }
160
+ return result;
161
+ }
160
162
  /**
161
163
  * Flushes all tables (all namespaces) at once.
162
164
  */
@@ -1,7 +1,7 @@
1
- import { StringMap } from '@naturalcycles/js-lib';
1
+ import { KeyValueTuple, StringMap } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDBCreateOptions } from '../../db.model';
4
- import { CommonKeyValueDB, KeyValueDBTuple } from '../../kv/commonKeyValueDB';
4
+ import { CommonKeyValueDB, IncrementTuple } from '../../kv/commonKeyValueDB';
5
5
  export interface InMemoryKeyValueDBCfg {
6
6
  }
7
7
  export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
@@ -11,15 +11,15 @@ export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
11
11
  count?: boolean;
12
12
  increment?: boolean;
13
13
  };
14
- data: StringMap<StringMap<Buffer>>;
14
+ data: StringMap<StringMap<any>>;
15
15
  ping(): Promise<void>;
16
16
  createTable(_table: string, _opt?: CommonDBCreateOptions): Promise<void>;
17
17
  deleteByIds(table: string, ids: string[]): Promise<void>;
18
- getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]>;
19
- saveBatch(table: string, entries: KeyValueDBTuple[]): Promise<void>;
18
+ getByIds<V>(table: string, ids: string[]): Promise<KeyValueTuple<string, V>[]>;
19
+ saveBatch<V>(table: string, entries: KeyValueTuple<string, V>[]): Promise<void>;
20
20
  streamIds(table: string, limit?: number): ReadableTyped<string>;
21
- streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
22
- streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
21
+ streamValues<V>(table: string, limit?: number): ReadableTyped<V>;
22
+ streamEntries<V>(table: string, limit?: number): ReadableTyped<KeyValueTuple<string, V>>;
23
23
  count(table: string): Promise<number>;
24
- increment(table: string, id: string, by?: number): Promise<number>;
24
+ incrementBatch(table: string, entries: IncrementTuple[]): Promise<IncrementTuple[]>;
25
25
  }
@@ -9,7 +9,7 @@ class InMemoryKeyValueDB {
9
9
  this.support = {
10
10
  ...commonKeyValueDB_1.commonKeyValueDBFullSupport,
11
11
  };
12
- // data[table][id] > Buffer
12
+ // data[table][id] => V
13
13
  this.data = {};
14
14
  }
15
15
  async ping() { }
@@ -24,7 +24,7 @@ class InMemoryKeyValueDB {
24
24
  }
25
25
  async saveBatch(table, entries) {
26
26
  this.data[table] ||= {};
27
- entries.forEach(([id, buf]) => (this.data[table][id] = buf));
27
+ entries.forEach(([id, v]) => (this.data[table][id] = v));
28
28
  }
29
29
  streamIds(table, limit) {
30
30
  return node_stream_1.Readable.from(Object.keys(this.data[table] || {}).slice(0, limit));
@@ -39,12 +39,13 @@ class InMemoryKeyValueDB {
39
39
  this.data[table] ||= {};
40
40
  return Object.keys(this.data[table]).length;
41
41
  }
42
- async increment(table, id, by = 1) {
42
+ async incrementBatch(table, entries) {
43
43
  this.data[table] ||= {};
44
- const currentValue = this.data[table][id] ? parseInt(this.data[table][id].toString()) : 0;
45
- const newValue = currentValue + by;
46
- this.data[table][id] = Buffer.from(String(newValue));
47
- return newValue;
44
+ return entries.map(([id, by]) => {
45
+ const newValue = (this.data[table][id] || 0) + by;
46
+ this.data[table][id] = newValue;
47
+ return [id, newValue];
48
+ });
48
49
  }
49
50
  }
50
51
  exports.InMemoryKeyValueDB = InMemoryKeyValueDB;
@@ -1,7 +1,7 @@
1
- import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
1
+ import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDB, CommonDBSupport, CommonDBType } from './common.db';
4
- import { CommonDBOptions, CommonDBSaveOptions, CommonDBTransactionOptions, DBPatch, DBTransactionFn, RunQueryResult } from './db.model';
4
+ import { CommonDBOptions, CommonDBSaveOptions, CommonDBTransactionOptions, DBTransactionFn, RunQueryResult } from './db.model';
5
5
  import { DBQuery } from './query/dbQuery';
6
6
  /**
7
7
  * No-op implementation of CommonDB interface.
@@ -16,11 +16,12 @@ export declare class BaseCommonDB implements CommonDB {
16
16
  createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>): Promise<void>;
17
17
  getByIds<ROW extends ObjectWithId>(_table: string, _ids: string[]): Promise<ROW[]>;
18
18
  deleteByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
19
- updateByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>, _patch: DBPatch<ROW>, _opt?: CommonDBOptions): Promise<number>;
19
+ patchByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>, _patch: Partial<ROW>, _opt?: CommonDBOptions): Promise<number>;
20
20
  runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
21
21
  runQueryCount<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
22
22
  saveBatch<ROW extends ObjectWithId>(_table: string, _rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
23
23
  streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): ReadableTyped<ROW>;
24
24
  deleteByIds(_table: string, _ids: string[], _opt?: CommonDBOptions): Promise<number>;
25
25
  runInTransaction(fn: DBTransactionFn, _opt?: CommonDBTransactionOptions): Promise<void>;
26
+ incrementBatch(_table: string, _prop: string, _incrementMap: StringMap<number>, _opt?: CommonDBOptions): Promise<StringMap<number>>;
26
27
  }
@@ -30,8 +30,8 @@ class BaseCommonDB {
30
30
  async deleteByQuery(_q) {
31
31
  throw new Error('deleteByQuery is not implemented');
32
32
  }
33
- async updateByQuery(_q, _patch, _opt) {
34
- throw new Error('updateByQuery is not implemented');
33
+ async patchByQuery(_q, _patch, _opt) {
34
+ throw new Error('patchByQuery is not implemented');
35
35
  }
36
36
  async runQuery(_q) {
37
37
  throw new Error('runQuery is not implemented');
@@ -53,5 +53,8 @@ class BaseCommonDB {
53
53
  await fn(tx);
54
54
  // there's no try/catch and rollback, as there's nothing to rollback
55
55
  }
56
+ async incrementBatch(_table, _prop, _incrementMap, _opt) {
57
+ throw new Error('incrementBatch is not implemented');
58
+ }
56
59
  }
57
60
  exports.BaseCommonDB = BaseCommonDB;
@@ -1,6 +1,6 @@
1
- import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
1
+ import { JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, StringMap } from '@naturalcycles/js-lib';
2
2
  import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
- import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBTransactionOptions, DBPatch, DBTransactionFn, RunQueryResult } from './db.model';
3
+ import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBTransactionOptions, DBTransactionFn, RunQueryResult } from './db.model';
4
4
  import { DBQuery } from './query/dbQuery';
5
5
  export declare enum CommonDBType {
6
6
  'document' = "document",
@@ -64,7 +64,7 @@ export interface CommonDB {
64
64
  */
65
65
  deleteByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<number>;
66
66
  /**
67
- * Applies patch to the rows returned by the query.
67
+ * Applies patch to all the rows that are matched by the query.
68
68
  *
69
69
  * Example:
70
70
  *
@@ -72,16 +72,9 @@ export interface CommonDB {
72
72
  *
73
73
  * patch would be { A: 'B' } for that query.
74
74
  *
75
- * Supports "increment query", example:
76
- *
77
- * UPDATE table SET A = A + 1
78
- *
79
- * In that case patch would look like:
80
- * { A: DBIncrement(1) }
81
- *
82
- * Returns number of rows affected.
75
+ * Returns the number of rows affected.
83
76
  */
84
- updateByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CommonDBOptions) => Promise<number>;
77
+ patchByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: Partial<ROW>, opt?: CommonDBOptions) => Promise<number>;
85
78
  /**
86
79
  * Should be implemented as a Transaction (best effort), which means that
87
80
  * either ALL or NONE of the operations should be applied.
@@ -94,6 +87,22 @@ export interface CommonDB {
94
87
  * unless specified as readOnly in CommonDBTransactionOptions.
95
88
  */
96
89
  runInTransaction: (fn: DBTransactionFn, opt?: CommonDBTransactionOptions) => Promise<void>;
90
+ /**
91
+ * Increments a value of a property by a given amount.
92
+ * This is a batch operation, so it allows to increment multiple rows at once.
93
+ *
94
+ * - table - the table to apply operations on
95
+ * - prop - name of the property to increment (in each of the rows passed)
96
+ * - incrementMap - map from id to increment value
97
+ *
98
+ * Example of incrementMap:
99
+ * { rowId1: 2, rowId2: 3 }
100
+ *
101
+ * Returns the incrementMap with the same keys and updated values.
102
+ *
103
+ * @experimental
104
+ */
105
+ incrementBatch: (table: string, prop: string, incrementMap: StringMap<number>, opt?: CommonDBOptions) => Promise<StringMap<number>>;
97
106
  }
98
107
  /**
99
108
  * Manifest of supported features.
@@ -106,8 +115,8 @@ export interface CommonDBSupport {
106
115
  dbQuerySelectFields?: boolean;
107
116
  insertSaveMethod?: boolean;
108
117
  updateSaveMethod?: boolean;
109
- updateByQuery?: boolean;
110
- dbIncrement?: boolean;
118
+ patchByQuery?: boolean;
119
+ increment?: boolean;
111
120
  createTable?: boolean;
112
121
  tableSchemas?: boolean;
113
122
  streaming?: boolean;
package/dist/common.db.js CHANGED
@@ -14,8 +14,8 @@ exports.commonDBFullSupport = {
14
14
  dbQuerySelectFields: true,
15
15
  insertSaveMethod: true,
16
16
  updateSaveMethod: true,
17
- updateByQuery: true,
18
- dbIncrement: true,
17
+ patchByQuery: true,
18
+ increment: true,
19
19
  createTable: true,
20
20
  tableSchemas: true,
21
21
  streaming: true,
@@ -1,7 +1,7 @@
1
1
  import { Transform } from 'node:stream';
2
- import { AsyncMapper, BaseDBEntity, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
2
+ import { AsyncMapper, BaseDBEntity, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, StringMap, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
3
3
  import { AjvSchema, ObjectSchema, ReadableTyped } from '@naturalcycles/nodejs-lib';
4
- import { CommonDBTransactionOptions, DBPatch, DBTransaction, RunQueryResult } from '../db.model';
4
+ import { CommonDBTransactionOptions, DBTransaction, RunQueryResult } from '../db.model';
5
5
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
6
6
  import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoPatchByIdOptions, CommonDaoPatchOptions, CommonDaoSaveBatchOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
7
7
  /**
@@ -125,9 +125,20 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
125
125
  * This is expected to be more memory-efficient way of deleting large number of rows.
126
126
  */
127
127
  deleteByQuery(q: DBQuery<DBM>, opt?: CommonDaoStreamDeleteOptions<DBM>): Promise<number>;
128
- updateById(id: ID, patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
129
- updateByIds(ids: ID[], patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
130
- updateByQuery(q: DBQuery<DBM>, patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
128
+ patchByIds(ids: ID[], patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
129
+ patchByQuery(q: DBQuery<DBM>, patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
130
+ /**
131
+ * Caveat: it doesn't update created/updated props.
132
+ *
133
+ * @experimental
134
+ */
135
+ increment(prop: keyof DBM, id: ID, by?: number, opt?: CommonDaoOptions): Promise<number>;
136
+ /**
137
+ * Caveat: it doesn't update created/updated props.
138
+ *
139
+ * @experimental
140
+ */
141
+ incrementBatch(prop: keyof DBM, incrementMap: StringMap<number>, opt?: CommonDaoOptions): Promise<StringMap<number>>;
131
142
  dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>;
132
143
  dbmToBM(_dbm?: DBM, opt?: CommonDaoOptions): Promise<BM>;
133
144
  dbmsToBM(dbms: DBM[], opt?: CommonDaoOptions): Promise<BM[]>;
@@ -829,25 +829,54 @@ class CommonDao {
829
829
  this.logSaveResult(started, op, q.table);
830
830
  return deleted;
831
831
  }
832
- async updateById(id, patch, opt = {}) {
833
- return await this.updateByQuery(this.query().filterEq('id', id), patch, opt);
834
- }
835
- async updateByIds(ids, patch, opt = {}) {
832
+ async patchByIds(ids, patch, opt = {}) {
836
833
  if (!ids.length)
837
834
  return 0;
838
- return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt);
835
+ return await this.patchByQuery(this.query().filterIn('id', ids), patch, opt);
839
836
  }
840
- async updateByQuery(q, patch, opt = {}) {
837
+ async patchByQuery(q, patch, opt = {}) {
841
838
  this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
842
839
  this.requireWriteAccess();
843
840
  this.requireObjectMutability(opt);
844
841
  q.table = opt.table || q.table;
845
- const op = `updateByQuery(${q.pretty()})`;
842
+ const op = `patchByQuery(${q.pretty()})`;
846
843
  const started = this.logStarted(op, q.table);
847
- const updated = await this.cfg.db.updateByQuery(q, patch, opt);
844
+ const updated = await this.cfg.db.patchByQuery(q, patch, opt);
848
845
  this.logSaveResult(started, op, q.table);
849
846
  return updated;
850
847
  }
848
+ /**
849
+ * Caveat: it doesn't update created/updated props.
850
+ *
851
+ * @experimental
852
+ */
853
+ async increment(prop, id, by = 1, opt = {}) {
854
+ this.requireWriteAccess();
855
+ this.requireObjectMutability(opt);
856
+ const { table } = this.cfg;
857
+ const op = `increment`;
858
+ const started = this.logStarted(op, table);
859
+ const result = await this.cfg.db.incrementBatch(table, prop, {
860
+ [id]: by,
861
+ });
862
+ this.logSaveResult(started, op, table);
863
+ return result[id];
864
+ }
865
+ /**
866
+ * Caveat: it doesn't update created/updated props.
867
+ *
868
+ * @experimental
869
+ */
870
+ async incrementBatch(prop, incrementMap, opt = {}) {
871
+ this.requireWriteAccess();
872
+ this.requireObjectMutability(opt);
873
+ const { table } = this.cfg;
874
+ const op = `incrementBatch`;
875
+ const started = this.logStarted(op, table);
876
+ const result = await this.cfg.db.incrementBatch(table, prop, incrementMap);
877
+ this.logSaveResult(started, op, table);
878
+ return result;
879
+ }
851
880
  async dbmToBM(_dbm, opt = {}) {
852
881
  if (!_dbm)
853
882
  return;
@@ -96,16 +96,3 @@ export declare enum DBModelType {
96
96
  DBM = "DBM",
97
97
  BM = "BM"
98
98
  }
99
- /**
100
- * Allows to construct a query similar to:
101
- *
102
- * UPDATE table SET A = A + 1
103
- *
104
- * In this case DBIncement.of(1) will be needed.
105
- */
106
- export declare class DBIncrement {
107
- amount: number;
108
- private constructor();
109
- static of(amount: number): DBIncrement;
110
- }
111
- export type DBPatch<ROW extends ObjectWithId> = Partial<Record<keyof ROW, ROW[keyof ROW] | DBIncrement>>;
package/dist/db.model.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DBIncrement = exports.DBModelType = exports.DBRelation = void 0;
3
+ exports.DBModelType = exports.DBRelation = void 0;
4
4
  var DBRelation;
5
5
  (function (DBRelation) {
6
6
  DBRelation["ONE_TO_ONE"] = "ONE_TO_ONE";
@@ -11,19 +11,3 @@ var DBModelType;
11
11
  DBModelType["DBM"] = "DBM";
12
12
  DBModelType["BM"] = "BM";
13
13
  })(DBModelType || (exports.DBModelType = DBModelType = {}));
14
- /**
15
- * Allows to construct a query similar to:
16
- *
17
- * UPDATE table SET A = A + 1
18
- *
19
- * In this case DBIncement.of(1) will be needed.
20
- */
21
- class DBIncrement {
22
- constructor(amount) {
23
- this.amount = amount;
24
- }
25
- static of(amount) {
26
- return new DBIncrement(amount);
27
- }
28
- }
29
- exports.DBIncrement = DBIncrement;
@@ -1,4 +1,4 @@
1
- import { UnixTimestampNumber } from '@naturalcycles/js-lib';
1
+ import { Integer, KeyValueTuple, UnixTimestampNumber } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDBCreateOptions } from '../db.model';
4
4
  /**
@@ -25,23 +25,31 @@ export interface CommonKeyValueDB {
25
25
  *
26
26
  * Currently it is NOT required to maintain the same order as input `ids`.
27
27
  */
28
- getByIds: (table: string, ids: string[]) => Promise<KeyValueDBTuple[]>;
28
+ getByIds: <V>(table: string, ids: string[]) => Promise<KeyValueTuple<string, V>[]>;
29
29
  deleteByIds: (table: string, ids: string[]) => Promise<void>;
30
- saveBatch: (table: string, entries: KeyValueDBTuple[], opt?: CommonKeyValueDBSaveBatchOptions) => Promise<void>;
30
+ saveBatch: <V>(table: string, entries: KeyValueTuple<string, V>[], opt?: CommonKeyValueDBSaveBatchOptions) => Promise<void>;
31
31
  streamIds: (table: string, limit?: number) => ReadableTyped<string>;
32
- streamValues: (table: string, limit?: number) => ReadableTyped<Buffer>;
33
- streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>;
32
+ streamValues: <V>(table: string, limit?: number) => ReadableTyped<V>;
33
+ streamEntries: <V>(table: string, limit?: number) => ReadableTyped<KeyValueTuple<string, V>>;
34
34
  count: (table: string) => Promise<number>;
35
35
  /**
36
+ * Perform a batch of Increment operations.
37
+ * Given entries array, increment each key of it (1st index of the tuple) by the given amount (2nd index of the tuple).
36
38
  *
37
- * Increments the value of a key in a table by a given amount.
38
- * Default increment is 1 when `by` is not provided.
39
+ * Example:
40
+ * [
41
+ * ['key1', 2],
42
+ * ['key2', 3],
43
+ * ]
44
+ * would increment `key1` by 2, and `key2` by 3.
39
45
  *
40
- * Returns the new value.
46
+ * Returns the entries array with tuples of the same structure, with updated numbers.
47
+ *
48
+ * @experimental
41
49
  */
42
- increment: (table: string, id: string, by?: number) => Promise<number>;
50
+ incrementBatch: (table: string, entries: IncrementTuple[]) => Promise<IncrementTuple[]>;
43
51
  }
44
- export type KeyValueDBTuple = [key: string, value: Buffer];
52
+ export type IncrementTuple = [key: string, value: Integer];
45
53
  export interface CommonKeyValueDBSaveBatchOptions {
46
54
  /**
47
55
  * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
@@ -2,8 +2,8 @@ import { CommonLogger, KeyValueTuple } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDaoLogLevel } from '../commondao/common.dao.model';
4
4
  import { CommonDBCreateOptions } from '../db.model';
5
- import { CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, KeyValueDBTuple } from './commonKeyValueDB';
6
- export interface CommonKeyValueDaoCfg<V> {
5
+ import { CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, IncrementTuple } from './commonKeyValueDB';
6
+ export interface CommonKeyValueDaoCfg<RAW_V, V = RAW_V> {
7
7
  db: CommonKeyValueDB;
8
8
  table: string;
9
9
  /**
@@ -23,40 +23,31 @@ export interface CommonKeyValueDaoCfg<V> {
23
23
  * @default false
24
24
  */
25
25
  logStarted?: boolean;
26
- hooks?: {
27
- mapValueToBuffer?: (v: V) => Promise<Buffer>;
28
- mapBufferToValue?: (b: Buffer) => Promise<V>;
29
- beforeCreate?: (v: Partial<V>) => Partial<V>;
30
- };
31
- /**
32
- * Set to `true` to conveniently enable zipping+JSON.stringify
33
- * (and unzipping+JSON.parse) of the Buffer value via hooks.
34
- * Custom hooks will override these hooks (if provided).
35
- */
36
- deflatedJsonValue?: boolean;
26
+ transformer?: CommonKeyValueDaoTransformer<V, RAW_V>;
37
27
  }
38
28
  export type CommonKeyValueDaoSaveOptions = CommonKeyValueDBSaveBatchOptions;
39
- export declare class CommonKeyValueDao<V, K extends string = string> {
40
- constructor(cfg: CommonKeyValueDaoCfg<V>);
41
- cfg: CommonKeyValueDaoCfg<V> & {
42
- hooks: NonNullable<CommonKeyValueDaoCfg<V>['hooks']>;
29
+ export interface CommonKeyValueDaoTransformer<V, RAW_V> {
30
+ valueToRaw: (v: V) => Promise<RAW_V>;
31
+ rawToValue: (raw: RAW_V) => Promise<V>;
32
+ }
33
+ export declare const commonKeyValueDaoDeflatedJsonTransformer: CommonKeyValueDaoTransformer<any, Buffer>;
34
+ export declare class CommonKeyValueDao<K extends string, RAW_V, V = RAW_V> {
35
+ constructor(cfg: CommonKeyValueDaoCfg<RAW_V, V>);
36
+ cfg: CommonKeyValueDaoCfg<RAW_V, V> & {
43
37
  logger: CommonLogger;
44
38
  };
45
39
  ping(): Promise<void>;
46
40
  createTable(opt?: CommonDBCreateOptions): Promise<void>;
47
- create(input?: Partial<V>): V;
48
41
  getById(id?: K): Promise<V | null>;
49
- getByIdAsBuffer(id?: K): Promise<Buffer | null>;
42
+ getByIdRaw(id?: K): Promise<RAW_V | null>;
50
43
  requireById(id: K): Promise<V>;
51
- requireByIdAsBuffer(id: K): Promise<Buffer>;
52
- getByIdOrEmpty(id: K, part?: Partial<V>): Promise<V>;
53
- patch(id: K, patch: Partial<V>, opt?: CommonKeyValueDaoSaveOptions): Promise<V>;
44
+ requireByIdRaw(id: K): Promise<RAW_V>;
54
45
  getByIds(ids: K[]): Promise<KeyValueTuple<string, V>[]>;
55
- getByIdsAsBuffer(ids: K[]): Promise<KeyValueTuple<K, Buffer>[]>;
46
+ getByIdsRaw(ids: K[]): Promise<KeyValueTuple<K, RAW_V>[]>;
56
47
  save(id: K, value: V, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
57
- saveAsBuffer(id: K, value: Buffer, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
48
+ saveRaw(id: K, value: RAW_V, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
58
49
  saveBatch(entries: KeyValueTuple<K, V>[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
59
- saveBatchAsBuffer(entries: KeyValueDBTuple[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
50
+ saveBatchRaw(entries: KeyValueTuple<K, RAW_V>[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
60
51
  deleteByIds(ids: K[]): Promise<void>;
61
52
  deleteById(id: K): Promise<void>;
62
53
  streamIds(limit?: number): ReadableTyped<K>;
@@ -72,4 +63,5 @@ export declare class CommonKeyValueDao<V, K extends string = string> {
72
63
  * Returns the new value of the field.
73
64
  */
74
65
  increment(id: K, by?: number): Promise<number>;
66
+ incrementBatch(entries: IncrementTuple[]): Promise<IncrementTuple[]>;
75
67
  }