@naturalcycles/db-lib 9.19.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
@@ -36,37 +36,40 @@ export interface CommonKeyValueDaoCfg<T> {
36
36
  deflatedJsonValue?: boolean;
37
37
  }
38
38
  export type CommonKeyValueDaoSaveOptions = CommonKeyValueDBSaveBatchOptions;
39
- export declare class CommonKeyValueDao<T> {
40
- constructor(cfg: CommonKeyValueDaoCfg<T>);
41
- cfg: CommonKeyValueDaoCfg<T> & {
42
- hooks: NonNullable<CommonKeyValueDaoCfg<T>['hooks']>;
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']>;
43
43
  logger: CommonLogger;
44
44
  };
45
45
  ping(): Promise<void>;
46
46
  createTable(opt?: CommonDBCreateOptions): Promise<void>;
47
- create(input?: Partial<T>): T;
48
- getById(id?: string): Promise<T | null>;
49
- getByIdAsBuffer(id?: string): Promise<Buffer | null>;
50
- requireById(id: string): Promise<T>;
51
- requireByIdAsBuffer(id: string): Promise<Buffer>;
52
- getByIdOrEmpty(id: string, part?: Partial<T>): Promise<T>;
53
- patch(id: string, patch: Partial<T>, opt?: CommonKeyValueDaoSaveOptions): Promise<T>;
54
- getByIds(ids: string[]): Promise<KeyValueTuple<string, T>[]>;
55
- getByIdsAsBuffer(ids: string[]): Promise<KeyValueTuple<string, Buffer>[]>;
56
- save(id: string, value: T, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
57
- saveAsBuffer(id: string, value: Buffer, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
58
- saveBatch(entries: KeyValueTuple<string, T>[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
47
+ create(input?: Partial<V>): V;
48
+ getById(id?: K): Promise<V | null>;
49
+ getByIdAsBuffer(id?: K): Promise<Buffer | null>;
50
+ 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>;
54
+ getByIds(ids: K[]): Promise<KeyValueTuple<string, V>[]>;
55
+ getByIdsAsBuffer(ids: K[]): Promise<KeyValueTuple<K, Buffer>[]>;
56
+ save(id: K, value: V, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
57
+ saveAsBuffer(id: K, value: Buffer, opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
58
+ saveBatch(entries: KeyValueTuple<K, V>[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
59
59
  saveBatchAsBuffer(entries: KeyValueDBTuple[], opt?: CommonKeyValueDaoSaveOptions): Promise<void>;
60
- deleteByIds(ids: string[]): Promise<void>;
61
- deleteById(id: string): Promise<void>;
62
- streamIds(limit?: number): ReadableTyped<string>;
63
- streamValues(limit?: number): ReadableTyped<T>;
64
- streamEntries(limit?: number): ReadableTyped<KeyValueTuple<string, T>>;
60
+ deleteByIds(ids: K[]): Promise<void>;
61
+ deleteById(id: K): Promise<void>;
62
+ streamIds(limit?: number): ReadableTyped<K>;
63
+ streamValues(limit?: number): ReadableTyped<V>;
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.
68
71
  *
69
72
  * Returns the new value of the field.
70
73
  */
71
- increment(id: string, by?: number): Promise<number>;
74
+ increment(id: K, by?: number): Promise<number>;
72
75
  }
@@ -92,7 +92,7 @@ class CommonKeyValueDao {
92
92
  ]);
93
93
  }
94
94
  async getByIdsAsBuffer(ids) {
95
- return await this.cfg.db.getByIds(this.cfg.table, ids);
95
+ return (await this.cfg.db.getByIds(this.cfg.table, ids));
96
96
  }
97
97
  async save(id, value, opt) {
98
98
  await this.saveBatch([[id, value]], opt);
@@ -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.19.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
  /**
@@ -53,8 +53,8 @@ export type CommonKeyValueDaoSaveOptions = CommonKeyValueDBSaveBatchOptions
53
53
  // todo: logging
54
54
  // todo: readonly
55
55
 
56
- export class CommonKeyValueDao<T> {
57
- constructor(cfg: CommonKeyValueDaoCfg<T>) {
56
+ export class CommonKeyValueDao<V, K extends string = string> {
57
+ constructor(cfg: CommonKeyValueDaoCfg<V>) {
58
58
  this.cfg = {
59
59
  hooks: {},
60
60
  logger: console,
@@ -70,8 +70,8 @@ export class CommonKeyValueDao<T> {
70
70
  }
71
71
  }
72
72
 
73
- cfg: CommonKeyValueDaoCfg<T> & {
74
- hooks: NonNullable<CommonKeyValueDaoCfg<T>['hooks']>
73
+ cfg: CommonKeyValueDaoCfg<V> & {
74
+ hooks: NonNullable<CommonKeyValueDaoCfg<V>['hooks']>
75
75
  logger: CommonLogger
76
76
  }
77
77
 
@@ -83,25 +83,25 @@ export class CommonKeyValueDao<T> {
83
83
  await this.cfg.db.createTable(this.cfg.table, opt)
84
84
  }
85
85
 
86
- create(input: Partial<T> = {}): T {
86
+ create(input: Partial<V> = {}): V {
87
87
  return {
88
88
  ...this.cfg.hooks.beforeCreate?.(input),
89
- } as T
89
+ } as V
90
90
  }
91
91
 
92
- async getById(id?: string): Promise<T | null> {
92
+ async getById(id?: K): Promise<V | null> {
93
93
  if (!id) return null
94
94
  const [r] = await this.getByIds([id])
95
95
  return r?.[1] || null
96
96
  }
97
97
 
98
- async getByIdAsBuffer(id?: string): Promise<Buffer | null> {
98
+ async getByIdAsBuffer(id?: K): Promise<Buffer | null> {
99
99
  if (!id) return null
100
100
  const [r] = await this.cfg.db.getByIds(this.cfg.table, [id])
101
101
  return r?.[1] || null
102
102
  }
103
103
 
104
- async requireById(id: string): Promise<T> {
104
+ async requireById(id: K): Promise<V> {
105
105
  const [r] = await this.getByIds([id])
106
106
 
107
107
  if (!r) {
@@ -115,7 +115,7 @@ export class CommonKeyValueDao<T> {
115
115
  return r[1]
116
116
  }
117
117
 
118
- async requireByIdAsBuffer(id: string): Promise<Buffer> {
118
+ async requireByIdAsBuffer(id: K): Promise<Buffer> {
119
119
  const [r] = await this.cfg.db.getByIds(this.cfg.table, [id])
120
120
 
121
121
  if (!r) {
@@ -129,18 +129,18 @@ export class CommonKeyValueDao<T> {
129
129
  return r[1]
130
130
  }
131
131
 
132
- async getByIdOrEmpty(id: string, part: Partial<T> = {}): Promise<T> {
132
+ async getByIdOrEmpty(id: K, part: Partial<V> = {}): Promise<V> {
133
133
  const [r] = await this.getByIds([id])
134
134
  if (r) return r[1]
135
135
 
136
136
  return {
137
137
  ...this.cfg.hooks.beforeCreate?.({}),
138
138
  ...part,
139
- } as T
139
+ } as V
140
140
  }
141
141
 
142
- async patch(id: string, patch: Partial<T>, opt?: CommonKeyValueDaoSaveOptions): Promise<T> {
143
- const v: T = {
142
+ async patch(id: K, patch: Partial<V>, opt?: CommonKeyValueDaoSaveOptions): Promise<V> {
143
+ const v: V = {
144
144
  ...(await this.getByIdOrEmpty(id)),
145
145
  ...patch,
146
146
  }
@@ -150,7 +150,7 @@ export class CommonKeyValueDao<T> {
150
150
  return v
151
151
  }
152
152
 
153
- async getByIds(ids: string[]): Promise<KeyValueTuple<string, T>[]> {
153
+ async getByIds(ids: K[]): Promise<KeyValueTuple<string, V>[]> {
154
154
  const entries = await this.cfg.db.getByIds(this.cfg.table, ids)
155
155
  if (!this.cfg.hooks.mapBufferToValue) return entries as any
156
156
 
@@ -160,20 +160,20 @@ export class CommonKeyValueDao<T> {
160
160
  ])
161
161
  }
162
162
 
163
- async getByIdsAsBuffer(ids: string[]): Promise<KeyValueTuple<string, Buffer>[]> {
164
- return await this.cfg.db.getByIds(this.cfg.table, ids)
163
+ async getByIdsAsBuffer(ids: K[]): Promise<KeyValueTuple<K, Buffer>[]> {
164
+ return (await this.cfg.db.getByIds(this.cfg.table, ids)) as KeyValueTuple<K, Buffer>[]
165
165
  }
166
166
 
167
- async save(id: string, value: T, opt?: CommonKeyValueDaoSaveOptions): Promise<void> {
167
+ async save(id: K, value: V, opt?: CommonKeyValueDaoSaveOptions): Promise<void> {
168
168
  await this.saveBatch([[id, value]], opt)
169
169
  }
170
170
 
171
- async saveAsBuffer(id: string, value: Buffer, opt?: CommonKeyValueDaoSaveOptions): Promise<void> {
171
+ async saveAsBuffer(id: K, value: Buffer, opt?: CommonKeyValueDaoSaveOptions): Promise<void> {
172
172
  await this.cfg.db.saveBatch(this.cfg.table, [[id, value]], opt)
173
173
  }
174
174
 
175
175
  async saveBatch(
176
- entries: KeyValueTuple<string, T>[],
176
+ entries: KeyValueTuple<K, V>[],
177
177
  opt?: CommonKeyValueDaoSaveOptions,
178
178
  ): Promise<void> {
179
179
  const { mapValueToBuffer } = this.cfg.hooks
@@ -195,23 +195,23 @@ export class CommonKeyValueDao<T> {
195
195
  await this.cfg.db.saveBatch(this.cfg.table, entries, opt)
196
196
  }
197
197
 
198
- async deleteByIds(ids: string[]): Promise<void> {
198
+ async deleteByIds(ids: K[]): Promise<void> {
199
199
  await this.cfg.db.deleteByIds(this.cfg.table, ids)
200
200
  }
201
201
 
202
- async deleteById(id: string): Promise<void> {
202
+ async deleteById(id: K): Promise<void> {
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
- streamValues(limit?: number): ReadableTyped<T> {
210
+ streamValues(limit?: number): ReadableTyped<V> {
211
211
  const { mapBufferToValue } = this.cfg.hooks
212
212
 
213
213
  if (!mapBufferToValue) {
214
- return this.cfg.db.streamValues(this.cfg.table, limit) as ReadableTyped<T>
214
+ return this.cfg.db.streamValues(this.cfg.table, limit) as ReadableTyped<V>
215
215
  }
216
216
 
217
217
  return this.cfg.db.streamValues(this.cfg.table, limit).flatMap(
@@ -229,16 +229,16 @@ export class CommonKeyValueDao<T> {
229
229
  )
230
230
  }
231
231
 
232
- streamEntries(limit?: number): ReadableTyped<KeyValueTuple<string, T>> {
232
+ streamEntries(limit?: number): ReadableTyped<KeyValueTuple<K, V>> {
233
233
  const { mapBufferToValue } = this.cfg.hooks
234
234
 
235
235
  if (!mapBufferToValue) {
236
- return this.cfg.db.streamEntries(this.cfg.table, limit) as ReadableTyped<
237
- KeyValueTuple<string, T>
238
- >
236
+ return this.cfg.db.streamEntries(this.cfg.table, limit) as ReadableTyped<KeyValueTuple<K, V>>
239
237
  }
240
238
 
241
- 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(
242
242
  async ([id, buf]) => {
243
243
  try {
244
244
  return [[id, await mapBufferToValue(buf)]]
@@ -253,13 +253,25 @@ export class CommonKeyValueDao<T> {
253
253
  )
254
254
  }
255
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
+
256
268
  /**
257
269
  * Increments the `id` field by the amount specified in `by`,
258
270
  * or by 1 if `by` is not specified.
259
271
  *
260
272
  * Returns the new value of the field.
261
273
  */
262
- async increment(id: string, by = 1): Promise<number> {
274
+ async increment(id: K, by = 1): Promise<number> {
263
275
  return await this.cfg.db.increment(this.cfg.table, id, by)
264
276
  }
265
277
  }
@@ -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
  }