@naturalcycles/db-lib 9.18.0 → 9.20.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.
@@ -17,4 +17,5 @@ export declare class InMemoryKeyValueDB implements CommonKeyValueDB {
17
17
  streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
18
18
  streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
19
19
  count(table: string): Promise<number>;
20
+ increment(table: string, id: string, by?: number): Promise<number>;
20
21
  }
@@ -35,5 +35,12 @@ class InMemoryKeyValueDB {
35
35
  this.data[table] ||= {};
36
36
  return Object.keys(this.data[table]).length;
37
37
  }
38
+ async increment(table, id, by = 1) {
39
+ this.data[table] ||= {};
40
+ const currentValue = this.data[table][id] ? parseInt(this.data[table][id].toString()) : 0;
41
+ const newValue = currentValue + by;
42
+ this.data[table][id] = Buffer.from(String(newValue));
43
+ return newValue;
44
+ }
38
45
  }
39
46
  exports.InMemoryKeyValueDB = InMemoryKeyValueDB;
@@ -36,4 +36,12 @@ export interface CommonKeyValueDB {
36
36
  streamValues: (table: string, limit?: number) => ReadableTyped<Buffer>;
37
37
  streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>;
38
38
  count: (table: string) => Promise<number>;
39
+ /**
40
+ *
41
+ * Increments the value of a key in a table by a given amount.
42
+ * Default increment is 1 when `by` is not provided.
43
+ *
44
+ * Returns the new value.
45
+ */
46
+ increment: (table: string, id: string, by?: number) => Promise<number>;
39
47
  }
@@ -36,30 +36,37 @@ 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>;
60
+ deleteByIds(ids: K[]): Promise<void>;
61
+ deleteById(id: K): Promise<void>;
62
62
  streamIds(limit?: number): ReadableTyped<string>;
63
- streamValues(limit?: number): ReadableTyped<T>;
64
- streamEntries(limit?: number): ReadableTyped<KeyValueTuple<string, T>>;
63
+ streamValues(limit?: number): ReadableTyped<V>;
64
+ streamEntries(limit?: number): ReadableTyped<KeyValueTuple<K, V>>;
65
+ /**
66
+ * Increments the `id` field by the amount specified in `by`,
67
+ * or by 1 if `by` is not specified.
68
+ *
69
+ * Returns the new value of the field.
70
+ */
71
+ increment(id: K, by?: number): Promise<number>;
65
72
  }
@@ -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,5 +157,14 @@ class CommonKeyValueDao {
157
157
  concurrency: 32,
158
158
  });
159
159
  }
160
+ /**
161
+ * Increments the `id` field by the amount specified in `by`,
162
+ * or by 1 if `by` is not specified.
163
+ *
164
+ * Returns the new value of the field.
165
+ */
166
+ async increment(id, by = 1) {
167
+ return await this.cfg.db.increment(this.cfg.table, id, by);
168
+ }
160
169
  }
161
170
  exports.CommonKeyValueDao = CommonKeyValueDao;
@@ -1,6 +1,7 @@
1
1
  import { runCommonDaoTest } from './daoTest';
2
2
  import { CommonDBImplementationQuirks, runCommonDBTest } from './dbTest';
3
+ import { runCommonKeyValueDaoTest } from './keyValueDaoTest';
3
4
  import { runCommonKeyValueDBTest } from './keyValueDBTest';
4
5
  import { createTestItemBM, createTestItemDBM, createTestItemsBM, createTestItemsDBM, TEST_TABLE, TestItemBM, testItemBMJsonSchema, testItemBMSchema, TestItemDBM, TestItemTM, testItemTMSchema } from './test.model';
5
6
  export type { CommonDBImplementationQuirks, TestItemBM, TestItemDBM, TestItemTM };
6
- export { createTestItemBM, createTestItemDBM, createTestItemsBM, createTestItemsDBM, runCommonDaoTest, runCommonDBTest, runCommonKeyValueDBTest, TEST_TABLE, testItemBMJsonSchema, testItemBMSchema, testItemTMSchema, };
7
+ export { createTestItemBM, createTestItemDBM, createTestItemsBM, createTestItemsDBM, runCommonDaoTest, runCommonDBTest, runCommonKeyValueDaoTest, runCommonKeyValueDBTest, TEST_TABLE, testItemBMJsonSchema, testItemBMSchema, testItemTMSchema, };
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.testItemTMSchema = exports.testItemBMSchema = exports.testItemBMJsonSchema = exports.TEST_TABLE = exports.runCommonKeyValueDBTest = exports.runCommonDBTest = exports.runCommonDaoTest = exports.createTestItemsDBM = exports.createTestItemsBM = exports.createTestItemDBM = exports.createTestItemBM = void 0;
3
+ exports.testItemTMSchema = exports.testItemBMSchema = exports.testItemBMJsonSchema = exports.TEST_TABLE = exports.runCommonKeyValueDBTest = exports.runCommonKeyValueDaoTest = exports.runCommonDBTest = exports.runCommonDaoTest = exports.createTestItemsDBM = exports.createTestItemsBM = exports.createTestItemDBM = exports.createTestItemBM = void 0;
4
4
  const daoTest_1 = require("./daoTest");
5
5
  Object.defineProperty(exports, "runCommonDaoTest", { enumerable: true, get: function () { return daoTest_1.runCommonDaoTest; } });
6
6
  const dbTest_1 = require("./dbTest");
7
7
  Object.defineProperty(exports, "runCommonDBTest", { enumerable: true, get: function () { return dbTest_1.runCommonDBTest; } });
8
+ const keyValueDaoTest_1 = require("./keyValueDaoTest");
9
+ Object.defineProperty(exports, "runCommonKeyValueDaoTest", { enumerable: true, get: function () { return keyValueDaoTest_1.runCommonKeyValueDaoTest; } });
8
10
  const keyValueDBTest_1 = require("./keyValueDBTest");
9
11
  Object.defineProperty(exports, "runCommonKeyValueDBTest", { enumerable: true, get: function () { return keyValueDBTest_1.runCommonKeyValueDBTest; } });
10
12
  const test_model_1 = require("./test.model");
@@ -6,6 +6,18 @@ const test_model_1 = require("./test.model");
6
6
  const testIds = (0, js_lib_1._range)(1, 4).map(n => `id${n}`);
7
7
  const testEntries = testIds.map(id => [id, Buffer.from(`${id}value`)]);
8
8
  function runCommonKeyValueDBTest(db) {
9
+ beforeAll(async () => {
10
+ // Tests in this suite are not isolated,
11
+ // and failing tests can leave the DB in an unexpected state for other tests,
12
+ // including the following test run.
13
+ // Here we clear the table before running the tests.
14
+ const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
15
+ await db.deleteByIds(test_model_1.TEST_TABLE, ids);
16
+ });
17
+ afterAll(async () => {
18
+ const ids = await db.streamIds(test_model_1.TEST_TABLE).toArray();
19
+ await db.deleteByIds(test_model_1.TEST_TABLE, ids);
20
+ });
9
21
  test('ping', async () => {
10
22
  await db.ping();
11
23
  });
@@ -70,4 +82,16 @@ function runCommonKeyValueDBTest(db) {
70
82
  const results = await db.getByIds(test_model_1.TEST_TABLE, testIds);
71
83
  expect(results).toEqual([]);
72
84
  });
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
+ });
73
97
  }
@@ -5,6 +5,18 @@ const js_lib_1 = require("@naturalcycles/js-lib");
5
5
  const testIds = (0, js_lib_1._range)(1, 4).map(n => `id${n}`);
6
6
  const testEntries = testIds.map(id => [id, Buffer.from(`${id}value`)]);
7
7
  function runCommonKeyValueDaoTest(dao) {
8
+ beforeAll(async () => {
9
+ // Tests in this suite are not isolated,
10
+ // and failing tests can leave the DB in an unexpected state for other tests,
11
+ // including the following test run.
12
+ // Here we clear the table before running the tests.
13
+ const ids = await dao.streamIds().toArray();
14
+ await dao.deleteByIds(ids);
15
+ });
16
+ afterAll(async () => {
17
+ const ids = await dao.streamIds().toArray();
18
+ await dao.deleteByIds(ids);
19
+ });
8
20
  test('ping', async () => {
9
21
  await dao.ping();
10
22
  });
@@ -63,4 +75,16 @@ function runCommonKeyValueDaoTest(dao) {
63
75
  const results = await dao.getByIds(testIds);
64
76
  expect(results).toEqual([]);
65
77
  });
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
+ });
66
90
  }
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  "engines": {
46
46
  "node": ">=20.13"
47
47
  },
48
- "version": "9.18.0",
48
+ "version": "9.20.0",
49
49
  "description": "Lowest Common Denominator API to supported Databases",
50
50
  "keywords": [
51
51
  "db",
@@ -47,4 +47,14 @@ export class InMemoryKeyValueDB implements CommonKeyValueDB {
47
47
  this.data[table] ||= {}
48
48
  return Object.keys(this.data[table]).length
49
49
  }
50
+
51
+ async increment(table: string, id: string, by = 1): Promise<number> {
52
+ this.data[table] ||= {}
53
+
54
+ const currentValue = this.data[table][id] ? parseInt(this.data[table][id].toString()) : 0
55
+ const newValue = currentValue + by
56
+ this.data[table][id] = Buffer.from(String(newValue))
57
+
58
+ return newValue
59
+ }
50
60
  }
@@ -49,4 +49,13 @@ export interface CommonKeyValueDB {
49
49
  streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>
50
50
 
51
51
  count: (table: string) => Promise<number>
52
+
53
+ /**
54
+ *
55
+ * Increments the value of a key in a table by a given amount.
56
+ * Default increment is 1 when `by` is not provided.
57
+ *
58
+ * Returns the new value.
59
+ */
60
+ increment: (table: string, id: string, by?: number) => Promise<number>
52
61
  }
@@ -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,11 +195,11 @@ 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
 
@@ -207,11 +207,11 @@ export class CommonKeyValueDao<T> {
207
207
  return this.cfg.db.streamIds(this.cfg.table, limit)
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,19 +229,17 @@ 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
239
  return this.cfg.db.streamEntries(this.cfg.table, limit).flatMap(
242
240
  async ([id, buf]) => {
243
241
  try {
244
- return [[id, await mapBufferToValue(buf)]]
242
+ return [[id as K, await mapBufferToValue(buf)]]
245
243
  } catch (err) {
246
244
  this.cfg.logger.error(err)
247
245
  return [] // SKIP
@@ -252,4 +250,14 @@ export class CommonKeyValueDao<T> {
252
250
  },
253
251
  )
254
252
  }
253
+
254
+ /**
255
+ * Increments the `id` field by the amount specified in `by`,
256
+ * or by 1 if `by` is not specified.
257
+ *
258
+ * Returns the new value of the field.
259
+ */
260
+ async increment(id: K, by = 1): Promise<number> {
261
+ return await this.cfg.db.increment(this.cfg.table, id, by)
262
+ }
255
263
  }
@@ -1,5 +1,6 @@
1
1
  import { runCommonDaoTest } from './daoTest'
2
2
  import { CommonDBImplementationQuirks, runCommonDBTest } from './dbTest'
3
+ import { runCommonKeyValueDaoTest } from './keyValueDaoTest'
3
4
  import { runCommonKeyValueDBTest } from './keyValueDBTest'
4
5
  import {
5
6
  createTestItemBM,
@@ -24,6 +25,7 @@ export {
24
25
  createTestItemsDBM,
25
26
  runCommonDaoTest,
26
27
  runCommonDBTest,
28
+ runCommonKeyValueDaoTest,
27
29
  runCommonKeyValueDBTest,
28
30
  TEST_TABLE,
29
31
  testItemBMJsonSchema,
@@ -7,6 +7,20 @@ const testIds = _range(1, 4).map(n => `id${n}`)
7
7
  const testEntries: KeyValueDBTuple[] = testIds.map(id => [id, Buffer.from(`${id}value`)])
8
8
 
9
9
  export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
10
+ beforeAll(async () => {
11
+ // Tests in this suite are not isolated,
12
+ // and failing tests can leave the DB in an unexpected state for other tests,
13
+ // including the following test run.
14
+ // Here we clear the table before running the tests.
15
+ const ids = await db.streamIds(TEST_TABLE).toArray()
16
+ await db.deleteByIds(TEST_TABLE, ids)
17
+ })
18
+
19
+ afterAll(async () => {
20
+ const ids = await db.streamIds(TEST_TABLE).toArray()
21
+ await db.deleteByIds(TEST_TABLE, ids)
22
+ })
23
+
10
24
  test('ping', async () => {
11
25
  await db.ping()
12
26
  })
@@ -85,4 +99,19 @@ export function runCommonKeyValueDBTest(db: CommonKeyValueDB): void {
85
99
  const results = await db.getByIds(TEST_TABLE, testIds)
86
100
  expect(results).toEqual([])
87
101
  })
102
+
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
+
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
+ })
112
+
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
+ })
88
117
  }
@@ -6,6 +6,20 @@ const testIds = _range(1, 4).map(n => `id${n}`)
6
6
  const testEntries: KeyValueDBTuple[] = testIds.map(id => [id, Buffer.from(`${id}value`)])
7
7
 
8
8
  export function runCommonKeyValueDaoTest(dao: CommonKeyValueDao<Buffer>): void {
9
+ beforeAll(async () => {
10
+ // Tests in this suite are not isolated,
11
+ // and failing tests can leave the DB in an unexpected state for other tests,
12
+ // including the following test run.
13
+ // Here we clear the table before running the tests.
14
+ const ids = await dao.streamIds().toArray()
15
+ await dao.deleteByIds(ids)
16
+ })
17
+
18
+ afterAll(async () => {
19
+ const ids = await dao.streamIds().toArray()
20
+ await dao.deleteByIds(ids)
21
+ })
22
+
9
23
  test('ping', async () => {
10
24
  await dao.ping()
11
25
  })
@@ -76,4 +90,19 @@ export function runCommonKeyValueDaoTest(dao: CommonKeyValueDao<Buffer>): void {
76
90
  const results = await dao.getByIds(testIds)
77
91
  expect(results).toEqual([])
78
92
  })
93
+
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
+ })
98
+
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
+ })
103
+
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
+ })
79
108
  }