@naturalcycles/db-lib 9.15.1 → 9.17.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.
@@ -31,8 +31,9 @@ function queryInMemory(q, rows = []) {
31
31
  if (order) {
32
32
  const { name, descending } = order;
33
33
  rows = rows.sort((a, b) => {
34
+ // biome-ignore lint/suspicious/noDoubleEquals: ok
34
35
  if (a[name] == b[name])
35
- return 0; // eslint-disable-line eqeqeq
36
+ return 0;
36
37
  if (descending) {
37
38
  return a[name] < b[name] ? 1 : -1;
38
39
  }
@@ -12,15 +12,15 @@ export declare class BaseCommonDB implements CommonDB {
12
12
  support: CommonDBSupport;
13
13
  ping(): Promise<void>;
14
14
  getTables(): Promise<string[]>;
15
- getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
16
- createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>): Promise<void>;
17
- getByIds<ROW extends ObjectWithId>(table: string, ids: string[]): Promise<ROW[]>;
18
- deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number>;
19
- updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CommonDBOptions): Promise<number>;
20
- runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
21
- runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number>;
22
- saveBatch<ROW extends ObjectWithId>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
23
- streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): ReadableTyped<ROW>;
24
- deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number>;
25
- runInTransaction(fn: DBTransactionFn, opt?: CommonDBTransactionOptions): Promise<void>;
15
+ getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<JsonSchemaRootObject<ROW>>;
16
+ createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>): Promise<void>;
17
+ getByIds<ROW extends ObjectWithId>(_table: string, _ids: string[]): Promise<ROW[]>;
18
+ deleteByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
19
+ updateByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>, _patch: DBPatch<ROW>, _opt?: CommonDBOptions): Promise<number>;
20
+ runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>>;
21
+ runQueryCount<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number>;
22
+ saveBatch<ROW extends ObjectWithId>(_table: string, _rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
23
+ streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): ReadableTyped<ROW>;
24
+ deleteByIds(_table: string, _ids: string[], _opt?: CommonDBOptions): Promise<number>;
25
+ runInTransaction(fn: DBTransactionFn, _opt?: CommonDBTransactionOptions): Promise<void>;
26
26
  }
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseCommonDB = void 0;
4
4
  const common_db_1 = require("./common.db");
5
5
  const dbTransaction_util_1 = require("./transaction/dbTransaction.util");
6
- /* eslint-disable unused-imports/no-unused-vars */
7
6
  /**
8
7
  * No-op implementation of CommonDB interface.
9
8
  * To be extended by actual implementations.
@@ -19,37 +18,37 @@ class BaseCommonDB {
19
18
  async getTables() {
20
19
  throw new Error('getTables is not implemented');
21
20
  }
22
- async getTableSchema(table) {
21
+ async getTableSchema(_table) {
23
22
  throw new Error('getTableSchema is not implemented');
24
23
  }
25
- async createTable(table, schema) {
24
+ async createTable(_table, _schema) {
26
25
  // no-op
27
26
  }
28
- async getByIds(table, ids) {
27
+ async getByIds(_table, _ids) {
29
28
  throw new Error('getByIds is not implemented');
30
29
  }
31
- async deleteByQuery(q) {
30
+ async deleteByQuery(_q) {
32
31
  throw new Error('deleteByQuery is not implemented');
33
32
  }
34
- async updateByQuery(q, patch, opt) {
33
+ async updateByQuery(_q, _patch, _opt) {
35
34
  throw new Error('updateByQuery is not implemented');
36
35
  }
37
- async runQuery(q) {
36
+ async runQuery(_q) {
38
37
  throw new Error('runQuery is not implemented');
39
38
  }
40
- async runQueryCount(q) {
39
+ async runQueryCount(_q) {
41
40
  throw new Error('runQueryCount is not implemented');
42
41
  }
43
- async saveBatch(table, rows, opt) {
42
+ async saveBatch(_table, _rows, _opt) {
44
43
  throw new Error('saveBatch is not implemented');
45
44
  }
46
- streamQuery(q) {
45
+ streamQuery(_q) {
47
46
  throw new Error('streamQuery is not implemented');
48
47
  }
49
- async deleteByIds(table, ids, opt) {
48
+ async deleteByIds(_table, _ids, _opt) {
50
49
  throw new Error('deleteByIds is not implemented');
51
50
  }
52
- async runInTransaction(fn, opt) {
51
+ async runInTransaction(fn, _opt) {
53
52
  const tx = new dbTransaction_util_1.FakeDBTransaction(this);
54
53
  await fn(tx);
55
54
  // there's no try/catch and rollback, as there's nothing to rollback
@@ -11,19 +11,19 @@ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoPatchB
11
11
  * BM = Backend model (optimized for API access)
12
12
  * TM = Transport model (optimized to be sent over the wire)
13
13
  */
14
- export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
15
- cfg: CommonDaoCfg<BM, DBM>;
16
- constructor(cfg: CommonDaoCfg<BM, DBM>);
14
+ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, ID = BM['id']> {
15
+ cfg: CommonDaoCfg<BM, DBM, ID>;
16
+ constructor(cfg: CommonDaoCfg<BM, DBM, ID>);
17
17
  create(part?: Partial<BM>, opt?: CommonDaoOptions): BM;
18
18
  getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
19
- getById(id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
20
- getByIdOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<BM>;
19
+ getById(id?: ID | null, opt?: CommonDaoOptions): Promise<BM | null>;
20
+ getByIdOrEmpty(id: ID, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<BM>;
21
21
  getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
22
- getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>;
23
- getByIds(ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
24
- getByIdsAsDBM(ids: string[], opt?: CommonDaoOptions): Promise<DBM[]>;
25
- requireById(id: string, opt?: CommonDaoOptions): Promise<BM>;
26
- requireByIdAsDBM(id: string, opt?: CommonDaoOptions): Promise<DBM>;
22
+ getByIdAsDBM(id?: ID | null, opt?: CommonDaoOptions): Promise<DBM | null>;
23
+ getByIds(ids: ID[], opt?: CommonDaoOptions): Promise<BM[]>;
24
+ getByIdsAsDBM(ids: ID[], opt?: CommonDaoOptions): Promise<DBM[]>;
25
+ requireById(id: ID, opt?: CommonDaoOptions): Promise<BM>;
26
+ requireByIdAsDBM(id: ID, opt?: CommonDaoOptions): Promise<DBM>;
27
27
  private throwRequiredError;
28
28
  /**
29
29
  * Throws if readOnly is true
@@ -40,7 +40,7 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
40
40
  /**
41
41
  * Pass `table` to override table
42
42
  */
43
- query(table?: string): RunnableDBQuery<BM, DBM>;
43
+ query(table?: string): RunnableDBQuery<BM, DBM, ID>;
44
44
  runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<BM[]>;
45
45
  runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]>;
46
46
  /**
@@ -69,9 +69,9 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
69
69
  * You can do `.pipe(transformNoOp)` to make it "valid again".
70
70
  */
71
71
  streamQuery(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions<BM>): ReadableTyped<BM>;
72
- queryIds(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<string[]>;
73
- streamQueryIds(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions<string>): ReadableTyped<string>;
74
- streamQueryIdsForEach(q: DBQuery<DBM>, mapper: AsyncMapper<string, void>, opt?: CommonDaoStreamForEachOptions<string>): Promise<void>;
72
+ queryIds(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<ID[]>;
73
+ streamQueryIds(q: DBQuery<DBM>, opt?: CommonDaoStreamOptions<ID>): ReadableTyped<ID>;
74
+ streamQueryIdsForEach(q: DBQuery<DBM>, mapper: AsyncMapper<ID, void>, opt?: CommonDaoStreamForEachOptions<ID>): Promise<void>;
75
75
  /**
76
76
  * Mutates!
77
77
  * "Returns", just to have a type of "Saved"
@@ -86,11 +86,11 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
86
86
  * 2. Applies the patch on top of loaded data.
87
87
  * 3. Saves (as fast as possible since the read) with the Patch applied, but only if the data has changed.
88
88
  */
89
- patchById(id: string, patch: Partial<BM>, opt?: CommonDaoPatchByIdOptions<DBM>): Promise<BM>;
89
+ patchById(id: ID, patch: Partial<BM>, opt?: CommonDaoPatchByIdOptions<DBM>): Promise<BM>;
90
90
  /**
91
91
  * Like patchById, but runs all operations within a Transaction.
92
92
  */
93
- patchByIdInTransaction(id: string, patch: Partial<BM>, opt?: CommonDaoPatchByIdOptions<DBM>): Promise<BM>;
93
+ patchByIdInTransaction(id: ID, patch: Partial<BM>, opt?: CommonDaoPatchByIdOptions<DBM>): Promise<BM>;
94
94
  /**
95
95
  * Same as patchById, but takes the whole object as input.
96
96
  * This "whole object" is mutated with the patch and returned.
@@ -119,16 +119,16 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
119
119
  /**
120
120
  * @returns number of deleted items
121
121
  */
122
- deleteById(id?: string | null, opt?: CommonDaoOptions): Promise<number>;
123
- deleteByIds(ids: string[], opt?: CommonDaoOptions): Promise<number>;
122
+ deleteById(id?: ID | null, opt?: CommonDaoOptions): Promise<number>;
123
+ deleteByIds(ids: ID[], opt?: CommonDaoOptions): Promise<number>;
124
124
  /**
125
125
  * Pass `chunkSize: number` (e.g 500) option to use Streaming: it will Stream the query, chunk by 500, and execute
126
126
  * `deleteByIds` for each chunk concurrently (infinite concurrency).
127
127
  * This is expected to be more memory-efficient way of deleting large number of rows.
128
128
  */
129
129
  deleteByQuery(q: DBQuery<DBM>, opt?: CommonDaoStreamDeleteOptions<DBM>): Promise<number>;
130
- updateById(id: string, patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
131
- updateByIds(ids: string[], patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
130
+ updateById(id: ID, patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
131
+ updateByIds(ids: ID[], patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
132
132
  updateByQuery(q: DBQuery<DBM>, patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
133
133
  dbmToBM(_dbm: undefined, opt?: CommonDaoOptions): Promise<undefined>;
134
134
  dbmToBM(_dbm?: DBM, opt?: CommonDaoOptions): Promise<BM>;
@@ -157,6 +157,10 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
157
157
  */
158
158
  ping(): Promise<void>;
159
159
  runInTransaction<T = void>(fn: CommonDaoTransactionFn<T>, opt?: CommonDBTransactionOptions): Promise<T>;
160
+ /**
161
+ * Throws if query uses a property that is in `excludeFromIndexes` list.
162
+ */
163
+ private validateQueryIndexes;
160
164
  protected logResult(started: number, op: string, res: any, table: string): void;
161
165
  protected logSaveResult(started: number, op: string, table: string): void;
162
166
  protected logStarted(op: string, table: string, force?: boolean): UnixTimestampMillisNumber;
@@ -180,8 +184,8 @@ export declare class CommonDaoTransaction {
180
184
  * Perform a graceful rollback without throwing/re-throwing any error.
181
185
  */
182
186
  rollback(): Promise<void>;
183
- getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
184
- getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
187
+ getById<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(dao: CommonDao<BM, DBM, ID>, id?: ID | null, opt?: CommonDaoOptions): Promise<BM | null>;
188
+ getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(dao: CommonDao<BM, DBM, ID>, ids: ID[], opt?: CommonDaoOptions): Promise<BM[]>;
185
189
  save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: Unsaved<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
186
190
  saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM[]>;
187
191
  /**
@@ -191,7 +195,7 @@ export declare class CommonDaoTransaction {
191
195
  *
192
196
  * So, this method is a rather simple convenience "Object.assign and then save".
193
197
  */
194
- patch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: BM, patch: Partial<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
195
- deleteById(dao: CommonDao<any>, id?: string | null, opt?: CommonDaoOptions): Promise<number>;
196
- deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number>;
198
+ patch<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(dao: CommonDao<BM, DBM, ID>, bm: BM, patch: Partial<BM>, opt?: CommonDaoSaveOptions<BM, DBM>): Promise<BM>;
199
+ deleteById<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(dao: CommonDao<BM, DBM, ID>, id?: ID | null, opt?: CommonDaoOptions): Promise<number>;
200
+ deleteByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(dao: CommonDao<BM, DBM, ID>, ids: ID[], opt?: CommonDaoOptions): Promise<number>;
197
201
  }
@@ -202,6 +202,7 @@ class CommonDao {
202
202
  return (0, js_lib_1._uniqBy)(results, r => r.id);
203
203
  }
204
204
  async runQueryExtended(q, opt = {}) {
205
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
205
206
  q.table = opt.table || q.table;
206
207
  const op = `runQuery(${q.pretty()})`;
207
208
  const started = this.logStarted(op, q.table);
@@ -222,6 +223,7 @@ class CommonDao {
222
223
  return rows;
223
224
  }
224
225
  async runQueryExtendedAsDBM(q, opt = {}) {
226
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
225
227
  q.table = opt.table || q.table;
226
228
  const op = `runQueryAsDBM(${q.pretty()})`;
227
229
  const started = this.logStarted(op, q.table);
@@ -235,6 +237,7 @@ class CommonDao {
235
237
  return { rows: dbms, ...queryResult };
236
238
  }
237
239
  async runQueryCount(q, opt = {}) {
240
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
238
241
  q.table = opt.table || q.table;
239
242
  const op = `runQueryCount(${q.pretty()})`;
240
243
  const started = this.logStarted(op, q.table);
@@ -245,6 +248,7 @@ class CommonDao {
245
248
  return count;
246
249
  }
247
250
  async streamQueryForEach(q, mapper, opt = {}) {
251
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
248
252
  q.table = opt.table || q.table;
249
253
  opt.skipValidation = opt.skipValidation !== false; // default true
250
254
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
@@ -283,6 +287,7 @@ class CommonDao {
283
287
  }
284
288
  }
285
289
  async streamQueryAsDBMForEach(q, mapper, opt = {}) {
290
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
286
291
  q.table = opt.table || q.table;
287
292
  opt.skipValidation = opt.skipValidation !== false; // default true
288
293
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
@@ -324,6 +329,7 @@ class CommonDao {
324
329
  * Stream as Readable, to be able to .pipe() it further with support of backpressure.
325
330
  */
326
331
  streamQueryAsDBM(q, opt = {}) {
332
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
327
333
  q.table = opt.table || q.table;
328
334
  opt.skipValidation = opt.skipValidation !== false; // default true
329
335
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
@@ -354,6 +360,7 @@ class CommonDao {
354
360
  * You can do `.pipe(transformNoOp)` to make it "valid again".
355
361
  */
356
362
  streamQuery(q, opt = {}) {
363
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
357
364
  q.table = opt.table || q.table;
358
365
  opt.skipValidation = opt.skipValidation !== false; // default true
359
366
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
@@ -394,11 +401,13 @@ class CommonDao {
394
401
  .pipe((0, nodejs_lib_1.transformNoOp)()));
395
402
  }
396
403
  async queryIds(q, opt = {}) {
404
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
397
405
  q.table = opt.table || q.table;
398
406
  const { rows } = await this.cfg.db.runQuery(q.select(['id']), opt);
399
407
  return rows.map(r => r.id);
400
408
  }
401
409
  streamQueryIds(q, opt = {}) {
410
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
402
411
  q.table = opt.table || q.table;
403
412
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
404
413
  // Experimental: using `.map()`
@@ -417,6 +426,7 @@ class CommonDao {
417
426
  return stream;
418
427
  }
419
428
  async streamQueryIdsForEach(q, mapper, opt = {}) {
429
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
420
430
  q.table = opt.table || q.table;
421
431
  opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
422
432
  const op = `streamQueryIdsForEach(${q.pretty()})`;
@@ -455,7 +465,8 @@ class CommonDao {
455
465
  obj.updated = opt.preserveUpdatedCreated && obj.updated ? obj.updated : now;
456
466
  }
457
467
  if (this.cfg.generateId) {
458
- obj.id ||= this.cfg.hooks.createNaturalId?.(obj) || this.cfg.hooks.createRandomId();
468
+ obj.id ||= (this.cfg.hooks.createNaturalId?.(obj) ||
469
+ this.cfg.hooks.createRandomId());
459
470
  }
460
471
  return obj;
461
472
  }
@@ -777,6 +788,7 @@ class CommonDao {
777
788
  * This is expected to be more memory-efficient way of deleting large number of rows.
778
789
  */
779
790
  async deleteByQuery(q, opt = {}) {
791
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
780
792
  this.requireWriteAccess();
781
793
  this.requireObjectMutability(opt);
782
794
  q.table = opt.table || q.table;
@@ -820,6 +832,7 @@ class CommonDao {
820
832
  return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt);
821
833
  }
822
834
  async updateByQuery(q, patch, opt = {}) {
835
+ this.validateQueryIndexes(q); // throws if query uses `excludeFromIndexes` property
823
836
  this.requireWriteAccess();
824
837
  this.requireObjectMutability(opt);
825
838
  q.table = opt.table || q.table;
@@ -959,6 +972,19 @@ class CommonDao {
959
972
  }, opt);
960
973
  return r;
961
974
  }
975
+ /**
976
+ * Throws if query uses a property that is in `excludeFromIndexes` list.
977
+ */
978
+ validateQueryIndexes(q) {
979
+ const { excludeFromIndexes } = this.cfg;
980
+ if (!excludeFromIndexes)
981
+ return;
982
+ for (const f of q._filters) {
983
+ (0, js_lib_1._assert)(!excludeFromIndexes.includes(f.name), `cannot query on non-indexed property: ${this.cfg.table}.${f.name}`, {
984
+ query: q.pretty(),
985
+ });
986
+ }
987
+ }
962
988
  logResult(started, op, res, table) {
963
989
  if (!this.cfg.logLevel)
964
990
  return;
@@ -2,24 +2,24 @@ import { BaseDBEntity, CommonLogger, ErrorMode, Promisable, ZodError, ZodSchema
2
2
  import { AjvSchema, AjvValidationError, JoiValidationError, ObjectSchema, TransformLogProgressOptions, TransformMapOptions } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDB } from '../common.db';
4
4
  import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model';
5
- export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity> {
5
+ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']> {
6
6
  /**
7
7
  * Allows to override the id generation function.
8
8
  * By default it uses `stringId` from nodejs-lib
9
9
  * (which uses lowercase alphanumberic alphabet and the size of 16).
10
10
  */
11
- createRandomId: () => string;
11
+ createRandomId: () => ID;
12
12
  /**
13
13
  * createNaturalId hook is called (tried) first.
14
14
  * If it doesn't exist - createRandomId is called.
15
15
  */
16
- createNaturalId: (obj: DBM | BM) => string;
16
+ createNaturalId: (obj: DBM | BM) => ID;
17
17
  /**
18
18
  * It's a counter-part of `createNaturalId`.
19
19
  * Allows to provide a parser function to parse "natural id" into
20
20
  * DBM components (e.g accountId and some other property that is part of the id).
21
21
  */
22
- parseNaturalId: (id: string) => Partial<DBM>;
22
+ parseNaturalId: (id: ID) => Partial<DBM>;
23
23
  /**
24
24
  * It is called only on `dao.create` method.
25
25
  * Dao.create method is called in:
@@ -93,7 +93,7 @@ export declare enum CommonDaoLogLevel {
93
93
  */
94
94
  DATA_FULL = 30
95
95
  }
96
- export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
96
+ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, ID = BM['id']> {
97
97
  db: CommonDB;
98
98
  table: string;
99
99
  /**
@@ -138,7 +138,7 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
138
138
  * @default false
139
139
  */
140
140
  logStarted?: boolean;
141
- hooks?: Partial<CommonDaoHooks<BM, DBM>>;
141
+ hooks?: Partial<CommonDaoHooks<BM, DBM, ID>>;
142
142
  /**
143
143
  * Defaults to true.
144
144
  * Set to false to disable auto-generation of `id`.
@@ -87,12 +87,12 @@ export declare class DBQuery<ROW extends ObjectWithId> {
87
87
  /**
88
88
  * DBQuery that has additional method to support Fluent API style.
89
89
  */
90
- export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> extends DBQuery<DBM> {
91
- dao: CommonDao<BM, DBM>;
90
+ export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, ID = BM['id']> extends DBQuery<DBM> {
91
+ dao: CommonDao<BM, DBM, ID>;
92
92
  /**
93
93
  * Pass `table` to override table.
94
94
  */
95
- constructor(dao: CommonDao<BM, DBM>, table?: string);
95
+ constructor(dao: CommonDao<BM, DBM, ID>, table?: string);
96
96
  runQuery(opt?: CommonDaoOptions): Promise<BM[]>;
97
97
  runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
98
98
  runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
@@ -104,8 +104,8 @@ export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDB
104
104
  streamQueryAsDBMForEach(mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
105
105
  streamQuery(opt?: CommonDaoStreamOptions<BM>): ReadableTyped<BM>;
106
106
  streamQueryAsDBM(opt?: CommonDaoStreamOptions<DBM>): ReadableTyped<DBM>;
107
- queryIds(opt?: CommonDaoOptions): Promise<string[]>;
108
- streamQueryIds(opt?: CommonDaoStreamOptions<string>): ReadableTyped<string>;
109
- streamQueryIdsForEach(mapper: AsyncMapper<string, void>, opt?: CommonDaoStreamForEachOptions<string>): Promise<void>;
107
+ queryIds(opt?: CommonDaoOptions): Promise<ID[]>;
108
+ streamQueryIds(opt?: CommonDaoStreamOptions<ID>): ReadableTyped<ID>;
109
+ streamQueryIdsForEach(mapper: AsyncMapper<ID, void>, opt?: CommonDaoStreamForEachOptions<ID>): Promise<void>;
110
110
  deleteByQuery(opt?: CommonDaoStreamDeleteOptions<DBM>): Promise<number>;
111
111
  }
@@ -8,7 +8,6 @@ const __1 = require("..");
8
8
  const common_dao_1 = require("../commondao/common.dao");
9
9
  const dbTest_1 = require("./dbTest");
10
10
  const test_model_1 = require("./test.model");
11
- // eslint-disable-next-line jest/no-export
12
11
  function runCommonDaoTest(db, quirks = {}) {
13
12
  const { support } = db;
14
13
  const dao = new common_dao_1.CommonDao({
@@ -7,11 +7,10 @@ const common_db_1 = require("../common.db");
7
7
  const db_model_1 = require("../db.model");
8
8
  const dbQuery_1 = require("../query/dbQuery");
9
9
  const test_model_1 = require("./test.model");
10
- const test_util_1 = require("./test.util");
11
10
  function runCommonDBTest(db, quirks = {}) {
12
11
  const { support } = db;
13
12
  const items = (0, test_model_1.createTestItemsDBM)(3);
14
- (0, test_util_1.deepFreeze)(items);
13
+ (0, js_lib_1._deepFreeze)(items);
15
14
  const item1 = items[0];
16
15
  const queryAll = () => dbQuery_1.DBQuery.create(test_model_1.TEST_TABLE);
17
16
  test('ping', async () => {
@@ -54,7 +53,7 @@ function runCommonDBTest(db, quirks = {}) {
54
53
  ...(0, test_model_1.createTestItemDBM)(3),
55
54
  k2: null,
56
55
  };
57
- (0, test_util_1.deepFreeze)(item3);
56
+ (0, js_lib_1._deepFreeze)(item3);
58
57
  await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
59
58
  const item3Loaded = (await db.getByIds(test_model_1.TEST_TABLE, [item3.id]))[0];
60
59
  expectMatch([item3], [item3Loaded], quirks);
@@ -67,7 +66,7 @@ function runCommonDBTest(db, quirks = {}) {
67
66
  ...(0, test_model_1.createTestItemDBM)(3),
68
67
  k2: undefined,
69
68
  };
70
- (0, test_util_1.deepFreeze)(item3);
69
+ (0, js_lib_1._deepFreeze)(item3);
71
70
  const expected = { ...item3 };
72
71
  delete expected.k2;
73
72
  await db.saveBatch(test_model_1.TEST_TABLE, [item3]);
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runCommonKeyValueDBTest = runCommonKeyValueDBTest;
4
4
  const js_lib_1 = require("@naturalcycles/js-lib");
5
5
  const test_model_1 = require("./test.model");
6
- /* eslint-disable jest/no-export */
7
6
  const testIds = (0, js_lib_1._range)(1, 4).map(n => `id${n}`);
8
7
  const testEntries = testIds.map(id => [id, Buffer.from(`${id}value`)]);
9
8
  function runCommonKeyValueDBTest(db) {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runCommonKeyValueDaoTest = runCommonKeyValueDaoTest;
4
4
  const js_lib_1 = require("@naturalcycles/js-lib");
5
- /* eslint-disable jest/no-export */
6
5
  const testIds = (0, js_lib_1._range)(1, 4).map(n => `id${n}`);
7
6
  const testEntries = testIds.map(id => [id, Buffer.from(`${id}value`)]);
8
7
  function runCommonKeyValueDaoTest(dao) {
@@ -24,5 +24,5 @@ export declare class FakeDBTransaction implements DBTransaction {
24
24
  rollback(): Promise<void>;
25
25
  getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: CommonDBOptions): Promise<ROW[]>;
26
26
  saveBatch<ROW extends ObjectWithId>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
27
- deleteByIds(table: string, ids: string[], opt?: CommonDBOptions | undefined): Promise<number>;
27
+ deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number>;
28
28
  }
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  "engines": {
46
46
  "node": ">=20.13"
47
47
  },
48
- "version": "9.15.1",
48
+ "version": "9.17.0",
49
49
  "description": "Lowest Common Denominator API to supported Databases",
50
50
  "keywords": [
51
51
  "db",
@@ -35,7 +35,8 @@ export function queryInMemory<ROW extends ObjectWithId>(q: DBQuery<ROW>, rows: R
35
35
  if (order) {
36
36
  const { name, descending } = order
37
37
  rows = rows.sort((a, b) => {
38
- if (a[name] == b[name]) return 0 // eslint-disable-line eqeqeq
38
+ // biome-ignore lint/suspicious/noDoubleEquals: ok
39
+ if (a[name] == b[name]) return 0
39
40
 
40
41
  if (descending) {
41
42
  return a[name] < b[name] ? 1 : -1
@@ -12,8 +12,6 @@ import {
12
12
  import { DBQuery } from './query/dbQuery'
13
13
  import { FakeDBTransaction } from './transaction/dbTransaction.util'
14
14
 
15
- /* eslint-disable unused-imports/no-unused-vars */
16
-
17
15
  /**
18
16
  * No-op implementation of CommonDB interface.
19
17
  * To be extended by actual implementations.
@@ -32,59 +30,59 @@ export class BaseCommonDB implements CommonDB {
32
30
  }
33
31
 
34
32
  async getTableSchema<ROW extends ObjectWithId>(
35
- table: string,
33
+ _table: string,
36
34
  ): Promise<JsonSchemaRootObject<ROW>> {
37
35
  throw new Error('getTableSchema is not implemented')
38
36
  }
39
37
 
40
38
  async createTable<ROW extends ObjectWithId>(
41
- table: string,
42
- schema: JsonSchemaObject<ROW>,
39
+ _table: string,
40
+ _schema: JsonSchemaObject<ROW>,
43
41
  ): Promise<void> {
44
42
  // no-op
45
43
  }
46
44
 
47
- async getByIds<ROW extends ObjectWithId>(table: string, ids: string[]): Promise<ROW[]> {
45
+ async getByIds<ROW extends ObjectWithId>(_table: string, _ids: string[]): Promise<ROW[]> {
48
46
  throw new Error('getByIds is not implemented')
49
47
  }
50
48
 
51
- async deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number> {
49
+ async deleteByQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number> {
52
50
  throw new Error('deleteByQuery is not implemented')
53
51
  }
54
52
 
55
53
  async updateByQuery<ROW extends ObjectWithId>(
56
- q: DBQuery<ROW>,
57
- patch: DBPatch<ROW>,
58
- opt?: CommonDBOptions,
54
+ _q: DBQuery<ROW>,
55
+ _patch: DBPatch<ROW>,
56
+ _opt?: CommonDBOptions,
59
57
  ): Promise<number> {
60
58
  throw new Error('updateByQuery is not implemented')
61
59
  }
62
60
 
63
- async runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<RunQueryResult<ROW>> {
61
+ async runQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<RunQueryResult<ROW>> {
64
62
  throw new Error('runQuery is not implemented')
65
63
  }
66
64
 
67
- async runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>): Promise<number> {
65
+ async runQueryCount<ROW extends ObjectWithId>(_q: DBQuery<ROW>): Promise<number> {
68
66
  throw new Error('runQueryCount is not implemented')
69
67
  }
70
68
 
71
69
  async saveBatch<ROW extends ObjectWithId>(
72
- table: string,
73
- rows: ROW[],
74
- opt?: CommonDBSaveOptions<ROW>,
70
+ _table: string,
71
+ _rows: ROW[],
72
+ _opt?: CommonDBSaveOptions<ROW>,
75
73
  ): Promise<void> {
76
74
  throw new Error('saveBatch is not implemented')
77
75
  }
78
76
 
79
- streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>): ReadableTyped<ROW> {
77
+ streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>): ReadableTyped<ROW> {
80
78
  throw new Error('streamQuery is not implemented')
81
79
  }
82
80
 
83
- async deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number> {
81
+ async deleteByIds(_table: string, _ids: string[], _opt?: CommonDBOptions): Promise<number> {
84
82
  throw new Error('deleteByIds is not implemented')
85
83
  }
86
84
 
87
- async runInTransaction(fn: DBTransactionFn, opt?: CommonDBTransactionOptions): Promise<void> {
85
+ async runInTransaction(fn: DBTransactionFn, _opt?: CommonDBTransactionOptions): Promise<void> {
88
86
  const tx = new FakeDBTransaction(this)
89
87
  await fn(tx)
90
88
  // there's no try/catch and rollback, as there's nothing to rollback
@@ -17,26 +17,26 @@ import {
17
17
  import { CommonDB } from '../common.db'
18
18
  import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model'
19
19
 
20
- export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity> {
20
+ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']> {
21
21
  /**
22
22
  * Allows to override the id generation function.
23
23
  * By default it uses `stringId` from nodejs-lib
24
24
  * (which uses lowercase alphanumberic alphabet and the size of 16).
25
25
  */
26
- createRandomId: () => string
26
+ createRandomId: () => ID
27
27
 
28
28
  /**
29
29
  * createNaturalId hook is called (tried) first.
30
30
  * If it doesn't exist - createRandomId is called.
31
31
  */
32
- createNaturalId: (obj: DBM | BM) => string
32
+ createNaturalId: (obj: DBM | BM) => ID
33
33
 
34
34
  /**
35
35
  * It's a counter-part of `createNaturalId`.
36
36
  * Allows to provide a parser function to parse "natural id" into
37
37
  * DBM components (e.g accountId and some other property that is part of the id).
38
38
  */
39
- parseNaturalId: (id: string) => Partial<DBM>
39
+ parseNaturalId: (id: ID) => Partial<DBM>
40
40
 
41
41
  /**
42
42
  * It is called only on `dao.create` method.
@@ -118,7 +118,11 @@ export enum CommonDaoLogLevel {
118
118
  DATA_FULL = 30,
119
119
  }
120
120
 
121
- export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
121
+ export interface CommonDaoCfg<
122
+ BM extends BaseDBEntity,
123
+ DBM extends BaseDBEntity = BM,
124
+ ID = BM['id'],
125
+ > {
122
126
  db: CommonDB
123
127
  table: string
124
128
 
@@ -174,7 +178,7 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
174
178
  logStarted?: boolean
175
179
 
176
180
  // Hooks are designed with inspiration from got/ky interface
177
- hooks?: Partial<CommonDaoHooks<BM, DBM>>
181
+ hooks?: Partial<CommonDaoHooks<BM, DBM, ID>>
178
182
 
179
183
  /**
180
184
  * Defaults to true.
@@ -72,8 +72,8 @@ const isCI = !!process.env['CI']
72
72
  * BM = Backend model (optimized for API access)
73
73
  * TM = Transport model (optimized to be sent over the wire)
74
74
  */
75
- export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
76
- constructor(public cfg: CommonDaoCfg<BM, DBM>) {
75
+ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, ID = BM['id']> {
76
+ constructor(public cfg: CommonDaoCfg<BM, DBM, ID>) {
77
77
  this.cfg = {
78
78
  // Default is to NOT log in AppEngine and in CI,
79
79
  // otherwise to log Operations
@@ -93,11 +93,11 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
93
93
  anonymize: dbm => dbm,
94
94
  onValidationError: err => err,
95
95
  ...cfg.hooks,
96
- } satisfies Partial<CommonDaoHooks<BM, DBM>>,
96
+ } satisfies Partial<CommonDaoHooks<BM, DBM, ID>>,
97
97
  }
98
98
 
99
99
  if (this.cfg.generateId) {
100
- this.cfg.hooks!.createRandomId ||= () => stringId()
100
+ this.cfg.hooks!.createRandomId ||= () => stringId() as ID
101
101
  } else {
102
102
  delete this.cfg.hooks!.createRandomId
103
103
  }
@@ -113,14 +113,14 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
113
113
 
114
114
  // GET
115
115
  async getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
116
- async getById(id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>
117
- async getById(id?: string | null, opt: CommonDaoOptions = {}): Promise<BM | null> {
116
+ async getById(id?: ID | null, opt?: CommonDaoOptions): Promise<BM | null>
117
+ async getById(id?: ID | null, opt: CommonDaoOptions = {}): Promise<BM | null> {
118
118
  if (!id) return null
119
119
  const op = `getById(${id})`
120
120
  const table = opt.table || this.cfg.table
121
121
  const started = this.logStarted(op, table)
122
122
 
123
- let dbm = (await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id]))[0]
123
+ let dbm = (await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id as string]))[0]
124
124
  if (dbm && this.cfg.hooks!.afterLoad) {
125
125
  dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
126
126
  }
@@ -130,7 +130,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
130
130
  return bm || null
131
131
  }
132
132
 
133
- async getByIdOrEmpty(id: string, part: Partial<BM> = {}, opt?: CommonDaoOptions): Promise<BM> {
133
+ async getByIdOrEmpty(id: ID, part: Partial<BM> = {}, opt?: CommonDaoOptions): Promise<BM> {
134
134
  const bm = await this.getById(id, opt)
135
135
  if (bm) return bm
136
136
 
@@ -138,13 +138,13 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
138
138
  }
139
139
 
140
140
  async getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
141
- async getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>
142
- async getByIdAsDBM(id?: string | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
141
+ async getByIdAsDBM(id?: ID | null, opt?: CommonDaoOptions): Promise<DBM | null>
142
+ async getByIdAsDBM(id?: ID | null, opt: CommonDaoOptions = {}): Promise<DBM | null> {
143
143
  if (!id) return null
144
144
  const op = `getByIdAsDBM(${id})`
145
145
  const table = opt.table || this.cfg.table
146
146
  const started = this.logStarted(op, table)
147
- let [dbm] = await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id])
147
+ let [dbm] = await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id as string])
148
148
  if (dbm && this.cfg.hooks!.afterLoad) {
149
149
  dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
150
150
  }
@@ -154,12 +154,12 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
154
154
  return dbm || null
155
155
  }
156
156
 
157
- async getByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<BM[]> {
157
+ async getByIds(ids: ID[], opt: CommonDaoOptions = {}): Promise<BM[]> {
158
158
  if (!ids.length) return []
159
159
  const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
160
160
  const table = opt.table || this.cfg.table
161
161
  const started = this.logStarted(op, table)
162
- let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
162
+ let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids as string[])
163
163
  if (this.cfg.hooks!.afterLoad && dbms.length) {
164
164
  dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
165
165
  _isTruthy,
@@ -171,12 +171,12 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
171
171
  return bms
172
172
  }
173
173
 
174
- async getByIdsAsDBM(ids: string[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
174
+ async getByIdsAsDBM(ids: ID[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
175
175
  if (!ids.length) return []
176
176
  const op = `getByIdsAsDBM ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
177
177
  const table = opt.table || this.cfg.table
178
178
  const started = this.logStarted(op, table)
179
- let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
179
+ let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids as string[])
180
180
  if (this.cfg.hooks!.afterLoad && dbms.length) {
181
181
  dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
182
182
  _isTruthy,
@@ -187,7 +187,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
187
187
  return dbms
188
188
  }
189
189
 
190
- async requireById(id: string, opt: CommonDaoOptions = {}): Promise<BM> {
190
+ async requireById(id: ID, opt: CommonDaoOptions = {}): Promise<BM> {
191
191
  const r = await this.getById(id, opt)
192
192
  if (!r) {
193
193
  this.throwRequiredError(id, opt)
@@ -195,7 +195,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
195
195
  return r
196
196
  }
197
197
 
198
- async requireByIdAsDBM(id: string, opt: CommonDaoOptions = {}): Promise<DBM> {
198
+ async requireByIdAsDBM(id: ID, opt: CommonDaoOptions = {}): Promise<DBM> {
199
199
  const r = await this.getByIdAsDBM(id, opt)
200
200
  if (!r) {
201
201
  this.throwRequiredError(id, opt)
@@ -203,7 +203,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
203
203
  return r
204
204
  }
205
205
 
206
- private throwRequiredError(id: string, opt: CommonDaoOptions): never {
206
+ private throwRequiredError(id: ID, opt: CommonDaoOptions): never {
207
207
  const table = opt.table || this.cfg.table
208
208
  throw new AppError(`DB row required, but not found in ${table}`, {
209
209
  table,
@@ -261,8 +261,8 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
261
261
  /**
262
262
  * Pass `table` to override table
263
263
  */
264
- query(table?: string): RunnableDBQuery<BM, DBM> {
265
- return new RunnableDBQuery<BM, DBM>(this, table)
264
+ query(table?: string): RunnableDBQuery<BM, DBM, ID> {
265
+ return new RunnableDBQuery<BM, DBM, ID>(this, table)
266
266
  }
267
267
 
268
268
  async runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<BM[]> {
@@ -295,6 +295,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
295
295
  }
296
296
 
297
297
  async runQueryExtended(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<RunQueryResult<BM>> {
298
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
298
299
  q.table = opt.table || q.table
299
300
  const op = `runQuery(${q.pretty()})`
300
301
  const started = this.logStarted(op, q.table)
@@ -323,6 +324,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
323
324
  q: DBQuery<DBM>,
324
325
  opt: CommonDaoOptions = {},
325
326
  ): Promise<RunQueryResult<DBM>> {
327
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
326
328
  q.table = opt.table || q.table
327
329
  const op = `runQueryAsDBM(${q.pretty()})`
328
330
  const started = this.logStarted(op, q.table)
@@ -340,6 +342,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
340
342
  }
341
343
 
342
344
  async runQueryCount(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
345
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
343
346
  q.table = opt.table || q.table
344
347
  const op = `runQueryCount(${q.pretty()})`
345
348
  const started = this.logStarted(op, q.table)
@@ -355,6 +358,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
355
358
  mapper: AsyncMapper<BM, void>,
356
359
  opt: CommonDaoStreamForEachOptions<BM> = {},
357
360
  ): Promise<void> {
361
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
358
362
  q.table = opt.table || q.table
359
363
  opt.skipValidation = opt.skipValidation !== false // default true
360
364
  opt.errorMode ||= ErrorMode.SUPPRESS
@@ -404,6 +408,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
404
408
  mapper: AsyncMapper<DBM, void>,
405
409
  opt: CommonDaoStreamForEachOptions<DBM> = {},
406
410
  ): Promise<void> {
411
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
407
412
  q.table = opt.table || q.table
408
413
  opt.skipValidation = opt.skipValidation !== false // default true
409
414
  opt.errorMode ||= ErrorMode.SUPPRESS
@@ -452,6 +457,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
452
457
  * Stream as Readable, to be able to .pipe() it further with support of backpressure.
453
458
  */
454
459
  streamQueryAsDBM(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<DBM> = {}): ReadableTyped<DBM> {
460
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
455
461
  q.table = opt.table || q.table
456
462
  opt.skipValidation = opt.skipValidation !== false // default true
457
463
  opt.errorMode ||= ErrorMode.SUPPRESS
@@ -490,6 +496,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
490
496
  * You can do `.pipe(transformNoOp)` to make it "valid again".
491
497
  */
492
498
  streamQuery(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<BM> = {}): ReadableTyped<BM> {
499
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
493
500
  q.table = opt.table || q.table
494
501
  opt.skipValidation = opt.skipValidation !== false // default true
495
502
  opt.errorMode ||= ErrorMode.SUPPRESS
@@ -539,21 +546,23 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
539
546
  )
540
547
  }
541
548
 
542
- async queryIds(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<string[]> {
549
+ async queryIds(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<ID[]> {
550
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
543
551
  q.table = opt.table || q.table
544
552
  const { rows } = await this.cfg.db.runQuery(q.select(['id']), opt)
545
- return rows.map(r => r.id)
553
+ return rows.map(r => r.id as ID)
546
554
  }
547
555
 
548
- streamQueryIds(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<string> = {}): ReadableTyped<string> {
556
+ streamQueryIds(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<ID> = {}): ReadableTyped<ID> {
557
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
549
558
  q.table = opt.table || q.table
550
559
  opt.errorMode ||= ErrorMode.SUPPRESS
551
560
 
552
561
  // Experimental: using `.map()`
553
- const stream: ReadableTyped<string> = this.cfg.db
562
+ const stream: ReadableTyped<ID> = this.cfg.db
554
563
  .streamQuery<DBM>(q.select(['id']), opt)
555
564
  // .on('error', err => stream.emit('error', err))
556
- .map((r: ObjectWithId) => r.id)
565
+ .map((r: ObjectWithId) => r.id as ID)
557
566
 
558
567
  // const stream: ReadableTyped<string> = this.cfg.db
559
568
  // .streamQuery<DBM>(q.select(['id']), opt)
@@ -569,9 +578,10 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
569
578
 
570
579
  async streamQueryIdsForEach(
571
580
  q: DBQuery<DBM>,
572
- mapper: AsyncMapper<string, void>,
573
- opt: CommonDaoStreamForEachOptions<string> = {},
581
+ mapper: AsyncMapper<ID, void>,
582
+ opt: CommonDaoStreamForEachOptions<ID> = {},
574
583
  ): Promise<void> {
584
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
575
585
  q.table = opt.table || q.table
576
586
  opt.errorMode ||= ErrorMode.SUPPRESS
577
587
 
@@ -584,7 +594,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
584
594
  count++
585
595
  return r.id
586
596
  }),
587
- transformMap<string, void>(mapper, {
597
+ transformMap<ID, void>(mapper, {
588
598
  ...opt,
589
599
  predicate: _passthroughPredicate,
590
600
  }),
@@ -617,7 +627,8 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
617
627
  }
618
628
 
619
629
  if (this.cfg.generateId) {
620
- obj.id ||= this.cfg.hooks!.createNaturalId?.(obj as any) || this.cfg.hooks!.createRandomId!()
630
+ obj.id ||= (this.cfg.hooks!.createNaturalId?.(obj as any) ||
631
+ this.cfg.hooks!.createRandomId!()) as T['id']
621
632
  }
622
633
 
623
634
  return obj as T
@@ -634,7 +645,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
634
645
  * 3. Saves (as fast as possible since the read) with the Patch applied, but only if the data has changed.
635
646
  */
636
647
  async patchById(
637
- id: string,
648
+ id: ID,
638
649
  patch: Partial<BM>,
639
650
  opt: CommonDaoPatchByIdOptions<DBM> = {},
640
651
  ): Promise<BM> {
@@ -671,7 +682,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
671
682
  * Like patchById, but runs all operations within a Transaction.
672
683
  */
673
684
  async patchByIdInTransaction(
674
- id: string,
685
+ id: ID,
675
686
  patch: Partial<BM>,
676
687
  opt?: CommonDaoPatchByIdOptions<DBM>,
677
688
  ): Promise<BM> {
@@ -706,7 +717,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
706
717
  }
707
718
  Object.assign(bm, patch)
708
719
  } else {
709
- const loaded = await this.getById(bm.id, opt)
720
+ const loaded = await this.getById(bm.id as ID, opt)
710
721
 
711
722
  if (loaded) {
712
723
  const loadedWithPatch: BM = {
@@ -989,19 +1000,19 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
989
1000
  /**
990
1001
  * @returns number of deleted items
991
1002
  */
992
- async deleteById(id?: string | null, opt: CommonDaoOptions = {}): Promise<number> {
1003
+ async deleteById(id?: ID | null, opt: CommonDaoOptions = {}): Promise<number> {
993
1004
  if (!id) return 0
994
1005
  return await this.deleteByIds([id], opt)
995
1006
  }
996
1007
 
997
- async deleteByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<number> {
1008
+ async deleteByIds(ids: ID[], opt: CommonDaoOptions = {}): Promise<number> {
998
1009
  if (!ids.length) return 0
999
1010
  this.requireWriteAccess()
1000
1011
  this.requireObjectMutability(opt)
1001
1012
  const op = `deleteByIds(${ids.join(', ')})`
1002
1013
  const table = opt.table || this.cfg.table
1003
1014
  const started = this.logStarted(op, table)
1004
- const count = await (opt.tx || this.cfg.db).deleteByIds(table, ids, opt)
1015
+ const count = await (opt.tx || this.cfg.db).deleteByIds(table, ids as string[], opt)
1005
1016
  this.logSaveResult(started, op, table)
1006
1017
  return count
1007
1018
  }
@@ -1015,6 +1026,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1015
1026
  q: DBQuery<DBM>,
1016
1027
  opt: CommonDaoStreamDeleteOptions<DBM> = {},
1017
1028
  ): Promise<number> {
1029
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
1018
1030
  this.requireWriteAccess()
1019
1031
  this.requireObjectMutability(opt)
1020
1032
  q.table = opt.table || q.table
@@ -1055,15 +1067,11 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1055
1067
  return deleted
1056
1068
  }
1057
1069
 
1058
- async updateById(id: string, patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1070
+ async updateById(id: ID, patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1059
1071
  return await this.updateByQuery(this.query().filterEq('id', id), patch, opt)
1060
1072
  }
1061
1073
 
1062
- async updateByIds(
1063
- ids: string[],
1064
- patch: DBPatch<DBM>,
1065
- opt: CommonDaoOptions = {},
1066
- ): Promise<number> {
1074
+ async updateByIds(ids: ID[], patch: DBPatch<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
1067
1075
  if (!ids.length) return 0
1068
1076
  return await this.updateByQuery(this.query().filterIn('id', ids), patch, opt)
1069
1077
  }
@@ -1073,6 +1081,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1073
1081
  patch: DBPatch<DBM>,
1074
1082
  opt: CommonDaoOptions = {},
1075
1083
  ): Promise<number> {
1084
+ this.validateQueryIndexes(q) // throws if query uses `excludeFromIndexes` property
1076
1085
  this.requireWriteAccess()
1077
1086
  this.requireObjectMutability(opt)
1078
1087
  q.table = opt.table || q.table
@@ -1092,7 +1101,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1092
1101
 
1093
1102
  // optimization: no need to run full joi DBM validation, cause BM validation will be run
1094
1103
  // const dbm = this.anyToDBM(_dbm, opt)
1095
- let dbm: DBM = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id) }
1104
+ let dbm: DBM = { ..._dbm, ...this.cfg.hooks!.parseNaturalId!(_dbm.id as ID) }
1096
1105
 
1097
1106
  if (opt.anonymize) {
1098
1107
  dbm = this.cfg.hooks!.anonymize!(dbm)
@@ -1138,7 +1147,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1138
1147
  // this shouldn't be happening on load! but should on save!
1139
1148
  // this.assignIdCreatedUpdated(dbm, opt)
1140
1149
 
1141
- dbm = { ...dbm, ...this.cfg.hooks!.parseNaturalId!(dbm.id) }
1150
+ dbm = { ...dbm, ...this.cfg.hooks!.parseNaturalId!(dbm.id as ID) }
1142
1151
 
1143
1152
  // todo: is this the right place?
1144
1153
  // todo: is anyToDBM even needed?
@@ -1259,6 +1268,24 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
1259
1268
  return r!
1260
1269
  }
1261
1270
 
1271
+ /**
1272
+ * Throws if query uses a property that is in `excludeFromIndexes` list.
1273
+ */
1274
+ private validateQueryIndexes(q: DBQuery<DBM>): void {
1275
+ const { excludeFromIndexes } = this.cfg
1276
+ if (!excludeFromIndexes) return
1277
+
1278
+ for (const f of q._filters) {
1279
+ _assert(
1280
+ !excludeFromIndexes.includes(f.name),
1281
+ `cannot query on non-indexed property: ${this.cfg.table}.${f.name as string}`,
1282
+ {
1283
+ query: q.pretty(),
1284
+ },
1285
+ )
1286
+ }
1287
+ }
1288
+
1262
1289
  protected logResult(started: number, op: string, res: any, table: string): void {
1263
1290
  if (!this.cfg.logLevel) return
1264
1291
 
@@ -1345,17 +1372,17 @@ export class CommonDaoTransaction {
1345
1372
  }
1346
1373
  }
1347
1374
 
1348
- async getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
1349
- dao: CommonDao<BM, DBM>,
1350
- id?: string | null,
1375
+ async getById<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(
1376
+ dao: CommonDao<BM, DBM, ID>,
1377
+ id?: ID | null,
1351
1378
  opt?: CommonDaoOptions,
1352
1379
  ): Promise<BM | null> {
1353
1380
  return await dao.getById(id, { ...opt, tx: this.tx })
1354
1381
  }
1355
1382
 
1356
- async getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
1357
- dao: CommonDao<BM, DBM>,
1358
- ids: string[],
1383
+ async getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(
1384
+ dao: CommonDao<BM, DBM, ID>,
1385
+ ids: ID[],
1359
1386
  opt?: CommonDaoOptions,
1360
1387
  ): Promise<BM[]> {
1361
1388
  return await dao.getByIds(ids, { ...opt, tx: this.tx })
@@ -1398,8 +1425,8 @@ export class CommonDaoTransaction {
1398
1425
  *
1399
1426
  * So, this method is a rather simple convenience "Object.assign and then save".
1400
1427
  */
1401
- async patch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
1402
- dao: CommonDao<BM, DBM>,
1428
+ async patch<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(
1429
+ dao: CommonDao<BM, DBM, ID>,
1403
1430
  bm: BM,
1404
1431
  patch: Partial<BM>,
1405
1432
  opt?: CommonDaoSaveOptions<BM, DBM>,
@@ -1409,16 +1436,20 @@ export class CommonDaoTransaction {
1409
1436
  return await dao.save(bm, { ...opt, skipIfEquals, tx: this.tx })
1410
1437
  }
1411
1438
 
1412
- async deleteById(
1413
- dao: CommonDao<any>,
1414
- id?: string | null,
1439
+ async deleteById<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(
1440
+ dao: CommonDao<BM, DBM, ID>,
1441
+ id?: ID | null,
1415
1442
  opt?: CommonDaoOptions,
1416
1443
  ): Promise<number> {
1417
1444
  if (!id) return 0
1418
1445
  return await this.deleteByIds(dao, [id], opt)
1419
1446
  }
1420
1447
 
1421
- async deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number> {
1448
+ async deleteByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity, ID = BM['id']>(
1449
+ dao: CommonDao<BM, DBM, ID>,
1450
+ ids: ID[],
1451
+ opt?: CommonDaoOptions,
1452
+ ): Promise<number> {
1422
1453
  return await dao.deleteByIds(ids, { ...opt, tx: this.tx })
1423
1454
  }
1424
1455
  }
@@ -193,7 +193,7 @@ export class DBQuery<ROW extends ObjectWithId> {
193
193
  }
194
194
 
195
195
  prettyConditions(): string[] {
196
- const tokens = []
196
+ const tokens: string[] = []
197
197
 
198
198
  // if (this.name) {
199
199
  // tokens.push(`"${this.name}"`)
@@ -240,12 +240,13 @@ export class DBQuery<ROW extends ObjectWithId> {
240
240
  export class RunnableDBQuery<
241
241
  BM extends BaseDBEntity,
242
242
  DBM extends BaseDBEntity = BM,
243
+ ID = BM['id'],
243
244
  > extends DBQuery<DBM> {
244
245
  /**
245
246
  * Pass `table` to override table.
246
247
  */
247
248
  constructor(
248
- public dao: CommonDao<BM, DBM>,
249
+ public dao: CommonDao<BM, DBM, ID>,
249
250
  table?: string,
250
251
  ) {
251
252
  super(table || dao.cfg.table)
@@ -301,17 +302,17 @@ export class RunnableDBQuery<
301
302
  return this.dao.streamQueryAsDBM(this, opt)
302
303
  }
303
304
 
304
- async queryIds(opt?: CommonDaoOptions): Promise<string[]> {
305
+ async queryIds(opt?: CommonDaoOptions): Promise<ID[]> {
305
306
  return await this.dao.queryIds(this, opt)
306
307
  }
307
308
 
308
- streamQueryIds(opt?: CommonDaoStreamOptions<string>): ReadableTyped<string> {
309
+ streamQueryIds(opt?: CommonDaoStreamOptions<ID>): ReadableTyped<ID> {
309
310
  return this.dao.streamQueryIds(this, opt)
310
311
  }
311
312
 
312
313
  async streamQueryIdsForEach(
313
- mapper: AsyncMapper<string, void>,
314
- opt?: CommonDaoStreamForEachOptions<string>,
314
+ mapper: AsyncMapper<ID, void>,
315
+ opt?: CommonDaoStreamForEachOptions<ID>,
315
316
  ): Promise<void> {
316
317
  await this.dao.streamQueryIdsForEach(this, mapper, opt)
317
318
  }
@@ -14,7 +14,6 @@ import {
14
14
  testItemBMSchema,
15
15
  } from './test.model'
16
16
 
17
- // eslint-disable-next-line jest/no-export
18
17
  export function runCommonDaoTest(db: CommonDB, quirks: CommonDBImplementationQuirks = {}): void {
19
18
  const { support } = db
20
19
  const dao = new CommonDao({
@@ -1,4 +1,4 @@
1
- import { _filterObject, _pick, _sortBy, pMap } from '@naturalcycles/js-lib'
1
+ import { _deepFreeze, _filterObject, _pick, _sortBy, pMap } from '@naturalcycles/js-lib'
2
2
  import { CommonDB, CommonDBType } from '../common.db'
3
3
  import { DBIncrement, DBPatch } from '../db.model'
4
4
  import { DBQuery } from '../query/dbQuery'
@@ -9,9 +9,6 @@ import {
9
9
  testItemBMJsonSchema,
10
10
  TestItemDBM,
11
11
  } from './test.model'
12
- import { deepFreeze } from './test.util'
13
-
14
- /* eslint-disable jest/no-export */
15
12
 
16
13
  /**
17
14
  * All options default to `false`.
@@ -31,7 +28,7 @@ export interface CommonDBImplementationQuirks {
31
28
  export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuirks = {}): void {
32
29
  const { support } = db
33
30
  const items = createTestItemsDBM(3)
34
- deepFreeze(items)
31
+ _deepFreeze(items)
35
32
  const item1 = items[0]!
36
33
 
37
34
  const queryAll = (): DBQuery<TestItemDBM> => DBQuery.create<TestItemDBM>(TEST_TABLE)
@@ -88,7 +85,7 @@ export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuir
88
85
  ...createTestItemDBM(3),
89
86
  k2: null,
90
87
  }
91
- deepFreeze(item3)
88
+ _deepFreeze(item3)
92
89
  await db.saveBatch(TEST_TABLE, [item3])
93
90
  const item3Loaded = (await db.getByIds<TestItemDBM>(TEST_TABLE, [item3.id]))[0]!
94
91
  expectMatch([item3], [item3Loaded], quirks)
@@ -102,7 +99,7 @@ export function runCommonDBTest(db: CommonDB, quirks: CommonDBImplementationQuir
102
99
  ...createTestItemDBM(3),
103
100
  k2: undefined,
104
101
  }
105
- deepFreeze(item3)
102
+ _deepFreeze(item3)
106
103
  const expected = { ...item3 }
107
104
  delete expected.k2
108
105
 
@@ -2,8 +2,6 @@ import { _range, _sortBy } from '@naturalcycles/js-lib'
2
2
  import { CommonKeyValueDB, KeyValueDBTuple } from '../kv/commonKeyValueDB'
3
3
  import { TEST_TABLE } from './test.model'
4
4
 
5
- /* eslint-disable jest/no-export */
6
-
7
5
  const testIds = _range(1, 4).map(n => `id${n}`)
8
6
 
9
7
  const testEntries: KeyValueDBTuple[] = testIds.map(id => [id, Buffer.from(`${id}value`)])
@@ -2,8 +2,6 @@ import { _range, _sortBy } from '@naturalcycles/js-lib'
2
2
  import { CommonKeyValueDao } from '../kv/commonKeyValueDao'
3
3
  import { KeyValueDBTuple } from '../kv/commonKeyValueDB'
4
4
 
5
- /* eslint-disable jest/no-export */
6
-
7
5
  const testIds = _range(1, 4).map(n => `id${n}`)
8
6
  const testEntries: KeyValueDBTuple[] = testIds.map(id => [id, Buffer.from(`${id}value`)])
9
7
 
@@ -120,11 +120,7 @@ export class FakeDBTransaction implements DBTransaction {
120
120
  ): Promise<void> {
121
121
  await this.db.saveBatch(table, rows, opt)
122
122
  }
123
- async deleteByIds(
124
- table: string,
125
- ids: string[],
126
- opt?: CommonDBOptions | undefined,
127
- ): Promise<number> {
123
+ async deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number> {
128
124
  return await this.db.deleteByIds(table, ids, opt)
129
125
  }
130
126
  }
@@ -1,6 +0,0 @@
1
- /**
2
- * Does Object.freeze recursively for given object.
3
- *
4
- * Based on: https://github.com/substack/deep-freeze/blob/master/index.js
5
- */
6
- export declare function deepFreeze(o: any): void;
@@ -1,23 +0,0 @@
1
- "use strict";
2
- // copy-pasted from test-lib to be able to not include devDependecies there
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.deepFreeze = deepFreeze;
5
- /**
6
- * Does Object.freeze recursively for given object.
7
- *
8
- * Based on: https://github.com/substack/deep-freeze/blob/master/index.js
9
- */
10
- function deepFreeze(o) {
11
- Object.freeze(o);
12
- Object.getOwnPropertyNames(o).forEach(prop => {
13
- if (
14
- // eslint-disable-next-line no-prototype-builtins
15
- o.hasOwnProperty(prop) &&
16
- o[prop] !== null &&
17
- (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
18
- !Object.isFrozen(o[prop])) {
19
- deepFreeze(o[prop]);
20
- }
21
- });
22
- return o;
23
- }
@@ -1,24 +0,0 @@
1
- // copy-pasted from test-lib to be able to not include devDependecies there
2
-
3
- /**
4
- * Does Object.freeze recursively for given object.
5
- *
6
- * Based on: https://github.com/substack/deep-freeze/blob/master/index.js
7
- */
8
- export function deepFreeze(o: any): void {
9
- Object.freeze(o)
10
-
11
- Object.getOwnPropertyNames(o).forEach(prop => {
12
- if (
13
- // eslint-disable-next-line no-prototype-builtins
14
- o.hasOwnProperty(prop) &&
15
- o[prop] !== null &&
16
- (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
17
- !Object.isFrozen(o[prop])
18
- ) {
19
- deepFreeze(o[prop])
20
- }
21
- })
22
-
23
- return o
24
- }