@naturalcycles/db-lib 9.20.0 → 9.21.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.
@@ -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>;
@@ -2,9 +2,13 @@
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 commonKeyValueDB_1 = require("../../kv/commonKeyValueDB");
5
6
  class InMemoryKeyValueDB {
6
7
  constructor(cfg = {}) {
7
8
  this.cfg = cfg;
9
+ this.support = {
10
+ ...commonKeyValueDB_1.commonKeyValueDBFullSupport,
11
+ };
8
12
  // data[table][id] > Buffer
9
13
  this.data = {};
10
14
  }
@@ -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.
@@ -1,20 +1,16 @@
1
1
  import { 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
  */
@@ -45,3 +41,19 @@ export interface CommonKeyValueDB {
45
41
  */
46
42
  increment: (table: string, id: string, by?: number) => Promise<number>;
47
43
  }
44
+ export type KeyValueDBTuple = [key: string, value: Buffer];
45
+ export interface CommonKeyValueDBSaveBatchOptions {
46
+ /**
47
+ * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
48
+ * E.g EXAT in Redis.
49
+ */
50
+ expireAt?: UnixTimestampNumber;
51
+ }
52
+ /**
53
+ * Manifest of supported features.
54
+ */
55
+ export interface CommonKeyValueDBSupport {
56
+ count?: boolean;
57
+ increment?: boolean;
58
+ }
59
+ 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.
@@ -18,6 +18,7 @@ function runCommonKeyValueDBTest(db) {
18
18
  const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
19
19
  await db.deleteByIds(test_model_1.TEST_TABLE, ids);
20
20
  });
21
+ const { support } = db;
21
22
  test('ping', async () => {
22
23
  await db.ping();
23
24
  });
@@ -40,9 +41,11 @@ function runCommonKeyValueDBTest(db) {
40
41
  (0, js_lib_1._sortBy)(entries, e => e[0], true);
41
42
  expect(entries).toEqual(testEntries);
42
43
  });
43
- test('count should be 3', async () => {
44
- expect(await db.count(test_model_1.TEST_TABLE)).toBe(3);
45
- });
44
+ if (support.count) {
45
+ test('count should be 3', async () => {
46
+ expect(await db.count(test_model_1.TEST_TABLE)).toBe(3);
47
+ });
48
+ }
46
49
  test('streamIds', async () => {
47
50
  const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
48
51
  ids.sort();
@@ -82,16 +85,18 @@ function runCommonKeyValueDBTest(db) {
82
85
  const results = await db.getByIds(test_model_1.TEST_TABLE, testIds);
83
86
  expect(results).toEqual([]);
84
87
  });
85
- test('increment on a non-existing field should set the value to 1', async () => {
86
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
87
- expect(result).toBe(1);
88
- });
89
- test('increment on a existing field should increase the value by one', async () => {
90
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
91
- expect(result).toBe(2);
92
- });
93
- test('increment should increase the value by the specified amount', async () => {
94
- const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField', 2);
95
- expect(result).toBe(4);
96
- });
88
+ if (support.increment) {
89
+ test('increment on a non-existing field should set the value to 1', async () => {
90
+ const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
91
+ expect(result).toBe(1);
92
+ });
93
+ test('increment on a existing field should increase the value by one', async () => {
94
+ const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField');
95
+ expect(result).toBe(2);
96
+ });
97
+ test('increment should increase the value by the specified amount', async () => {
98
+ const result = await db.increment(test_model_1.TEST_TABLE, 'nonExistingField', 2);
99
+ expect(result).toBe(4);
100
+ });
101
+ }
97
102
  }
@@ -17,6 +17,7 @@ function runCommonKeyValueDaoTest(dao) {
17
17
  const ids = await dao.streamIds().toArray();
18
18
  await dao.deleteByIds(ids);
19
19
  });
20
+ const { support } = dao.cfg.db;
20
21
  test('ping', async () => {
21
22
  await dao.ping();
22
23
  });
@@ -75,16 +76,18 @@ function runCommonKeyValueDaoTest(dao) {
75
76
  const results = await dao.getByIds(testIds);
76
77
  expect(results).toEqual([]);
77
78
  });
78
- test('increment on a non-existing field should set the value to 1', async () => {
79
- const result = await dao.increment('nonExistingField');
80
- expect(result).toBe(1);
81
- });
82
- test('increment on a existing field should increase the value by one', async () => {
83
- const result = await dao.increment('nonExistingField');
84
- expect(result).toBe(2);
85
- });
86
- test('increment should increase the value by the specified amount', async () => {
87
- const result = await dao.increment('nonExistingField', 2);
88
- expect(result).toBe(4);
89
- });
79
+ if (support.increment) {
80
+ test('increment on a non-existing field should set the value to 1', async () => {
81
+ const result = await dao.increment('nonExistingField');
82
+ expect(result).toBe(1);
83
+ });
84
+ test('increment on a existing field should increase the value by one', async () => {
85
+ const result = await dao.increment('nonExistingField');
86
+ expect(result).toBe(2);
87
+ });
88
+ test('increment should increase the value by the specified amount', async () => {
89
+ const result = await dao.increment('nonExistingField', 2);
90
+ expect(result).toBe(4);
91
+ });
92
+ }
90
93
  }
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  "engines": {
46
46
  "node": ">=20.13"
47
47
  },
48
- "version": "9.20.0",
48
+ "version": "9.21.0",
49
49
  "description": "Lowest Common Denominator API to supported Databases",
50
50
  "keywords": [
51
51
  "db",
@@ -2,13 +2,21 @@ import { Readable } from 'node:stream'
2
2
  import { StringMap } from '@naturalcycles/js-lib'
3
3
  import { ReadableTyped } from '@naturalcycles/nodejs-lib'
4
4
  import { CommonDBCreateOptions } from '../../db.model'
5
- import { CommonKeyValueDB, KeyValueDBTuple } from '../../kv/commonKeyValueDB'
5
+ import {
6
+ CommonKeyValueDB,
7
+ commonKeyValueDBFullSupport,
8
+ KeyValueDBTuple,
9
+ } from '../../kv/commonKeyValueDB'
6
10
 
7
11
  export interface InMemoryKeyValueDBCfg {}
8
12
 
9
13
  export class InMemoryKeyValueDB implements CommonKeyValueDB {
10
14
  constructor(public cfg: InMemoryKeyValueDBCfg = {}) {}
11
15
 
16
+ support = {
17
+ ...commonKeyValueDBFullSupport,
18
+ }
19
+
12
20
  // data[table][id] > Buffer
13
21
  data: StringMap<StringMap<Buffer>> = {}
14
22
 
package/src/common.db.ts CHANGED
@@ -28,23 +28,6 @@ export interface CommonDB {
28
28
  */
29
29
  support: CommonDBSupport
30
30
 
31
- // Support flags indicate which of the CommonDB features are supported by this implementation.
32
- supportsQueries?: boolean
33
- supportsDBQueryFilter?: boolean
34
- supportsDBQueryFilterIn?: boolean
35
- supportsDBQueryOrder?: boolean
36
- supportsDBQuerySelectFields?: boolean
37
- supportsInsertSaveMethod?: boolean
38
- supportsUpdateSaveMethod?: boolean
39
- supportsUpdateByQuery?: boolean
40
- supportsDBIncrement?: boolean
41
- supportsCreateTable?: boolean
42
- supportsTableSchemas?: boolean
43
- supportsStreaming?: boolean
44
- supportsBufferValues?: boolean
45
- supportsNullValues?: boolean
46
- supportsTransactions?: boolean
47
-
48
31
  /**
49
32
  * Checks that connection/credentials/etc is ok.
50
33
  * Also acts as a "warmup request" for a DB.
@@ -2,22 +2,17 @@ import { UnixTimestampNumber } from '@naturalcycles/js-lib'
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib'
3
3
  import { CommonDBCreateOptions } from '../db.model'
4
4
 
5
- export type KeyValueDBTuple = [key: string, value: Buffer]
6
-
7
- export interface CommonKeyValueDBSaveBatchOptions {
8
- /**
9
- * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
10
- * E.g EXAT in Redis.
11
- */
12
- expireAt?: UnixTimestampNumber
13
- }
14
-
15
5
  /**
16
6
  * Common interface for Key-Value database implementations.
17
7
  *
18
8
  * @experimental
19
9
  */
20
10
  export interface CommonKeyValueDB {
11
+ /**
12
+ * Manifest of supported features.
13
+ */
14
+ support: CommonKeyValueDBSupport
15
+
21
16
  /**
22
17
  * Check that DB connection is working properly.
23
18
  */
@@ -59,3 +54,26 @@ export interface CommonKeyValueDB {
59
54
  */
60
55
  increment: (table: string, id: string, by?: number) => Promise<number>
61
56
  }
57
+
58
+ export type KeyValueDBTuple = [key: string, value: Buffer]
59
+
60
+ export interface CommonKeyValueDBSaveBatchOptions {
61
+ /**
62
+ * If set (and if it's implemented by the driver) - will set expiry TTL for each key of the batch.
63
+ * E.g EXAT in Redis.
64
+ */
65
+ expireAt?: UnixTimestampNumber
66
+ }
67
+
68
+ /**
69
+ * Manifest of supported features.
70
+ */
71
+ export interface CommonKeyValueDBSupport {
72
+ count?: boolean
73
+ increment?: boolean
74
+ }
75
+
76
+ export const commonKeyValueDBFullSupport: CommonKeyValueDBSupport = {
77
+ count: true,
78
+ increment: true,
79
+ }
@@ -8,7 +8,7 @@ import {
8
8
  KeyValueDBTuple,
9
9
  } from './commonKeyValueDB'
10
10
 
11
- export interface CommonKeyValueDaoCfg<T> {
11
+ export interface CommonKeyValueDaoCfg<V> {
12
12
  db: CommonKeyValueDB
13
13
 
14
14
  table: string
@@ -35,9 +35,9 @@ export interface CommonKeyValueDaoCfg<T> {
35
35
  logStarted?: boolean
36
36
 
37
37
  hooks?: {
38
- mapValueToBuffer?: (v: T) => Promise<Buffer>
39
- mapBufferToValue?: (b: Buffer) => Promise<T>
40
- beforeCreate?: (v: Partial<T>) => Partial<T>
38
+ mapValueToBuffer?: (v: V) => Promise<Buffer>
39
+ mapBufferToValue?: (b: Buffer) => Promise<V>
40
+ beforeCreate?: (v: Partial<V>) => Partial<V>
41
41
  }
42
42
 
43
43
  /**
@@ -203,8 +203,8 @@ export class CommonKeyValueDao<V, K extends string = string> {
203
203
  await this.cfg.db.deleteByIds(this.cfg.table, [id])
204
204
  }
205
205
 
206
- streamIds(limit?: number): ReadableTyped<string> {
207
- return this.cfg.db.streamIds(this.cfg.table, limit)
206
+ streamIds(limit?: number): ReadableTyped<K> {
207
+ return this.cfg.db.streamIds(this.cfg.table, limit) as ReadableTyped<K>
208
208
  }
209
209
 
210
210
  streamValues(limit?: number): ReadableTyped<V> {
@@ -236,10 +236,12 @@ export class CommonKeyValueDao<V, K extends string = string> {
236
236
  return this.cfg.db.streamEntries(this.cfg.table, limit) as ReadableTyped<KeyValueTuple<K, V>>
237
237
  }
238
238
 
239
- return this.cfg.db.streamEntries(this.cfg.table, limit).flatMap(
239
+ return (
240
+ this.cfg.db.streamEntries(this.cfg.table, limit) as ReadableTyped<KeyValueTuple<K, Buffer>>
241
+ ).flatMap(
240
242
  async ([id, buf]) => {
241
243
  try {
242
- return [[id as K, await mapBufferToValue(buf)]]
244
+ return [[id, await mapBufferToValue(buf)]]
243
245
  } catch (err) {
244
246
  this.cfg.logger.error(err)
245
247
  return [] // SKIP
@@ -251,6 +253,18 @@ export class CommonKeyValueDao<V, K extends string = string> {
251
253
  )
252
254
  }
253
255
 
256
+ async getAllKeys(limit?: number): Promise<K[]> {
257
+ return await this.streamIds(limit).toArray()
258
+ }
259
+
260
+ async getAllValues(limit?: number): Promise<V[]> {
261
+ return await this.streamValues(limit).toArray()
262
+ }
263
+
264
+ async getAllEntries(limit?: number): Promise<KeyValueTuple<K, V>[]> {
265
+ return await this.streamEntries(limit).toArray()
266
+ }
267
+
254
268
  /**
255
269
  * Increments the `id` field by the amount specified in `by`,
256
270
  * or by 1 if `by` is not specified.
@@ -21,6 +21,8 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
21
21
  await db.deleteByIds(TEST_TABLE, ids)
22
22
  })
23
23
 
24
+ const { support } = db
25
+
24
26
  test('ping', async () => {
25
27
  await db.ping()
26
28
  })
@@ -50,9 +52,11 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
50
52
  expect(entries).toEqual(testEntries)
51
53
  })
52
54
 
53
- test('count should be 3', async () => {
54
- expect(await db.count(TEST_TABLE)).toBe(3)
55
- })
55
+ if (support.count) {
56
+ test('count should be 3', async () => {
57
+ expect(await db.count(TEST_TABLE)).toBe(3)
58
+ })
59
+ }
56
60
 
57
61
  test('streamIds', async () => {
58
62
  const ids = await db.streamIds(TEST_TABLE).toArray()
@@ -100,18 +104,20 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
100
104
  expect(results).toEqual([])
101
105
  })
102
106
 
103
- test('increment on a non-existing field should set the value to 1', async () => {
104
- const result = await db.increment(TEST_TABLE, 'nonExistingField')
105
- expect(result).toBe(1)
106
- })
107
+ if (support.increment) {
108
+ test('increment on a non-existing field should set the value to 1', async () => {
109
+ const result = await db.increment(TEST_TABLE, 'nonExistingField')
110
+ expect(result).toBe(1)
111
+ })
107
112
 
108
- test('increment on a existing field should increase the value by one', async () => {
109
- const result = await db.increment(TEST_TABLE, 'nonExistingField')
110
- expect(result).toBe(2)
111
- })
113
+ test('increment on a existing field should increase the value by one', async () => {
114
+ const result = await db.increment(TEST_TABLE, 'nonExistingField')
115
+ expect(result).toBe(2)
116
+ })
112
117
 
113
- test('increment should increase the value by the specified amount', async () => {
114
- const result = await db.increment(TEST_TABLE, 'nonExistingField', 2)
115
- expect(result).toBe(4)
116
- })
118
+ test('increment should increase the value by the specified amount', async () => {
119
+ const result = await db.increment(TEST_TABLE, 'nonExistingField', 2)
120
+ expect(result).toBe(4)
121
+ })
122
+ }
117
123
  }
@@ -20,6 +20,8 @@ export function runCommonKeyValueDaoTest(dao: CommonKeyValueDao<Buffer>): void {
20
20
  await dao.deleteByIds(ids)
21
21
  })
22
22
 
23
+ const { support } = dao.cfg.db
24
+
23
25
  test('ping', async () => {
24
26
  await dao.ping()
25
27
  })
@@ -91,18 +93,20 @@ export function runCommonKeyValueDaoTest(dao: CommonKeyValueDao<Buffer>): void {
91
93
  expect(results).toEqual([])
92
94
  })
93
95
 
94
- test('increment on a non-existing field should set the value to 1', async () => {
95
- const result = await dao.increment('nonExistingField')
96
- expect(result).toBe(1)
97
- })
96
+ if (support.increment) {
97
+ test('increment on a non-existing field should set the value to 1', async () => {
98
+ const result = await dao.increment('nonExistingField')
99
+ expect(result).toBe(1)
100
+ })
98
101
 
99
- test('increment on a existing field should increase the value by one', async () => {
100
- const result = await dao.increment('nonExistingField')
101
- expect(result).toBe(2)
102
- })
102
+ test('increment on a existing field should increase the value by one', async () => {
103
+ const result = await dao.increment('nonExistingField')
104
+ expect(result).toBe(2)
105
+ })
103
106
 
104
- test('increment should increase the value by the specified amount', async () => {
105
- const result = await dao.increment('nonExistingField', 2)
106
- expect(result).toBe(4)
107
- })
107
+ test('increment should increase the value by the specified amount', async () => {
108
+ const result = await dao.increment('nonExistingField', 2)
109
+ expect(result).toBe(4)
110
+ })
111
+ }
108
112
  }