@naturalcycles/db-lib 9.9.1 → 9.10.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.
@@ -361,6 +361,17 @@ class CommonDao {
361
361
  const partialQuery = !!q._selectedFieldNames;
362
362
  if (partialQuery)
363
363
  return stream;
364
+ // This almost works, but hard to implement `errorMode: THROW_AGGREGATED` in this case
365
+ // return stream.flatMap(async (dbm: DBM) => {
366
+ // if (this.cfg.hooks!.afterLoad) {
367
+ // dbm = (await this.cfg.hooks!.afterLoad(dbm))!
368
+ // if (dbm === null) return [] // SKIP
369
+ // }
370
+ //
371
+ // return [await this.dbmToBM(dbm, opt)] satisfies BM[]
372
+ // }, {
373
+ // concurrency: 16,
374
+ // })
364
375
  return (stream
365
376
  // optimization: 1 validation is enough
366
377
  // .pipe(transformMap<any, DBM>(dbm => this.anyToDBM(dbm, opt), safeOpt))
@@ -376,10 +387,11 @@ class CommonDao {
376
387
  }, {
377
388
  errorMode: opt.errorMode,
378
389
  }))
379
- // this can make the stream async-iteration-friendly
380
- // but not applying it now for perf reasons
381
- // .pipe(transformNoOp())
382
- );
390
+ // this can make the stream async-iteration-friendly
391
+ // but not applying it now for perf reasons
392
+ // UPD: applying, to be compliant with `.toArray()`, etc.
393
+ .on('error', err => stream.emit('error', err))
394
+ .pipe((0, nodejs_lib_1.transformNoOp)()));
383
395
  }
384
396
  async queryIds(q, opt = {}) {
385
397
  q.table = opt.table || q.table;
@@ -389,12 +401,19 @@ class CommonDao {
389
401
  streamQueryIds(q, opt = {}) {
390
402
  q.table = opt.table || q.table;
391
403
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
404
+ // Experimental: using `.map()`
392
405
  const stream = this.cfg.db
393
406
  .streamQuery(q.select(['id']), opt)
394
407
  .on('error', err => stream.emit('error', err))
395
- .pipe((0, nodejs_lib_1.transformMapSimple)(r => r.id, {
396
- errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
397
- }));
408
+ .map((r) => r.id);
409
+ // const stream: ReadableTyped<string> = this.cfg.db
410
+ // .streamQuery<DBM>(q.select(['id']), opt)
411
+ // .on('error', err => stream.emit('error', err))
412
+ // .pipe(
413
+ // transformMapSimple<DBM, string>(r => r.id, {
414
+ // errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
415
+ // }),
416
+ // )
398
417
  return stream;
399
418
  }
400
419
  async streamQueryIdsForEach(q, mapper, opt = {}) {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { KeyValueTuple } from '@naturalcycles/js-lib';
2
+ import { CommonLogger, KeyValueTuple } from '@naturalcycles/js-lib';
3
3
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
4
4
  import { CommonDaoLogLevel } from '../commondao/common.dao.model';
5
5
  import { CommonDBCreateOptions } from '../db.model';
@@ -12,6 +12,10 @@ export interface CommonKeyValueDaoCfg<T> {
12
12
  * Set to true to limit DB writing (will throw an error is such case).
13
13
  */
14
14
  readOnly?: boolean;
15
+ /**
16
+ * Default to console
17
+ */
18
+ logger?: CommonLogger;
15
19
  /**
16
20
  * @default OPERATIONS
17
21
  */
@@ -33,8 +37,11 @@ export interface CommonKeyValueDaoCfg<T> {
33
37
  deflatedJsonValue?: boolean;
34
38
  }
35
39
  export declare class CommonKeyValueDao<T> {
36
- cfg: CommonKeyValueDaoCfg<T>;
37
40
  constructor(cfg: CommonKeyValueDaoCfg<T>);
41
+ cfg: CommonKeyValueDaoCfg<T> & {
42
+ hooks: NonNullable<CommonKeyValueDaoCfg<T>['hooks']>;
43
+ logger: CommonLogger;
44
+ };
38
45
  ping(): Promise<void>;
39
46
  createTable(opt?: CommonDBCreateOptions): Promise<void>;
40
47
  create(input?: Partial<T>): T;
@@ -7,9 +7,13 @@ const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
7
7
  // todo: readonly
8
8
  class CommonKeyValueDao {
9
9
  constructor(cfg) {
10
- this.cfg = cfg;
10
+ this.cfg = {
11
+ hooks: {},
12
+ logger: console,
13
+ ...cfg,
14
+ };
11
15
  if (cfg.deflatedJsonValue) {
12
- cfg.hooks = {
16
+ this.cfg.hooks = {
13
17
  mapValueToBuffer: async (v) => await (0, nodejs_lib_1.deflateString)(JSON.stringify(v)),
14
18
  mapBufferToValue: async (buf) => JSON.parse(await (0, nodejs_lib_1.inflateToString)(buf)),
15
19
  ...cfg.hooks,
@@ -24,7 +28,7 @@ class CommonKeyValueDao {
24
28
  }
25
29
  create(input = {}) {
26
30
  return {
27
- ...this.cfg.hooks?.beforeCreate?.(input),
31
+ ...this.cfg.hooks.beforeCreate?.(input),
28
32
  };
29
33
  }
30
34
  async getById(id) {
@@ -66,7 +70,7 @@ class CommonKeyValueDao {
66
70
  if (r)
67
71
  return r[1];
68
72
  return {
69
- ...this.cfg.hooks?.beforeCreate?.({}),
73
+ ...this.cfg.hooks.beforeCreate?.({}),
70
74
  ...part,
71
75
  };
72
76
  }
@@ -80,7 +84,7 @@ class CommonKeyValueDao {
80
84
  }
81
85
  async getByIds(ids) {
82
86
  const entries = await this.cfg.db.getByIds(this.cfg.table, ids);
83
- if (!this.cfg.hooks?.mapBufferToValue)
87
+ if (!this.cfg.hooks.mapBufferToValue)
84
88
  return entries;
85
89
  return await (0, js_lib_1.pMap)(entries, async ([id, buf]) => [
86
90
  id,
@@ -97,8 +101,8 @@ class CommonKeyValueDao {
97
101
  await this.cfg.db.saveBatch(this.cfg.table, [[id, value]]);
98
102
  }
99
103
  async saveBatch(entries) {
100
- let bufferEntries = [];
101
- if (!this.cfg.hooks?.mapValueToBuffer) {
104
+ let bufferEntries;
105
+ if (!this.cfg.hooks.mapValueToBuffer) {
102
106
  bufferEntries = entries;
103
107
  }
104
108
  else {
@@ -122,29 +126,41 @@ class CommonKeyValueDao {
122
126
  return this.cfg.db.streamIds(this.cfg.table, limit);
123
127
  }
124
128
  streamValues(limit) {
125
- if (!this.cfg.hooks?.mapBufferToValue) {
129
+ const { mapBufferToValue } = this.cfg.hooks;
130
+ if (!mapBufferToValue) {
126
131
  return this.cfg.db.streamValues(this.cfg.table, limit);
127
132
  }
128
- // todo: consider it when readableMap supports `errorMode: SUPPRESS`
129
- // readableMap(this.cfg.db.streamValues(this.cfg.table, limit), async buf => await this.cfg.hooks!.mapBufferToValue(buf))
130
133
  const stream = this.cfg.db
131
134
  .streamValues(this.cfg.table, limit)
132
135
  .on('error', err => stream.emit('error', err))
133
- .pipe((0, nodejs_lib_1.transformMap)(async (buf) => await this.cfg.hooks.mapBufferToValue(buf), {
134
- errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
135
- }));
136
+ .flatMap(async (buf) => {
137
+ try {
138
+ return [await mapBufferToValue(buf)];
139
+ }
140
+ catch (err) {
141
+ this.cfg.logger.error(err);
142
+ return []; // SKIP
143
+ }
144
+ });
136
145
  return stream;
137
146
  }
138
147
  streamEntries(limit) {
139
- if (!this.cfg.hooks?.mapBufferToValue) {
148
+ const { mapBufferToValue } = this.cfg.hooks;
149
+ if (!mapBufferToValue) {
140
150
  return this.cfg.db.streamEntries(this.cfg.table, limit);
141
151
  }
142
152
  const stream = this.cfg.db
143
153
  .streamEntries(this.cfg.table, limit)
144
154
  .on('error', err => stream.emit('error', err))
145
- .pipe((0, nodejs_lib_1.transformMap)(async ([id, buf]) => [id, await this.cfg.hooks.mapBufferToValue(buf)], {
146
- errorMode: js_lib_1.ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
147
- }));
155
+ .flatMap(async ([id, buf]) => {
156
+ try {
157
+ return [[id, await mapBufferToValue(buf)]];
158
+ }
159
+ catch (err) {
160
+ this.cfg.logger.error(err);
161
+ return []; // SKIP
162
+ }
163
+ });
148
164
  return stream;
149
165
  }
150
166
  }
@@ -1,4 +1,4 @@
1
- import { AsyncMemoCache } from '@naturalcycles/js-lib';
1
+ import { AsyncMemoCache, MISS } from '@naturalcycles/js-lib';
2
2
  import { CommonKeyValueDao } from './commonKeyValueDao';
3
3
  /**
4
4
  * AsyncMemoCache implementation, backed by CommonKeyValueDao.
@@ -11,7 +11,7 @@ import { CommonKeyValueDao } from './commonKeyValueDao';
11
11
  export declare class CommonKeyValueDaoMemoCache<VALUE = any> implements AsyncMemoCache<string, VALUE> {
12
12
  private dao;
13
13
  constructor(dao: CommonKeyValueDao<VALUE>);
14
- get(k: string): Promise<VALUE | Error | undefined>;
15
- set(k: string, v: VALUE | Error): Promise<void>;
14
+ get(k: string): Promise<VALUE | typeof MISS>;
15
+ set(k: string, v: VALUE): Promise<void>;
16
16
  clear(): Promise<void>;
17
17
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommonKeyValueDaoMemoCache = void 0;
4
+ const js_lib_1 = require("@naturalcycles/js-lib");
4
5
  /**
5
6
  * AsyncMemoCache implementation, backed by CommonKeyValueDao.
6
7
  *
@@ -14,13 +15,9 @@ class CommonKeyValueDaoMemoCache {
14
15
  this.dao = dao;
15
16
  }
16
17
  async get(k) {
17
- return (await this.dao.getById(k)) || undefined;
18
+ return (await this.dao.getById(k)) || js_lib_1.MISS;
18
19
  }
19
20
  async set(k, v) {
20
- if (v instanceof Error) {
21
- // We currently don't persist errors there
22
- return;
23
- }
24
21
  await this.dao.save(k, v);
25
22
  }
26
23
  async clear() {
@@ -144,9 +144,7 @@ function runCommonDaoTest(db, quirks = {}) {
144
144
  (0, dbTest_1.expectMatch)(expectedItems, rows, quirks);
145
145
  });
146
146
  test('streamQuery all', async () => {
147
- // let rows = await readableToArray(dao.query().streamQuery())
148
- // todo: remove transformNoOp after `transformMap` learns to be async-iteration-friendly
149
- let rows = await (0, nodejs_lib_1.readableToArray)(dao.query().streamQuery().pipe((0, nodejs_lib_1.transformNoOp)()));
147
+ let rows = await dao.query().streamQuery().toArray();
150
148
  rows = (0, js_lib_1._sortBy)(rows, r => r.id);
151
149
  (0, dbTest_1.expectMatch)(expectedItems, rows, quirks);
152
150
  });
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "engines": {
41
41
  "node": ">=18.12"
42
42
  },
43
- "version": "9.9.1",
43
+ "version": "9.10.0",
44
44
  "description": "Lowest Common Denominator API to supported Databases",
45
45
  "keywords": [
46
46
  "db",
package/readme.md CHANGED
@@ -150,7 +150,7 @@ Returns `ReadableTyped` (typed wrapper of Node.js
150
150
 
151
151
  Streams in Node.js support back-pressure by default (if piped properly by the consumer).
152
152
 
153
- ```typescript
153
+ ```ts
154
154
  const q = DBQuery.create('table1') // "return all items" query
155
155
 
156
156
  await _pipeline([
@@ -165,6 +165,14 @@ await _pipeline([
165
165
  // ...
166
166
  ```
167
167
 
168
+ Alternative:
169
+
170
+ ```ts
171
+ await db.streamQuery(q).forEach(item => {
172
+ console.log(item)
173
+ })
174
+ ```
175
+
168
176
  ###### saveBatch
169
177
 
170
178
  `saveBatch<DBM>(table: string, dbms: DBM[]): Promise<void>`
@@ -40,6 +40,7 @@ import {
40
40
  transformLogProgress,
41
41
  transformMap,
42
42
  transformMapSimple,
43
+ transformNoOp,
43
44
  writableVoid,
44
45
  } from '@naturalcycles/nodejs-lib'
45
46
  import { DBLibError } from '../cnst'
@@ -496,6 +497,18 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
496
497
  const partialQuery = !!q._selectedFieldNames
497
498
  if (partialQuery) return stream
498
499
 
500
+ // This almost works, but hard to implement `errorMode: THROW_AGGREGATED` in this case
501
+ // return stream.flatMap(async (dbm: DBM) => {
502
+ // if (this.cfg.hooks!.afterLoad) {
503
+ // dbm = (await this.cfg.hooks!.afterLoad(dbm))!
504
+ // if (dbm === null) return [] // SKIP
505
+ // }
506
+ //
507
+ // return [await this.dbmToBM(dbm, opt)] satisfies BM[]
508
+ // }, {
509
+ // concurrency: 16,
510
+ // })
511
+
499
512
  return (
500
513
  stream
501
514
  // optimization: 1 validation is enough
@@ -517,9 +530,11 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
517
530
  },
518
531
  ),
519
532
  )
520
- // this can make the stream async-iteration-friendly
521
- // but not applying it now for perf reasons
522
- // .pipe(transformNoOp())
533
+ // this can make the stream async-iteration-friendly
534
+ // but not applying it now for perf reasons
535
+ // UPD: applying, to be compliant with `.toArray()`, etc.
536
+ .on('error', err => stream.emit('error', err))
537
+ .pipe(transformNoOp())
523
538
  )
524
539
  }
525
540
 
@@ -533,14 +548,20 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
533
548
  q.table = opt.table || q.table
534
549
  opt.errorMode ||= ErrorMode.SUPPRESS
535
550
 
551
+ // Experimental: using `.map()`
536
552
  const stream: ReadableTyped<string> = this.cfg.db
537
553
  .streamQuery<DBM>(q.select(['id']), opt)
538
554
  .on('error', err => stream.emit('error', err))
539
- .pipe(
540
- transformMapSimple<DBM, string>(r => r.id, {
541
- errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
542
- }),
543
- )
555
+ .map((r: ObjectWithId) => r.id)
556
+
557
+ // const stream: ReadableTyped<string> = this.cfg.db
558
+ // .streamQuery<DBM>(q.select(['id']), opt)
559
+ // .on('error', err => stream.emit('error', err))
560
+ // .pipe(
561
+ // transformMapSimple<DBM, string>(r => r.id, {
562
+ // errorMode: ErrorMode.SUPPRESS, // cause .pipe() cannot propagate errors
563
+ // }),
564
+ // )
544
565
 
545
566
  return stream
546
567
  }
@@ -1,10 +1,5 @@
1
- import { AppError, ErrorMode, KeyValueTuple, pMap } from '@naturalcycles/js-lib'
2
- import {
3
- deflateString,
4
- inflateToString,
5
- ReadableTyped,
6
- transformMap,
7
- } from '@naturalcycles/nodejs-lib'
1
+ import { AppError, CommonLogger, KeyValueTuple, pMap } from '@naturalcycles/js-lib'
2
+ import { deflateString, inflateToString, ReadableTyped } from '@naturalcycles/nodejs-lib'
8
3
  import { CommonDaoLogLevel } from '../commondao/common.dao.model'
9
4
  import { CommonDBCreateOptions } from '../db.model'
10
5
  import { CommonKeyValueDB, KeyValueDBTuple } from './commonKeyValueDB'
@@ -20,6 +15,11 @@ export interface CommonKeyValueDaoCfg<T> {
20
15
  */
21
16
  readOnly?: boolean
22
17
 
18
+ /**
19
+ * Default to console
20
+ */
21
+ logger?: CommonLogger
22
+
23
23
  /**
24
24
  * @default OPERATIONS
25
25
  */
@@ -48,9 +48,15 @@ export interface CommonKeyValueDaoCfg<T> {
48
48
  // todo: readonly
49
49
 
50
50
  export class CommonKeyValueDao<T> {
51
- constructor(public cfg: CommonKeyValueDaoCfg<T>) {
51
+ constructor(cfg: CommonKeyValueDaoCfg<T>) {
52
+ this.cfg = {
53
+ hooks: {},
54
+ logger: console,
55
+ ...cfg,
56
+ }
57
+
52
58
  if (cfg.deflatedJsonValue) {
53
- cfg.hooks = {
59
+ this.cfg.hooks = {
54
60
  mapValueToBuffer: async v => await deflateString(JSON.stringify(v)),
55
61
  mapBufferToValue: async buf => JSON.parse(await inflateToString(buf)),
56
62
  ...cfg.hooks,
@@ -58,6 +64,11 @@ export class CommonKeyValueDao<T> {
58
64
  }
59
65
  }
60
66
 
67
+ cfg: CommonKeyValueDaoCfg<T> & {
68
+ hooks: NonNullable<CommonKeyValueDaoCfg<T>['hooks']>
69
+ logger: CommonLogger
70
+ }
71
+
61
72
  async ping(): Promise<void> {
62
73
  await this.cfg.db.ping()
63
74
  }
@@ -68,7 +79,7 @@ export class CommonKeyValueDao<T> {
68
79
 
69
80
  create(input: Partial<T> = {}): T {
70
81
  return {
71
- ...this.cfg.hooks?.beforeCreate?.(input),
82
+ ...this.cfg.hooks.beforeCreate?.(input),
72
83
  } as T
73
84
  }
74
85
 
@@ -117,7 +128,7 @@ export class CommonKeyValueDao<T> {
117
128
  if (r) return r[1]
118
129
 
119
130
  return {
120
- ...this.cfg.hooks?.beforeCreate?.({}),
131
+ ...this.cfg.hooks.beforeCreate?.({}),
121
132
  ...part,
122
133
  } as T
123
134
  }
@@ -135,11 +146,11 @@ export class CommonKeyValueDao<T> {
135
146
 
136
147
  async getByIds(ids: string[]): Promise<KeyValueTuple<string, T>[]> {
137
148
  const entries = await this.cfg.db.getByIds(this.cfg.table, ids)
138
- if (!this.cfg.hooks?.mapBufferToValue) return entries as any
149
+ if (!this.cfg.hooks.mapBufferToValue) return entries as any
139
150
 
140
151
  return await pMap(entries, async ([id, buf]) => [
141
152
  id,
142
- await this.cfg.hooks!.mapBufferToValue!(buf),
153
+ await this.cfg.hooks.mapBufferToValue!(buf),
143
154
  ])
144
155
  }
145
156
 
@@ -156,14 +167,14 @@ export class CommonKeyValueDao<T> {
156
167
  }
157
168
 
158
169
  async saveBatch(entries: KeyValueTuple<string, T>[]): Promise<void> {
159
- let bufferEntries: KeyValueDBTuple[] = []
170
+ let bufferEntries: KeyValueDBTuple[]
160
171
 
161
- if (!this.cfg.hooks?.mapValueToBuffer) {
172
+ if (!this.cfg.hooks.mapValueToBuffer) {
162
173
  bufferEntries = entries as any
163
174
  } else {
164
175
  bufferEntries = await pMap(entries, async ([id, v]) => [
165
176
  id,
166
- await this.cfg.hooks!.mapValueToBuffer!(v),
177
+ await this.cfg.hooks.mapValueToBuffer!(v),
167
178
  ])
168
179
  }
169
180
 
@@ -187,37 +198,45 @@ export class CommonKeyValueDao<T> {
187
198
  }
188
199
 
189
200
  streamValues(limit?: number): ReadableTyped<T> {
190
- if (!this.cfg.hooks?.mapBufferToValue) {
201
+ const { mapBufferToValue } = this.cfg.hooks
202
+
203
+ if (!mapBufferToValue) {
191
204
  return this.cfg.db.streamValues(this.cfg.table, limit)
192
205
  }
193
206
 
194
- // todo: consider it when readableMap supports `errorMode: SUPPRESS`
195
- // readableMap(this.cfg.db.streamValues(this.cfg.table, limit), async buf => await this.cfg.hooks!.mapBufferToValue(buf))
196
207
  const stream: ReadableTyped<T> = this.cfg.db
197
208
  .streamValues(this.cfg.table, limit)
198
209
  .on('error', err => stream.emit('error', err))
199
- .pipe(
200
- transformMap(async buf => await this.cfg.hooks!.mapBufferToValue!(buf), {
201
- errorMode: ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
202
- }),
203
- )
210
+ .flatMap(async (buf: Buffer) => {
211
+ try {
212
+ return [await mapBufferToValue(buf)] satisfies T[]
213
+ } catch (err) {
214
+ this.cfg.logger.error(err)
215
+ return [] // SKIP
216
+ }
217
+ })
204
218
 
205
219
  return stream
206
220
  }
207
221
 
208
222
  streamEntries(limit?: number): ReadableTyped<KeyValueTuple<string, T>> {
209
- if (!this.cfg.hooks?.mapBufferToValue) {
223
+ const { mapBufferToValue } = this.cfg.hooks
224
+
225
+ if (!mapBufferToValue) {
210
226
  return this.cfg.db.streamEntries(this.cfg.table, limit)
211
227
  }
212
228
 
213
229
  const stream: ReadableTyped<KeyValueTuple<string, T>> = this.cfg.db
214
230
  .streamEntries(this.cfg.table, limit)
215
231
  .on('error', err => stream.emit('error', err))
216
- .pipe(
217
- transformMap(async ([id, buf]) => [id, await this.cfg.hooks!.mapBufferToValue!(buf)], {
218
- errorMode: ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
219
- }),
220
- )
232
+ .flatMap(async ([id, buf]: KeyValueTuple<string, Buffer>) => {
233
+ try {
234
+ return [[id, await mapBufferToValue(buf)]] satisfies KeyValueTuple<string, T>[]
235
+ } catch (err) {
236
+ this.cfg.logger.error(err)
237
+ return [] // SKIP
238
+ }
239
+ })
221
240
 
222
241
  return stream
223
242
  }
@@ -1,4 +1,4 @@
1
- import { AsyncMemoCache } from '@naturalcycles/js-lib'
1
+ import { AsyncMemoCache, MISS } from '@naturalcycles/js-lib'
2
2
  import { CommonKeyValueDao } from './commonKeyValueDao'
3
3
 
4
4
  /**
@@ -12,16 +12,11 @@ import { CommonKeyValueDao } from './commonKeyValueDao'
12
12
  export class CommonKeyValueDaoMemoCache<VALUE = any> implements AsyncMemoCache<string, VALUE> {
13
13
  constructor(private dao: CommonKeyValueDao<VALUE>) {}
14
14
 
15
- async get(k: string): Promise<VALUE | Error | undefined> {
16
- return (await this.dao.getById(k)) || undefined
15
+ async get(k: string): Promise<VALUE | typeof MISS> {
16
+ return (await this.dao.getById(k)) || MISS
17
17
  }
18
18
 
19
- async set(k: string, v: VALUE | Error): Promise<void> {
20
- if (v instanceof Error) {
21
- // We currently don't persist errors there
22
- return
23
- }
24
-
19
+ async set(k: string, v: VALUE): Promise<void> {
25
20
  await this.dao.save(k, v)
26
21
  }
27
22
 
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'node:stream'
2
2
  import { _deepCopy, _pick, _sortBy, _omit, localTimeNow } from '@naturalcycles/js-lib'
3
- import { _pipeline, readableToArray, transformNoOp } from '@naturalcycles/nodejs-lib'
3
+ import { _pipeline, readableToArray } from '@naturalcycles/nodejs-lib'
4
4
  import { CommonDaoLogLevel, DBQuery } from '..'
5
5
  import { CommonDB } from '../common.db'
6
6
  import { CommonDao } from '../commondao/common.dao'
@@ -194,11 +194,7 @@ export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQui
194
194
  })
195
195
 
196
196
  test('streamQuery all', async () => {
197
- // let rows = await readableToArray(dao.query().streamQuery())
198
- // todo: remove transformNoOp after `transformMap` learns to be async-iteration-friendly
199
- let rows: TestItemBM[] = await readableToArray(
200
- dao.query().streamQuery().pipe(transformNoOp()),
201
- )
197
+ let rows: TestItemBM[] = await dao.query().streamQuery().toArray()
202
198
 
203
199
  rows = _sortBy(rows, r => r.id)
204
200
  expectMatch(expectedItems, rows, quirks)