@naturalcycles/db-lib 9.20.0 → 9.22.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 (41) 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 +5 -0
  7. package/dist/adapter/inmemory/inMemoryKeyValueDB.js +17 -0
  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 -29
  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 +36 -10
  17. package/dist/kv/commonKeyValueDB.js +5 -0
  18. package/dist/kv/commonKeyValueDao.d.ts +8 -5
  19. package/dist/kv/commonKeyValueDao.js +9 -0
  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 +32 -15
  25. package/dist/testing/keyValueDaoTest.js +15 -12
  26. package/package.json +1 -1
  27. package/src/adapter/cachedb/cache.db.ts +6 -5
  28. package/src/adapter/file/file.db.ts +2 -1
  29. package/src/adapter/inmemory/inMemory.db.ts +29 -18
  30. package/src/adapter/inmemory/inMemoryKeyValueDB.ts +26 -2
  31. package/src/base.common.db.ts +18 -5
  32. package/src/common.db.ts +36 -34
  33. package/src/commondao/common.dao.ts +46 -11
  34. package/src/db.model.ts +0 -19
  35. package/src/kv/commonKeyValueDB.ts +45 -12
  36. package/src/kv/commonKeyValueDao.ts +22 -8
  37. package/src/query/dbQuery.ts +2 -3
  38. package/src/testing/daoTest.ts +28 -0
  39. package/src/testing/dbTest.ts +22 -28
  40. package/src/testing/keyValueDBTest.ts +37 -17
  41. package/src/testing/keyValueDaoTest.ts +16 -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
  */
@@ -7,6 +7,10 @@ export interface InMemoryKeyValueDBCfg {
7
7
  export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
8
8
  cfg: InMemoryKeyValueDBCfg;
9
9
  constructor(cfg?: InMemoryKeyValueDBCfg);
10
+ support: {
11
+ count?: boolean;
12
+ increment?: boolean;
13
+ };
10
14
  data: StringMap<StringMap<Buffer>>;
11
15
  ping(): Promise<void>;
12
16
  createTable(_table: string, _opt?: CommonDBCreateOptions): Promise<void>;
@@ -18,4 +22,5 @@ export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
18
22
  streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
19
23
  count(table: string): Promise<number>;
20
24
  increment(table: string, id: string, by?: number): Promise<number>;
25
+ incrementBatch(table: string, incrementMap: StringMap<number>): Promise<StringMap<number>>;
21
26
  }
@@ -2,9 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InMemoryKeyValueDB = void 0;
4
4
  const node_stream_1 = require("node:stream");
5
+ const js_lib_1 = require("@naturalcycles/js-lib");
6
+ const commonKeyValueDB_1 = require("../../kv/commonKeyValueDB");
5
7
  class InMemoryKeyValueDB {
6
8
  constructor(cfg = {}) {
7
9
  this.cfg = cfg;
10
+ this.support = {
11
+ ...commonKeyValueDB_1.commonKeyValueDBFullSupport,
12
+ };
8
13
  // data[table][id] > Buffer
9
14
  this.data = {};
10
15
  }
@@ -14,6 +19,7 @@ class InMemoryKeyValueDB {
14
19
  this.data[table] ||= {};
15
20
  ids.forEach(id => delete this.data[table][id]);
16
21
  }
22
+ // todo: but should we work with Tuples or Objects?
17
23
  async getByIds(table, ids) {
18
24
  this.data[table] ||= {};
19
25
  return ids.map(id => [id, this.data[table][id]]).filter(e => e[1]);
@@ -42,5 +48,16 @@ class InMemoryKeyValueDB {
42
48
  this.data[table][id] = Buffer.from(String(newValue));
43
49
  return newValue;
44
50
  }
51
+ async incrementBatch(table, incrementMap) {
52
+ this.data[table] ||= {};
53
+ const result = {};
54
+ for (const [id, by] of (0, js_lib_1._stringMapEntries)(incrementMap)) {
55
+ const newValue = parseInt(this.data[table][id]?.toString() || '0') + by;
56
+ // todo: but should this.data store Buffer or number for incremented values?
57
+ this.data[table][id] = Buffer.from(String(newValue));
58
+ result[id] = newValue;
59
+ }
60
+ return result;
61
+ }
45
62
  }
46
63
  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",
@@ -15,21 +15,6 @@ export interface CommonDB {
15
15
  * Manifest of supported features.
16
16
  */
17
17
  support: CommonDBSupport;
18
- supportsQueries?: boolean;
19
- supportsDBQueryFilter?: boolean;
20
- supportsDBQueryFilterIn?: boolean;
21
- supportsDBQueryOrder?: boolean;
22
- supportsDBQuerySelectFields?: boolean;
23
- supportsInsertSaveMethod?: boolean;
24
- supportsUpdateSaveMethod?: boolean;
25
- supportsUpdateByQuery?: boolean;
26
- supportsDBIncrement?: boolean;
27
- supportsCreateTable?: boolean;
28
- supportsTableSchemas?: boolean;
29
- supportsStreaming?: boolean;
30
- supportsBufferValues?: boolean;
31
- supportsNullValues?: boolean;
32
- supportsTransactions?: boolean;
33
18
  /**
34
19
  * Checks that connection/credentials/etc is ok.
35
20
  * Also acts as a "warmup request" for a DB.
@@ -79,7 +64,7 @@ export interface CommonDB {
79
64
  */
80
65
  deleteByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<number>;
81
66
  /**
82
- * Applies patch to the rows returned by the query.
67
+ * Applies patch to all the rows that are matched by the query.
83
68
  *
84
69
  * Example:
85
70
  *
@@ -87,16 +72,9 @@ export interface CommonDB {
87
72
  *
88
73
  * patch would be { A: 'B' } for that query.
89
74
  *
90
- * Supports "increment query", example:
91
- *
92
- * UPDATE table SET A = A + 1
93
- *
94
- * In that case patch would look like:
95
- * { A: DBIncrement(1) }
96
- *
97
- * Returns number of rows affected.
75
+ * Returns the number of rows affected.
98
76
  */
99
- 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>;
100
78
  /**
101
79
  * Should be implemented as a Transaction (best effort), which means that
102
80
  * either ALL or NONE of the operations should be applied.
@@ -109,6 +87,22 @@ export interface CommonDB {
109
87
  * unless specified as readOnly in CommonDBTransactionOptions.
110
88
  */
111
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>>;
112
106
  }
113
107
  /**
114
108
  * Manifest of supported features.
@@ -121,8 +115,8 @@ export interface CommonDBSupport {
121
115
  dbQuerySelectFields?: boolean;
122
116
  insertSaveMethod?: boolean;
123
117
  updateSaveMethod?: boolean;
124
- updateByQuery?: boolean;
125
- dbIncrement?: boolean;
118
+ patchByQuery?: boolean;
119
+ increment?: boolean;
126
120
  createTable?: boolean;
127
121
  tableSchemas?: boolean;
128
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,20 +1,16 @@
1
- import { UnixTimestampNumber } from '@naturalcycles/js-lib';
1
+ import { StringMap, UnixTimestampNumber } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDBCreateOptions } from '../db.model';
4
- export type KeyValueDBTuple = [key: string, value: Buffer];
5
- export interface CommonKeyValueDBSaveBatchOptions {
6
- /**
7
- * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
8
- * E.g EXAT in Redis.
9
- */
10
- expireAt?: UnixTimestampNumber;
11
- }
12
4
  /**
13
5
  * Common interface for Key-Value database implementations.
14
6
  *
15
7
  * @experimental
16
8
  */
17
9
  export interface CommonKeyValueDB {
10
+ /**
11
+ * Manifest of supported features.
12
+ */
13
+ support: CommonKeyValueDBSupport;
18
14
  /**
19
15
  * Check that DB connection is working properly.
20
16
  */
@@ -37,11 +33,41 @@ export interface CommonKeyValueDB {
37
33
  streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>;
38
34
  count: (table: string) => Promise<number>;
39
35
  /**
40
- *
41
36
  * Increments the value of a key in a table by a given amount.
42
37
  * Default increment is 1 when `by` is not provided.
43
38
  *
44
39
  * Returns the new value.
40
+ *
41
+ * @experimental
45
42
  */
46
43
  increment: (table: string, id: string, by?: number) => Promise<number>;
44
+ /**
45
+ * Perform a batch of Increment operations.
46
+ * Given incrementMap, increment each key of it by the given amount (value of the map).
47
+ *
48
+ * Example:
49
+ * { key1: 2, key2: 3 }
50
+ * would increment `key1` by 2, and `key2` by 3.
51
+ *
52
+ * Returns the incrementMap with the same keys and updated values.
53
+ *
54
+ * @experimental
55
+ */
56
+ incrementBatch: (table: string, incrementMap: StringMap<number>) => Promise<StringMap<number>>;
57
+ }
58
+ export type KeyValueDBTuple = [key: string, value: Buffer];
59
+ export interface CommonKeyValueDBSaveBatchOptions {
60
+ /**
61
+ * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
62
+ * E.g EXAT in Redis.
63
+ */
64
+ expireAt?: UnixTimestampNumber;
65
+ }
66
+ /**
67
+ * Manifest of supported features.
68
+ */
69
+ export interface CommonKeyValueDBSupport {
70
+ count?: boolean;
71
+ increment?: boolean;
47
72
  }
73
+ export declare const commonKeyValueDBFullSupport: CommonKeyValueDBSupport;
@@ -1,2 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.commonKeyValueDBFullSupport = void 0;
4
+ exports.commonKeyValueDBFullSupport = {
5
+ count: true,
6
+ increment: true,
7
+ };
@@ -3,7 +3,7 @@ import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDaoLogLevel } from '../commondao/common.dao.model';
4
4
  import { CommonDBCreateOptions } from '../db.model';
5
5
  import { CommonKeyValueDB, CommonKeyValueDBSaveBatchOptions, KeyValueDBTuple } from './commonKeyValueDB';
6
- export interface CommonKeyValueDaoCfg<T> {
6
+ export interface CommonKeyValueDaoCfg<V> {
7
7
  db: CommonKeyValueDB;
8
8
  table: string;
9
9
  /**
@@ -24,9 +24,9 @@ export interface CommonKeyValueDaoCfg<T> {
24
24
  */
25
25
  logStarted?: boolean;
26
26
  hooks?: {
27
- mapValueToBuffer?: (v: T) => Promise<Buffer>;
28
- mapBufferToValue?: (b: Buffer) => Promise<T>;
29
- beforeCreate?: (v: Partial<T>) => Partial<T>;
27
+ mapValueToBuffer?: (v: V) => Promise<Buffer>;
28
+ mapBufferToValue?: (b: Buffer) => Promise<V>;
29
+ beforeCreate?: (v: Partial<V>) => Partial<V>;
30
30
  };
31
31
  /**
32
32
  * Set to `true` to conveniently enable zipping+JSON.stringify
@@ -59,9 +59,12 @@ export declare class CommonKeyValueDao<V, K extends string = string> {
59
59
  saveBatchAsBuffer(entries: KeyValueDBTuple[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
60
60
  deleteByIds(ids: K[]): Promise<void>;
61
61
  deleteById(id: K): Promise<void>;
62
- streamIds(limit?: number): ReadableTyped<string>;
62
+ streamIds(limit?: number): ReadableTyped<K>;
63
63
  streamValues(limit?: number): ReadableTyped<V>;
64
64
  streamEntries(limit?: number): ReadableTyped<KeyValueTuple<K, V>>;
65
+ getAllKeys(limit?: number): Promise<K[]>;
66
+ getAllValues(limit?: number): Promise<V[]>;
67
+ getAllEntries(limit?: number): Promise<KeyValueTuple<K, V>[]>;
65
68
  /**
66
69
  * Increments the `id` field by the amount specified in `by`,
67
70
  * or by 1 if `by` is not specified.
@@ -157,6 +157,15 @@ class CommonKeyValueDao {
157
157
  concurrency: 32,
158
158
  });
159
159
  }
160
+ async getAllKeys(limit) {
161
+ return await this.streamIds(limit).toArray();
162
+ }
163
+ async getAllValues(limit) {
164
+ return await this.streamValues(limit).toArray();
165
+ }
166
+ async getAllEntries(limit) {
167
+ return await this.streamEntries(limit).toArray();
168
+ }
160
169
  /**
161
170
  * Increments the `id` field by the amount specified in `by`,
162
171
  * or by 1 if `by` is not specified.
@@ -1,6 +1,6 @@
1
1
  import { AsyncMapper, BaseDBEntity, ObjectWithId } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
- import { CommonDaoOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, DBPatch } from '..';
3
+ import { CommonDaoOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions } from '..';
4
4
  import { CommonDao } from '../commondao/common.dao';
5
5
  import { RunQueryResult } from '../db.model';
6
6
  /**
@@ -99,7 +99,7 @@ export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDB
99
99
  runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<BM>>;
100
100
  runQueryExtendedAsDBM(opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
101
101
  runQueryCount(opt?: CommonDaoOptions): Promise<number>;
102
- updateByQuery(patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
102
+ patchByQuery(patch: Partial<DBM>, opt?: CommonDaoOptions): Promise<number>;
103
103
  streamQueryForEach(mapper: AsyncMapper<BM, void>, opt?: CommonDaoStreamForEachOptions<BM>): Promise<void>;
104
104
  streamQueryAsDBMForEach(mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
105
105
  streamQuery(opt?: CommonDaoStreamOptions<BM>): ReadableTyped<BM>;
@@ -165,8 +165,8 @@ class RunnableDBQuery extends DBQuery {
165
165
  async runQueryCount(opt) {
166
166
  return await this.dao.runQueryCount(this, opt);
167
167
  }
168
- async updateByQuery(patch, opt) {
169
- return await this.dao.updateByQuery(this, patch, opt);
168
+ async patchByQuery(patch, opt) {
169
+ return await this.dao.patchByQuery(this, patch, opt);
170
170
  }
171
171
  async streamQueryForEach(mapper, opt) {
172
172
  await this.dao.streamQueryForEach(this, mapper, opt);