@naturalcycles/db-lib 8.50.1 → 8.50.3

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.
Files changed (34) hide show
  1. package/dist/adapter/file/file.db.d.ts +8 -8
  2. package/dist/adapter/file/file.db.model.d.ts +4 -4
  3. package/dist/adapter/file/inMemory.persistence.plugin.d.ts +1 -1
  4. package/dist/adapter/file/localFile.persistence.plugin.d.ts +1 -1
  5. package/dist/adapter/file/noop.persistence.plugin.d.ts +1 -1
  6. package/dist/adapter/inmemory/inMemory.db.d.ts +8 -8
  7. package/dist/adapter/inmemory/queryInMemory.d.ts +1 -1
  8. package/dist/common.db.d.ts +12 -12
  9. package/dist/commondao/common.dao.d.ts +16 -5
  10. package/dist/commondao/common.dao.js +68 -0
  11. package/dist/commondao/common.dao.model.d.ts +17 -20
  12. package/dist/db.model.d.ts +2 -1
  13. package/dist/db.model.js +1 -0
  14. package/dist/kv/commonKeyValueDB.d.ts +9 -9
  15. package/dist/kv/commonKeyValueDao.d.ts +3 -3
  16. package/dist/query/dbQuery.d.ts +10 -8
  17. package/dist/query/dbQuery.js +6 -0
  18. package/dist/testing/daoTest.js +1 -0
  19. package/package.json +1 -1
  20. package/src/adapter/file/file.db.model.ts +4 -4
  21. package/src/adapter/file/file.db.ts +12 -12
  22. package/src/adapter/file/inMemory.persistence.plugin.ts +1 -1
  23. package/src/adapter/file/localFile.persistence.plugin.ts +1 -1
  24. package/src/adapter/file/noop.persistence.plugin.ts +1 -1
  25. package/src/adapter/inmemory/inMemory.db.ts +11 -11
  26. package/src/adapter/inmemory/queryInMemory.ts +1 -4
  27. package/src/common.db.ts +24 -18
  28. package/src/commondao/common.dao.model.ts +22 -24
  29. package/src/commondao/common.dao.ts +96 -6
  30. package/src/db.model.ts +1 -0
  31. package/src/kv/commonKeyValueDB.ts +9 -9
  32. package/src/kv/commonKeyValueDao.ts +3 -3
  33. package/src/query/dbQuery.ts +18 -8
  34. package/src/testing/daoTest.ts +2 -0
@@ -21,19 +21,19 @@ export declare class FileDB extends BaseCommonDB implements CommonDB {
21
21
  cfg: FileDBCfg;
22
22
  ping(): Promise<void>;
23
23
  getTables(): Promise<string[]>;
24
- getByIds<ROW extends Partial<ObjectWithId>>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
24
+ getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
25
25
  saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], _opt?: CommonDBSaveOptions<ROW>): Promise<void>;
26
26
  /**
27
27
  * Implementation is optimized for loading/saving _whole files_.
28
28
  */
29
29
  commitTransaction(tx: DBTransaction, _opt?: CommonDBOptions): Promise<void>;
30
- runQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
31
- runQueryCount<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
32
- streamQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
33
- deleteByQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
34
- getTableSchema<ROW extends Partial<ObjectWithId>>(table: string): Promise<JsonSchemaRootObject<ROW>>;
35
- loadFile<ROW extends Partial<ObjectWithId>>(table: string): Promise<ROW[]>;
36
- saveFile<ROW extends Partial<ObjectWithId>>(table: string, _rows: ROW[]): Promise<void>;
30
+ runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
31
+ runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
32
+ streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
33
+ deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
34
+ getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
35
+ loadFile<ROW extends ObjectWithId>(table: string): Promise<ROW[]>;
36
+ saveFile<ROW extends ObjectWithId>(table: string, _rows: ROW[]): Promise<void>;
37
37
  saveFiles<ROW extends ObjectWithId>(ops: DBSaveBatchOperation<ROW>[]): Promise<void>;
38
38
  private sortRows;
39
39
  private logStarted;
@@ -2,10 +2,10 @@ import { CommonLogger, ObjectWithId } from '@naturalcycles/js-lib';
2
2
  import { DBSaveBatchOperation } from '../../db.model';
3
3
  import type { DBQueryOrder } from '../../query/dbQuery';
4
4
  export interface FileDBPersistencePlugin {
5
- ping(): Promise<void>;
6
- getTables(): Promise<string[]>;
7
- loadFile<ROW extends Partial<ObjectWithId>>(table: string): Promise<ROW[]>;
8
- saveFiles(ops: DBSaveBatchOperation<any>[]): Promise<void>;
5
+ ping: () => Promise<void>;
6
+ getTables: () => Promise<string[]>;
7
+ loadFile: <ROW extends ObjectWithId>(table: string) => Promise<ROW[]>;
8
+ saveFiles: (ops: DBSaveBatchOperation<any>[]) => Promise<void>;
9
9
  }
10
10
  export interface FileDBCfg {
11
11
  plugin: FileDBPersistencePlugin;
@@ -8,6 +8,6 @@ export declare class InMemoryPersistencePlugin implements FileDBPersistencePlugi
8
8
  data: StringMap<StringMap<ObjectWithId>>;
9
9
  ping(): Promise<void>;
10
10
  getTables(): Promise<string[]>;
11
- loadFile<ROW extends Partial<ObjectWithId>>(table: string): Promise<ROW[]>;
11
+ loadFile<ROW extends ObjectWithId>(table: string): Promise<ROW[]>;
12
12
  saveFiles(ops: DBSaveBatchOperation[]): Promise<void>;
13
13
  }
@@ -19,7 +19,7 @@ export declare class LocalFilePersistencePlugin implements FileDBPersistencePlug
19
19
  cfg: LocalFilePersistencePluginCfg;
20
20
  ping(): Promise<void>;
21
21
  getTables(): Promise<string[]>;
22
- loadFile<ROW extends Partial<ObjectWithId>>(table: string): Promise<ROW[]>;
22
+ loadFile<ROW extends ObjectWithId>(table: string): Promise<ROW[]>;
23
23
  saveFiles(ops: DBSaveBatchOperation[]): Promise<void>;
24
24
  saveFile<ROW extends ObjectWithId>(table: string, rows: ROW[]): Promise<void>;
25
25
  }
@@ -4,6 +4,6 @@ import { FileDBPersistencePlugin } from './file.db.model';
4
4
  export declare class NoopPersistencePlugin implements FileDBPersistencePlugin {
5
5
  ping(): Promise<void>;
6
6
  getTables(): Promise<string[]>;
7
- loadFile<ROW extends Partial<ObjectWithId>>(_table: string): Promise<ROW[]>;
7
+ loadFile<ROW extends ObjectWithId>(_table: string): Promise<ROW[]>;
8
8
  saveFiles(_ops: DBSaveBatchOperation[]): Promise<void>;
9
9
  }
@@ -50,15 +50,15 @@ export declare class InMemoryDB implements CommonDB {
50
50
  */
51
51
  resetCache(_table?: string): Promise<void>;
52
52
  getTables(): Promise<string[]>;
53
- getTableSchema<ROW extends Partial<ObjectWithId>>(_table: string): Promise<JsonSchemaRootObject<ROW>>;
54
- createTable<ROW extends Partial<ObjectWithId>>(_table: string, _schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
55
- getByIds<ROW extends Partial<ObjectWithId>>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
53
+ getTableSchema<ROW extends ObjectWithId>(_table: string): Promise<JsonSchemaRootObject<ROW>>;
54
+ createTable<ROW extends ObjectWithId>(_table: string, _schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
55
+ getByIds<ROW extends ObjectWithId>(_table: string, ids: ROW['id'][], _opt?: CommonDBOptions): Promise<ROW[]>;
56
56
  saveBatch<ROW extends Partial<ObjectWithId>>(_table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
57
- deleteByQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
58
- updateByQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, patch: DBPatch<ROW>): Promise<number>;
59
- runQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
60
- runQueryCount<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
61
- streamQuery<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, _opt?: CommonDBOptions): ReadableTyped<ROW>;
57
+ deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
58
+ updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>): Promise<number>;
59
+ runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
60
+ runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
61
+ streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): ReadableTyped<ROW>;
62
62
  commitTransaction(tx: DBTransaction, opt?: CommonDBOptions): Promise<void>;
63
63
  /**
64
64
  * Flushes all tables (all namespaces) at once.
@@ -1,3 +1,3 @@
1
1
  import { ObjectWithId } from '@naturalcycles/js-lib';
2
2
  import { DBQuery } from '../../query/dbQuery';
3
- export declare function queryInMemory<ROW extends Partial<ObjectWithId>>(q: DBQuery<ROW>, rows?: ROW[]): ROW[];
3
+ export declare function queryInMemory<ROW extends ObjectWithId>(q: DBQuery<ROW>, rows?: ROW[]): ROW[];
@@ -10,43 +10,43 @@ export interface CommonDB {
10
10
  * It SHOULD fail if DB setup is wrong (e.g on wrong credentials).
11
11
  * It SHOULD succeed if e.g getByIds(['nonExistingKey']) doesn't throw.
12
12
  */
13
- ping(): Promise<void>;
13
+ ping: () => Promise<void>;
14
14
  /**
15
15
  * Return all tables (table names) available in this DB.
16
16
  */
17
- getTables(): Promise<string[]>;
17
+ getTables: () => Promise<string[]>;
18
18
  /**
19
19
  * $id of the schema SHOULD be like this:
20
20
  * `${tableName}.schema.json`
21
21
  *
22
22
  * This is important for the code to rely on it, and it's verified by dbTest
23
23
  */
24
- getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
24
+ getTableSchema: <ROW extends ObjectWithId>(table: string) => Promise<JsonSchemaRootObject<ROW>>;
25
25
  /**
26
26
  * Will do like `create table ...` for mysql.
27
27
  * Caution! dropIfExists defaults to false. If set to true - will actually DROP the table!
28
28
  */
29
- createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
29
+ createTable: <ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions) => Promise<void>;
30
30
  /**
31
31
  * Order of items returned is not guaranteed to match order of ids.
32
32
  * (Such limitation exists because Datastore doesn't support it).
33
33
  */
34
- getByIds<ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions): Promise<ROW[]>;
34
+ getByIds: <ROW extends ObjectWithId>(table: string, ids: ROW['id'][], opt?: CommonDBOptions) => Promise<ROW[]>;
35
35
  /**
36
36
  * Order by 'id' is not supported by all implementations (for example, Datastore doesn't support it).
37
37
  */
38
- runQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
39
- runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
40
- streamQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
38
+ runQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<RunQueryResult<ROW>>;
39
+ runQueryCount: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<number>;
40
+ streamQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBStreamOptions) => ReadableTyped<ROW>;
41
41
  /**
42
42
  * rows can have missing ids only if DB supports auto-generating them (like mysql auto_increment).
43
43
  */
44
- saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
44
+ saveBatch: <ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>) => Promise<void>;
45
45
  /**
46
46
  * Returns number of deleted items.
47
47
  * Not supported by all implementations (e.g Datastore will always return same number as number of ids).
48
48
  */
49
- deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
49
+ deleteByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, opt?: CommonDBOptions) => Promise<number>;
50
50
  /**
51
51
  * Applies patch to the rows returned by the query.
52
52
  *
@@ -65,10 +65,10 @@ export interface CommonDB {
65
65
  *
66
66
  * Returns number of rows affected.
67
67
  */
68
- updateByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CommonDBOptions): Promise<number>;
68
+ updateByQuery: <ROW extends ObjectWithId>(q: DBQuery<ROW>, patch: DBPatch<ROW>, opt?: CommonDBOptions) => Promise<number>;
69
69
  /**
70
70
  * Should be implemented as a Transaction (best effort), which means that
71
71
  * either ALL or NONE of the operations should be applied.
72
72
  */
73
- commitTransaction(tx: DBTransaction, opt?: CommonDBOptions): Promise<void>;
73
+ commitTransaction: (tx: DBTransaction, opt?: CommonDBOptions) => Promise<void>;
74
74
  }
@@ -1,4 +1,4 @@
1
- import { AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Saved, Unsaved } from '@naturalcycles/js-lib';
1
+ import { AnyObject, AsyncMapper, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId, Saved, Unsaved } from '@naturalcycles/js-lib';
2
2
  import { AjvSchema, ObjectSchemaTyped, ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { DBDeleteByIdsOperation, DBModelType, DBOperation, DBPatch, DBSaveBatchOperation, RunQueryResult } from '../db.model';
4
4
  import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
@@ -8,10 +8,11 @@ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveOp
8
8
  *
9
9
  * DBM = Database model (how it's stored in DB)
10
10
  * BM = Backend model (optimized for API access)
11
+ * TM = Transport model (optimized to be sent over the wire)
11
12
  */
12
- export declare class CommonDao<BM extends ObjectWithId<ID>, DBM extends ObjectWithId<ID> = BM, ID extends string | number = BM['id']> {
13
- cfg: CommonDaoCfg<BM, DBM, ID>;
14
- constructor(cfg: CommonDaoCfg<BM, DBM, ID>);
13
+ export declare class CommonDao<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID> = Saved<BM>, TM extends AnyObject = BM, ID extends string | number = NonNullable<BM['id']>> {
14
+ cfg: CommonDaoCfg<BM, DBM, TM, ID>;
15
+ constructor(cfg: CommonDaoCfg<BM, DBM, TM, ID>);
15
16
  create(part?: Partial<BM>, opt?: CommonDaoOptions): Saved<BM>;
16
17
  getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
17
18
  getById(id?: ID | null, opt?: CommonDaoOptions): Promise<Saved<BM> | null>;
@@ -19,6 +20,8 @@ export declare class CommonDao<BM extends ObjectWithId<ID>, DBM extends ObjectWi
19
20
  getByIdAsDBMOrEmpty(id: ID, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
20
21
  getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
21
22
  getByIdAsDBM(id?: ID | null, opt?: CommonDaoOptions): Promise<DBM | null>;
23
+ getByIdAsTM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
24
+ getByIdAsTM(id?: ID | null, opt?: CommonDaoOptions): Promise<TM | null>;
22
25
  getByIds(ids: ID[], opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
23
26
  getByIdsAsDBM(ids: ID[], opt?: CommonDaoOptions): Promise<DBM[]>;
24
27
  requireById(id: ID, opt?: CommonDaoOptions): Promise<Saved<BM>>;
@@ -39,7 +42,7 @@ export declare class CommonDao<BM extends ObjectWithId<ID>, DBM extends ObjectWi
39
42
  /**
40
43
  * Pass `table` to override table
41
44
  */
42
- query(table?: string): RunnableDBQuery<BM, DBM, ID>;
45
+ query(table?: string): RunnableDBQuery<BM, DBM, TM, ID>;
43
46
  runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
44
47
  runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]>;
45
48
  /**
@@ -51,6 +54,8 @@ export declare class CommonDao<BM extends ObjectWithId<ID>, DBM extends ObjectWi
51
54
  runQueryExtended(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<Saved<BM>>>;
52
55
  runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]>;
53
56
  runQueryExtendedAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
57
+ runQueryAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<TM[]>;
58
+ runQueryExtendedAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<TM>>;
54
59
  runQueryCount(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<number>;
55
60
  streamQueryForEach(q: DBQuery<DBM>, mapper: AsyncMapper<Saved<BM>, void>, opt?: CommonDaoStreamForEachOptions<Saved<BM>>): Promise<void>;
56
61
  streamQueryAsDBMForEach(q: DBQuery<DBM>, mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
@@ -131,6 +136,12 @@ export declare class CommonDao<BM extends ObjectWithId<ID>, DBM extends ObjectWi
131
136
  anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined;
132
137
  anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM;
133
138
  anyToDBMs(entities: DBM[], opt?: CommonDaoOptions): DBM[];
139
+ bmToTM(bm: undefined, opt?: CommonDaoOptions): TM | undefined;
140
+ bmToTM(bm?: Saved<BM>, opt?: CommonDaoOptions): TM;
141
+ bmsToTM(bms: Saved<BM>[], opt?: CommonDaoOptions): TM[];
142
+ tmToBM(tm: undefined, opt?: CommonDaoOptions): undefined;
143
+ tmToBM(tm?: TM, opt?: CommonDaoOptions): BM;
144
+ tmsToBM(tms: TM[], opt?: CommonDaoOptions): BM[];
134
145
  /**
135
146
  * Returns *converted value*.
136
147
  * Validates (unless `skipValidation=true` passed).
@@ -15,6 +15,7 @@ const isCI = !!process.env['CI'];
15
15
  *
16
16
  * DBM = Database model (how it's stored in DB)
17
17
  * BM = Backend model (optimized for API access)
18
+ * TM = Transport model (optimized to be sent over the wire)
18
19
  */
19
20
  class CommonDao {
20
21
  constructor(cfg) {
@@ -79,6 +80,8 @@ class CommonDao {
79
80
  beforeDBMValidate: dbm => dbm,
80
81
  beforeDBMToBM: dbm => dbm,
81
82
  beforeBMToDBM: bm => bm,
83
+ beforeTMToBM: tm => tm,
84
+ beforeBMToTM: bm => bm,
82
85
  anonymize: dbm => dbm,
83
86
  onValidationError: err => err,
84
87
  ...cfg.hooks,
@@ -136,6 +139,22 @@ class CommonDao {
136
139
  this.logResult(started, op, dbm, table);
137
140
  return dbm || null;
138
141
  }
142
+ async getByIdAsTM(id, opt = {}) {
143
+ if (!id)
144
+ return null;
145
+ const op = `getByIdAsTM(${id})`;
146
+ const table = opt.table || this.cfg.table;
147
+ const started = this.logStarted(op, table);
148
+ const [dbm] = await this.cfg.db.getByIds(table, [id]);
149
+ if (opt.raw) {
150
+ this.logResult(started, op, dbm, table);
151
+ return dbm || null;
152
+ }
153
+ const bm = await this.dbmToBM(dbm, opt);
154
+ const tm = this.bmToTM(bm, opt);
155
+ this.logResult(started, op, tm, table);
156
+ return tm || null;
157
+ }
139
158
  async getByIds(ids, opt = {}) {
140
159
  const op = `getByIds ${ids.length} id(s) (${(0, js_lib_1._truncate)(ids.slice(0, 10).join(', '), 50)})`;
141
160
  const table = opt.table || this.cfg.table;
@@ -271,6 +290,23 @@ class CommonDao {
271
290
  this.logResult(started, op, dbms, q.table);
272
291
  return { rows: dbms, ...queryResult };
273
292
  }
293
+ async runQueryAsTM(q, opt) {
294
+ const { rows } = await this.runQueryExtendedAsTM(q, opt);
295
+ return rows;
296
+ }
297
+ async runQueryExtendedAsTM(q, opt = {}) {
298
+ q.table = opt.table || q.table;
299
+ const op = `runQueryAsTM(${q.pretty()})`;
300
+ const started = this.logStarted(op, q.table);
301
+ const { rows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
302
+ const partialQuery = !!q._selectedFieldNames;
303
+ const tms = partialQuery || opt.raw ? rows : this.bmsToTM(await this.dbmsToBM(rows, opt), opt);
304
+ this.logResult(started, op, tms, q.table);
305
+ return {
306
+ rows: tms,
307
+ ...queryResult,
308
+ };
309
+ }
274
310
  async runQueryCount(q, opt = {}) {
275
311
  q.table = opt.table || q.table;
276
312
  const op = `runQueryCount(${q.pretty()})`;
@@ -732,6 +768,38 @@ class CommonDao {
732
768
  anyToDBMs(entities, opt = {}) {
733
769
  return entities.map(entity => this.anyToDBM(entity, opt));
734
770
  }
771
+ bmToTM(bm, opt) {
772
+ if (bm === undefined)
773
+ return;
774
+ // optimization: 1 validation is enough
775
+ // Validate/convert BM
776
+ // bm gets assigned to the new reference
777
+ // bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
778
+ // BM > TM
779
+ const tm = this.cfg.hooks.beforeBMToTM(bm);
780
+ // Validate/convert DBM
781
+ return this.validateAndConvert(tm, this.cfg.tmSchema, db_model_1.DBModelType.TM, opt);
782
+ }
783
+ bmsToTM(bms, opt = {}) {
784
+ // try/catch?
785
+ return bms.map(bm => this.bmToTM(bm, opt));
786
+ }
787
+ tmToBM(tm, opt = {}) {
788
+ if (!tm)
789
+ return;
790
+ // optimization: 1 validation is enough
791
+ // Validate/convert TM
792
+ // bm gets assigned to the new reference
793
+ // tm = this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
794
+ // TM > BM
795
+ const bm = this.cfg.hooks.beforeTMToBM(tm);
796
+ // Validate/convert BM
797
+ return this.validateAndConvert(bm, this.cfg.bmSchema, db_model_1.DBModelType.BM, opt);
798
+ }
799
+ tmsToBM(tms, opt = {}) {
800
+ // try/catch?
801
+ return tms.map(tm => this.tmToBM(tm, opt));
802
+ }
735
803
  /**
736
804
  * Returns *converted value*.
737
805
  * Validates (unless `skipValidation=true` passed).
@@ -1,30 +1,29 @@
1
- import { CommonLogger, ErrorMode, ObjectWithId } from '@naturalcycles/js-lib';
1
+ import { CommonLogger, ErrorMode, ObjectWithId, Saved } from '@naturalcycles/js-lib';
2
2
  import { AjvSchema, AjvValidationError, JoiValidationError, ObjectSchemaTyped, 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 Partial<ObjectWithId<ID>>, DBM extends Partial<ObjectWithId<ID>> = BM, ID extends string | number = NonNullable<BM['id']>> {
6
- createRandomId(): ID;
5
+ export interface CommonDaoHooks<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID>, TM, ID extends string | number> {
6
+ createRandomId: () => ID;
7
7
  /**
8
8
  * createNaturalId hook is called (tried) first.
9
9
  * If it doesn't exist - createRandomId is called.
10
10
  */
11
- createNaturalId(obj: DBM | BM): ID;
12
- parseNaturalId(id: ID): Partial<DBM>;
13
- beforeCreate(bm: Partial<BM>): Partial<BM>;
14
- beforeDBMValidate(dbm: Partial<DBM>): Partial<DBM>;
15
- beforeDBMToBM(dbm: DBM): Partial<BM> | Promise<Partial<BM>>;
16
- beforeBMToDBM(bm: BM): Partial<DBM> | Promise<Partial<DBM>>;
17
- /**
18
- * Applicable to **read** operations, never to **save** operations.
19
- */
20
- anonymize(dbm: DBM): DBM;
11
+ createNaturalId: (obj: DBM | BM) => ID;
12
+ parseNaturalId: (id: ID) => Partial<DBM>;
13
+ beforeCreate: (bm: Partial<BM>) => Partial<BM>;
14
+ beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>;
15
+ beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>;
16
+ beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>;
17
+ beforeTMToBM: (tm: TM) => Partial<BM>;
18
+ beforeBMToTM: (bm: BM) => Partial<TM>;
19
+ anonymize: (dbm: DBM) => DBM;
21
20
  /**
22
21
  * If hook is defined - allows to prevent or modify the error thrown.
23
22
  * Return `false` to prevent throwing an error.
24
23
  * Return original `err` to pass the error through (will be thrown in CommonDao).
25
24
  * Return modified/new `Error` if needed.
26
25
  */
27
- onValidationError(err: JoiValidationError | AjvValidationError): Error | false;
26
+ onValidationError: (err: JoiValidationError | AjvValidationError) => Error | false;
28
27
  }
29
28
  export declare enum CommonDaoLogLevel {
30
29
  /**
@@ -44,7 +43,7 @@ export declare enum CommonDaoLogLevel {
44
43
  */
45
44
  DATA_FULL = 30
46
45
  }
47
- export interface CommonDaoCfg<BM extends ObjectWithId<ID>, DBM extends ObjectWithId<ID> = BM, ID extends string | number = BM['id']> {
46
+ export interface CommonDaoCfg<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID> = Saved<BM>, TM = BM, ID extends string | number = string> {
48
47
  db: CommonDB;
49
48
  table: string;
50
49
  /**
@@ -52,6 +51,7 @@ export interface CommonDaoCfg<BM extends ObjectWithId<ID>, DBM extends ObjectWit
52
51
  */
53
52
  dbmSchema?: ObjectSchemaTyped<DBM> | AjvSchema<DBM>;
54
53
  bmSchema?: ObjectSchemaTyped<BM> | AjvSchema<BM>;
54
+ tmSchema?: ObjectSchemaTyped<TM> | AjvSchema<TM>;
55
55
  excludeFromIndexes?: (keyof DBM)[];
56
56
  /**
57
57
  * Defaults to false.
@@ -61,8 +61,6 @@ export interface CommonDaoCfg<BM extends ObjectWithId<ID>, DBM extends ObjectWit
61
61
  * `delete*` and `patch` will throw.
62
62
  *
63
63
  * You can still override saveMethod, or set opt.allowMutability to allow deletion.
64
- *
65
- * todo: consider merging it with readOnly, as it's almost the same
66
64
  */
67
65
  immutable?: boolean;
68
66
  /**
@@ -82,7 +80,7 @@ export interface CommonDaoCfg<BM extends ObjectWithId<ID>, DBM extends ObjectWit
82
80
  * @default false
83
81
  */
84
82
  logStarted?: boolean;
85
- hooks?: Partial<CommonDaoHooks<BM, DBM, ID>>;
83
+ hooks?: Partial<CommonDaoHooks<BM, DBM, TM, ID>>;
86
84
  /**
87
85
  * Defaults to 'string'
88
86
  */
@@ -96,7 +94,6 @@ export interface CommonDaoCfg<BM extends ObjectWithId<ID>, DBM extends ObjectWit
96
94
  /**
97
95
  * See the same option in CommonDB.
98
96
  * Defaults to false normally.
99
- * "Generated" means "generated by the underlying DB" (e.g MySQL autoincrement).
100
97
  */
101
98
  assignGeneratedIds?: boolean;
102
99
  /**
@@ -182,7 +179,7 @@ export interface CommonDaoOptions extends CommonDBOptions {
182
179
  /**
183
180
  * All properties default to undefined.
184
181
  */
185
- export interface CommonDaoSaveOptions<DBM extends Partial<ObjectWithId>> extends CommonDaoOptions, CommonDBSaveOptions<DBM> {
182
+ export interface CommonDaoSaveOptions<DBM extends ObjectWithId> extends CommonDaoOptions, CommonDBSaveOptions<DBM> {
186
183
  /**
187
184
  * @default false
188
185
  *
@@ -59,7 +59,8 @@ export declare enum DBRelation {
59
59
  }
60
60
  export declare enum DBModelType {
61
61
  DBM = "DBM",
62
- BM = "BM"
62
+ BM = "BM",
63
+ TM = "TM"
63
64
  }
64
65
  /**
65
66
  * Allows to construct a query similar to:
package/dist/db.model.js CHANGED
@@ -10,6 +10,7 @@ var DBModelType;
10
10
  (function (DBModelType) {
11
11
  DBModelType["DBM"] = "DBM";
12
12
  DBModelType["BM"] = "BM";
13
+ DBModelType["TM"] = "TM";
13
14
  })(DBModelType = exports.DBModelType || (exports.DBModelType = {}));
14
15
  /**
15
16
  * Allows to construct a query similar to:
@@ -11,22 +11,22 @@ export interface CommonKeyValueDB {
11
11
  /**
12
12
  * Check that DB connection is working properly.
13
13
  */
14
- ping(): Promise<void>;
14
+ ping: () => Promise<void>;
15
15
  /**
16
16
  * Will do like `create table ...` for mysql.
17
17
  * Caution! dropIfExists defaults to false. If set to true - will actually DROP the table!
18
18
  */
19
- createTable(table: string, opt?: CommonDBCreateOptions): Promise<void>;
19
+ createTable: (table: string, opt?: CommonDBCreateOptions) => Promise<void>;
20
20
  /**
21
21
  * Returns an array of tuples [key, value]. Not found values are not returned (no error is thrown).
22
22
  *
23
23
  * Currently it is NOT required to maintain the same order as input `ids`.
24
24
  */
25
- getByIds(table: string, ids: string[]): Promise<KeyValueDBTuple[]>;
26
- deleteByIds(table: string, ids: string[]): Promise<void>;
27
- saveBatch(table: string, entries: KeyValueDBTuple[]): Promise<void>;
28
- streamIds(table: string, limit?: number): ReadableTyped<string>;
29
- streamValues(table: string, limit?: number): ReadableTyped<Buffer>;
30
- streamEntries(table: string, limit?: number): ReadableTyped<KeyValueDBTuple>;
31
- count(table: string): Promise<number>;
25
+ getByIds: (table: string, ids: string[]) => Promise<KeyValueDBTuple[]>;
26
+ deleteByIds: (table: string, ids: string[]) => Promise<void>;
27
+ saveBatch: (table: string, entries: KeyValueDBTuple[]) => Promise<void>;
28
+ streamIds: (table: string, limit?: number) => ReadableTyped<string>;
29
+ streamValues: (table: string, limit?: number) => ReadableTyped<Buffer>;
30
+ streamEntries: (table: string, limit?: number) => ReadableTyped<KeyValueDBTuple>;
31
+ count: (table: string) => Promise<number>;
32
32
  }
@@ -21,9 +21,9 @@ export interface CommonKeyValueDaoCfg<T> {
21
21
  */
22
22
  logStarted?: boolean;
23
23
  hooks?: {
24
- mapValueToBuffer?(v: T): Promise<Buffer>;
25
- mapBufferToValue?(b: Buffer): Promise<T>;
26
- beforeCreate?(v: Partial<T>): Partial<T>;
24
+ mapValueToBuffer?: (v: T) => Promise<Buffer>;
25
+ mapBufferToValue?: (b: Buffer) => Promise<T>;
26
+ beforeCreate?: (v: Partial<T>) => Partial<T>;
27
27
  };
28
28
  /**
29
29
  * Set to `true` to conveniently enable zipping+JSON.stringify
@@ -1,4 +1,4 @@
1
- import { AnyObjectWithId, ObjectWithId, AsyncMapper, Saved } from '@naturalcycles/js-lib';
1
+ import { AnyObjectWithId, ObjectWithId, AsyncMapper, Saved, AnyObject } from '@naturalcycles/js-lib';
2
2
  import { ReadableTyped } from '@naturalcycles/nodejs-lib';
3
3
  import { CommonDaoOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, DBPatch } from '..';
4
4
  import { CommonDao } from '../commondao/common.dao';
@@ -24,12 +24,12 @@ import { RunQueryResult } from '../db.model';
24
24
  */
25
25
  export type DBQueryFilterOperator = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'in' | 'not-in' | 'array-contains' | 'array-contains-any';
26
26
  export declare const dbQueryFilterOperatorValues: DBQueryFilterOperator[];
27
- export interface DBQueryFilter<ROW extends Partial<ObjectWithId> = AnyObjectWithId> {
27
+ export interface DBQueryFilter<ROW extends ObjectWithId = AnyObjectWithId> {
28
28
  name: keyof ROW;
29
29
  op: DBQueryFilterOperator;
30
30
  val: any;
31
31
  }
32
- export interface DBQueryOrder<ROW extends Partial<ObjectWithId> = AnyObjectWithId> {
32
+ export interface DBQueryOrder<ROW extends ObjectWithId = AnyObjectWithId> {
33
33
  name: keyof ROW;
34
34
  descending?: boolean;
35
35
  }
@@ -43,14 +43,14 @@ export interface DBQueryOrder<ROW extends Partial<ObjectWithId> = AnyObjectWithI
43
43
  *
44
44
  * <DBM> is the type of **queried** object (so e.g `key of DBM` can be used), not **returned** object.
45
45
  */
46
- export declare class DBQuery<ROW extends Partial<ObjectWithId> = AnyObjectWithId> {
46
+ export declare class DBQuery<ROW extends ObjectWithId = AnyObjectWithId> {
47
47
  table: string;
48
48
  constructor(table: string);
49
49
  /**
50
50
  * Convenience method.
51
51
  */
52
52
  static create<ROW extends ObjectWithId = AnyObjectWithId>(table: string): DBQuery<ROW>;
53
- static fromPlainObject<ROW extends Partial<ObjectWithId> = AnyObjectWithId>(obj: Partial<DBQuery<ROW>> & {
53
+ static fromPlainObject<ROW extends ObjectWithId = AnyObjectWithId>(obj: Partial<DBQuery<ROW>> & {
54
54
  table: string;
55
55
  }): DBQuery<ROW>;
56
56
  _filters: DBQueryFilter<ROW>[];
@@ -84,17 +84,19 @@ export declare class DBQuery<ROW extends Partial<ObjectWithId> = AnyObjectWithId
84
84
  /**
85
85
  * DBQuery that has additional method to support Fluent API style.
86
86
  */
87
- export declare class RunnableDBQuery<BM extends ObjectWithId<ID>, DBM extends ObjectWithId<ID> = BM, ID extends string | number = BM['id']> extends DBQuery<DBM> {
88
- dao: CommonDao<BM, DBM, ID>;
87
+ export declare class RunnableDBQuery<BM extends Partial<ObjectWithId<ID>>, DBM extends ObjectWithId<ID> = Saved<BM>, TM extends AnyObject = BM, ID extends string | number = string> extends DBQuery<DBM> {
88
+ dao: CommonDao<BM, DBM, TM, ID>;
89
89
  /**
90
90
  * Pass `table` to override table.
91
91
  */
92
- constructor(dao: CommonDao<BM, DBM, ID>, table?: string);
92
+ constructor(dao: CommonDao<BM, DBM, TM, ID>, table?: string);
93
93
  runQuery(opt?: CommonDaoOptions): Promise<Saved<BM>[]>;
94
94
  runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
95
95
  runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
96
+ runQueryAsTM(opt?: CommonDaoOptions): Promise<TM[]>;
96
97
  runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<Saved<BM>>>;
97
98
  runQueryExtendedAsDBM(opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
99
+ runQueryExtendedAsTM(opt?: CommonDaoOptions): Promise<RunQueryResult<TM>>;
98
100
  runQueryCount(opt?: CommonDaoOptions): Promise<number>;
99
101
  updateByQuery(patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
100
102
  streamQueryForEach(mapper: AsyncMapper<Saved<BM>, void>, opt?: CommonDaoStreamForEachOptions<Saved<BM>>): Promise<void>;
@@ -153,12 +153,18 @@ class RunnableDBQuery extends DBQuery {
153
153
  async runQueryAsDBM(opt) {
154
154
  return await this.dao.runQueryAsDBM(this, opt);
155
155
  }
156
+ async runQueryAsTM(opt) {
157
+ return await this.dao.runQueryAsTM(this, opt);
158
+ }
156
159
  async runQueryExtended(opt) {
157
160
  return await this.dao.runQueryExtended(this, opt);
158
161
  }
159
162
  async runQueryExtendedAsDBM(opt) {
160
163
  return await this.dao.runQueryExtendedAsDBM(this, opt);
161
164
  }
165
+ async runQueryExtendedAsTM(opt) {
166
+ return await this.dao.runQueryExtendedAsTM(this, opt);
167
+ }
162
168
  async runQueryCount(opt) {
163
169
  return await this.dao.runQueryCount(this, opt);
164
170
  }
@@ -13,6 +13,7 @@ function runCommonDaoTest(db, features = {}, quirks = {}) {
13
13
  db,
14
14
  dbmSchema: test_model_1.testItemDBMSchema,
15
15
  bmSchema: test_model_1.testItemBMSchema,
16
+ tmSchema: test_model_1.testItemTMSchema,
16
17
  logStarted: true,
17
18
  logLevel: __1.CommonDaoLogLevel.DATA_FULL,
18
19
  });
package/package.json CHANGED
@@ -41,7 +41,7 @@
41
41
  "engines": {
42
42
  "node": ">=14.15"
43
43
  },
44
- "version": "8.50.1",
44
+ "version": "8.50.3",
45
45
  "description": "Lowest Common Denominator API to supported Databases",
46
46
  "keywords": [
47
47
  "db",
@@ -3,10 +3,10 @@ import { DBSaveBatchOperation } from '../../db.model'
3
3
  import type { DBQueryOrder } from '../../query/dbQuery'
4
4
 
5
5
  export interface FileDBPersistencePlugin {
6
- ping(): Promise<void>
7
- getTables(): Promise<string[]>
8
- loadFile<ROW extends Partial<ObjectWithId>>(table: string): Promise<ROW[]>
9
- saveFiles(ops: DBSaveBatchOperation<any>[]): Promise<void>
6
+ ping: () => Promise<void>
7
+ getTables: () => Promise<string[]>
8
+ loadFile: <ROW extends ObjectWithId>(table: string) => Promise<ROW[]>
9
+ saveFiles: (ops: DBSaveBatchOperation<any>[]) => Promise<void>
10
10
  }
11
11
 
12
12
  export interface FileDBCfg {