@naturalcycles/db-lib 9.4.2 → 9.6.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.
- package/dist/commondao/common.dao.d.ts +11 -18
- package/dist/commondao/common.dao.js +52 -118
- package/dist/commondao/common.dao.model.d.ts +4 -36
- package/dist/db.model.d.ts +1 -2
- package/dist/db.model.js +0 -1
- package/dist/query/dbQuery.d.ts +4 -6
- package/dist/query/dbQuery.js +0 -6
- package/dist/testing/daoTest.js +1 -3
- package/dist/testing/dbTest.js +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +1 -3
- package/dist/testing/test.model.d.ts +0 -2
- package/dist/testing/test.model.js +1 -21
- package/package.json +1 -1
- package/src/commondao/common.dao.model.ts +3 -43
- package/src/commondao/common.dao.ts +60 -157
- package/src/db.model.ts +0 -1
- package/src/query/dbQuery.ts +1 -11
- package/src/testing/daoTest.ts +2 -6
- package/src/testing/dbTest.ts +2 -2
- package/src/testing/index.ts +0 -4
- package/src/testing/test.model.ts +0 -22
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Transform } from 'node:stream';
|
|
3
|
-
import {
|
|
3
|
+
import { AsyncMapper, BaseDBEntity, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, UnixTimestampMillisNumber, Unsaved, ZodSchema } from '@naturalcycles/js-lib';
|
|
4
4
|
import { AjvSchema, ObjectSchema, ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
5
|
-
import { CommonDBTransactionOptions,
|
|
5
|
+
import { CommonDBTransactionOptions, DBPatch, DBTransaction, RunQueryResult } from '../db.model';
|
|
6
6
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery';
|
|
7
7
|
import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveBatchOptions, CommonDaoSaveOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, CommonDaoStreamSaveOptions } from './common.dao.model';
|
|
8
8
|
/**
|
|
@@ -12,9 +12,9 @@ import { CommonDaoCfg, CommonDaoCreateOptions, CommonDaoOptions, CommonDaoSaveBa
|
|
|
12
12
|
* BM = Backend model (optimized for API access)
|
|
13
13
|
* TM = Transport model (optimized to be sent over the wire)
|
|
14
14
|
*/
|
|
15
|
-
export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM
|
|
16
|
-
cfg: CommonDaoCfg<BM, DBM
|
|
17
|
-
constructor(cfg: CommonDaoCfg<BM, DBM
|
|
15
|
+
export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
16
|
+
cfg: CommonDaoCfg<BM, DBM>;
|
|
17
|
+
constructor(cfg: CommonDaoCfg<BM, DBM>);
|
|
18
18
|
create(part?: Partial<BM>, opt?: CommonDaoOptions): BM;
|
|
19
19
|
getById(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
|
|
20
20
|
getById(id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
|
|
@@ -22,8 +22,6 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
22
22
|
getByIdAsDBMOrEmpty(id: string, part?: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM>;
|
|
23
23
|
getByIdAsDBM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
|
|
24
24
|
getByIdAsDBM(id?: string | null, opt?: CommonDaoOptions): Promise<DBM | null>;
|
|
25
|
-
getByIdAsTM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>;
|
|
26
|
-
getByIdAsTM(id?: string | null, opt?: CommonDaoOptions): Promise<TM | null>;
|
|
27
25
|
getByIds(ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
|
|
28
26
|
getByIdsAsDBM(ids: string[], opt?: CommonDaoOptions): Promise<DBM[]>;
|
|
29
27
|
requireById(id: string, opt?: CommonDaoOptions): Promise<BM>;
|
|
@@ -44,7 +42,7 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
44
42
|
/**
|
|
45
43
|
* Pass `table` to override table
|
|
46
44
|
*/
|
|
47
|
-
query(table?: string): RunnableDBQuery<BM, DBM
|
|
45
|
+
query(table?: string): RunnableDBQuery<BM, DBM>;
|
|
48
46
|
runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<BM[]>;
|
|
49
47
|
runQuerySingleColumn<T = any>(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<T[]>;
|
|
50
48
|
/**
|
|
@@ -56,8 +54,6 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
56
54
|
runQueryExtended(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<BM>>;
|
|
57
55
|
runQueryAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<DBM[]>;
|
|
58
56
|
runQueryExtendedAsDBM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
|
|
59
|
-
runQueryAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<TM[]>;
|
|
60
|
-
runQueryExtendedAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<RunQueryResult<TM>>;
|
|
61
57
|
runQueryCount(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<number>;
|
|
62
58
|
streamQueryForEach(q: DBQuery<DBM>, mapper: AsyncMapper<BM, void>, opt?: CommonDaoStreamForEachOptions<BM>): Promise<void>;
|
|
63
59
|
streamQueryAsDBMForEach(q: DBQuery<DBM>, mapper: AsyncMapper<DBM, void>, opt?: CommonDaoStreamForEachOptions<DBM>): Promise<void>;
|
|
@@ -159,16 +155,13 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
159
155
|
anyToDBM(dbm: undefined, opt?: CommonDaoOptions): undefined;
|
|
160
156
|
anyToDBM(dbm?: any, opt?: CommonDaoOptions): DBM;
|
|
161
157
|
anyToDBMs(entities: DBM[], opt?: CommonDaoOptions): DBM[];
|
|
162
|
-
bmToTM(bm: undefined, opt?: CommonDaoOptions): TM | undefined;
|
|
163
|
-
bmToTM(bm?: BM, opt?: CommonDaoOptions): TM;
|
|
164
|
-
bmsToTM(bms: BM[], opt?: CommonDaoOptions): TM[];
|
|
165
158
|
/**
|
|
166
159
|
* Returns *converted value*.
|
|
167
160
|
* Validates (unless `skipValidation=true` passed).
|
|
168
161
|
*
|
|
169
162
|
* Does NOT mutate the object.
|
|
170
163
|
*/
|
|
171
|
-
validateAndConvert<T>(obj: Partial<T>, schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined,
|
|
164
|
+
validateAndConvert<T>(obj: Partial<T>, schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined, opt?: CommonDaoOptions): any;
|
|
172
165
|
getTableSchema(): Promise<JsonSchemaRootObject<DBM>>;
|
|
173
166
|
createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void>;
|
|
174
167
|
/**
|
|
@@ -199,10 +192,10 @@ export declare class CommonDaoTransaction {
|
|
|
199
192
|
* Perform a graceful rollback without throwing/re-throwing any error.
|
|
200
193
|
*/
|
|
201
194
|
rollback(): Promise<void>;
|
|
202
|
-
getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM
|
|
203
|
-
getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM
|
|
204
|
-
save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM
|
|
205
|
-
saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM
|
|
195
|
+
getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, id?: string | null, opt?: CommonDaoOptions): Promise<BM | null>;
|
|
196
|
+
getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, ids: string[], opt?: CommonDaoOptions): Promise<BM[]>;
|
|
197
|
+
save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bm: Unsaved<BM>, opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM>;
|
|
198
|
+
saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(dao: CommonDao<BM, DBM>, bms: Unsaved<BM>[], opt?: CommonDaoSaveBatchOptions<DBM>): Promise<BM[]>;
|
|
206
199
|
deleteById(dao: CommonDao<any>, id?: string | null, opt?: CommonDaoOptions): Promise<number>;
|
|
207
200
|
deleteByIds(dao: CommonDao<any>, ids: string[], opt?: CommonDaoOptions): Promise<number>;
|
|
208
201
|
}
|
|
@@ -4,7 +4,6 @@ exports.CommonDaoTransaction = exports.CommonDao = void 0;
|
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const cnst_1 = require("../cnst");
|
|
7
|
-
const db_model_1 = require("../db.model");
|
|
8
7
|
const dbQuery_1 = require("../query/dbQuery");
|
|
9
8
|
const common_dao_model_1 = require("./common.dao.model");
|
|
10
9
|
const isGAE = !!process.env['GAE_INSTANCE'];
|
|
@@ -33,10 +32,6 @@ class CommonDao {
|
|
|
33
32
|
hooks: {
|
|
34
33
|
parseNaturalId: () => ({}),
|
|
35
34
|
beforeCreate: bm => bm,
|
|
36
|
-
beforeDBMValidate: dbm => dbm,
|
|
37
|
-
beforeDBMToBM: dbm => dbm,
|
|
38
|
-
beforeBMToDBM: bm => bm,
|
|
39
|
-
beforeBMToTM: bm => bm,
|
|
40
35
|
anonymize: dbm => dbm,
|
|
41
36
|
onValidationError: err => err,
|
|
42
37
|
...cfg.hooks,
|
|
@@ -54,7 +49,7 @@ class CommonDao {
|
|
|
54
49
|
const bm = this.cfg.hooks.beforeCreate(part);
|
|
55
50
|
// First assignIdCreatedUpdated, then validate!
|
|
56
51
|
this.assignIdCreatedUpdated(bm, opt);
|
|
57
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema,
|
|
52
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
58
53
|
}
|
|
59
54
|
async getById(id, opt = {}) {
|
|
60
55
|
if (!id)
|
|
@@ -63,10 +58,10 @@ class CommonDao {
|
|
|
63
58
|
const table = opt.table || this.cfg.table;
|
|
64
59
|
const started = this.logStarted(op, table);
|
|
65
60
|
let dbm = (await (opt.tx || this.cfg.db).getByIds(table, [id]))[0];
|
|
66
|
-
if (dbm &&
|
|
61
|
+
if (dbm && this.cfg.hooks.afterLoad) {
|
|
67
62
|
dbm = (await this.cfg.hooks.afterLoad(dbm)) || undefined;
|
|
68
63
|
}
|
|
69
|
-
const bm =
|
|
64
|
+
const bm = await this.dbmToBM(dbm, opt);
|
|
70
65
|
this.logResult(started, op, bm, table);
|
|
71
66
|
return bm || null;
|
|
72
67
|
}
|
|
@@ -90,34 +85,13 @@ class CommonDao {
|
|
|
90
85
|
const table = opt.table || this.cfg.table;
|
|
91
86
|
const started = this.logStarted(op, table);
|
|
92
87
|
let [dbm] = await (opt.tx || this.cfg.db).getByIds(table, [id]);
|
|
93
|
-
if (dbm &&
|
|
88
|
+
if (dbm && this.cfg.hooks.afterLoad) {
|
|
94
89
|
dbm = (await this.cfg.hooks.afterLoad(dbm)) || undefined;
|
|
95
90
|
}
|
|
96
|
-
|
|
97
|
-
dbm = this.anyToDBM(dbm, opt);
|
|
98
|
-
}
|
|
91
|
+
dbm = this.anyToDBM(dbm, opt);
|
|
99
92
|
this.logResult(started, op, dbm, table);
|
|
100
93
|
return dbm || null;
|
|
101
94
|
}
|
|
102
|
-
async getByIdAsTM(id, opt = {}) {
|
|
103
|
-
if (!id)
|
|
104
|
-
return null;
|
|
105
|
-
const op = `getByIdAsTM(${id})`;
|
|
106
|
-
const table = opt.table || this.cfg.table;
|
|
107
|
-
const started = this.logStarted(op, table);
|
|
108
|
-
let [dbm] = await (opt.tx || this.cfg.db).getByIds(table, [id]);
|
|
109
|
-
if (dbm && !opt.raw && this.cfg.hooks.afterLoad) {
|
|
110
|
-
dbm = (await this.cfg.hooks.afterLoad(dbm)) || undefined;
|
|
111
|
-
}
|
|
112
|
-
if (opt.raw) {
|
|
113
|
-
this.logResult(started, op, dbm, table);
|
|
114
|
-
return dbm || null;
|
|
115
|
-
}
|
|
116
|
-
const bm = await this.dbmToBM(dbm, opt);
|
|
117
|
-
const tm = this.bmToTM(bm, opt);
|
|
118
|
-
this.logResult(started, op, tm, table);
|
|
119
|
-
return tm || null;
|
|
120
|
-
}
|
|
121
95
|
async getByIds(ids, opt = {}) {
|
|
122
96
|
if (!ids.length)
|
|
123
97
|
return [];
|
|
@@ -125,10 +99,10 @@ class CommonDao {
|
|
|
125
99
|
const table = opt.table || this.cfg.table;
|
|
126
100
|
const started = this.logStarted(op, table);
|
|
127
101
|
let dbms = await (opt.tx || this.cfg.db).getByIds(table, ids);
|
|
128
|
-
if (
|
|
102
|
+
if (this.cfg.hooks.afterLoad && dbms.length) {
|
|
129
103
|
dbms = (await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
|
|
130
104
|
}
|
|
131
|
-
const bms =
|
|
105
|
+
const bms = await this.dbmsToBM(dbms, opt);
|
|
132
106
|
this.logResult(started, op, bms, table);
|
|
133
107
|
return bms;
|
|
134
108
|
}
|
|
@@ -139,7 +113,7 @@ class CommonDao {
|
|
|
139
113
|
const table = opt.table || this.cfg.table;
|
|
140
114
|
const started = this.logStarted(op, table);
|
|
141
115
|
let dbms = await (opt.tx || this.cfg.db).getByIds(table, ids);
|
|
142
|
-
if (
|
|
116
|
+
if (this.cfg.hooks.afterLoad && dbms.length) {
|
|
143
117
|
dbms = (await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
|
|
144
118
|
}
|
|
145
119
|
this.logResult(started, op, dbms, table);
|
|
@@ -238,10 +212,10 @@ class CommonDao {
|
|
|
238
212
|
const started = this.logStarted(op, q.table);
|
|
239
213
|
let { rows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
|
|
240
214
|
const partialQuery = !!q._selectedFieldNames;
|
|
241
|
-
if (
|
|
215
|
+
if (this.cfg.hooks.afterLoad && rows.length) {
|
|
242
216
|
rows = (await (0, js_lib_1.pMap)(rows, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
|
|
243
217
|
}
|
|
244
|
-
const bms = partialQuery
|
|
218
|
+
const bms = partialQuery ? rows : await this.dbmsToBM(rows, opt);
|
|
245
219
|
this.logResult(started, op, bms, q.table);
|
|
246
220
|
return {
|
|
247
221
|
rows: bms,
|
|
@@ -257,34 +231,14 @@ class CommonDao {
|
|
|
257
231
|
const op = `runQueryAsDBM(${q.pretty()})`;
|
|
258
232
|
const started = this.logStarted(op, q.table);
|
|
259
233
|
let { rows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
|
|
260
|
-
if (
|
|
234
|
+
if (this.cfg.hooks.afterLoad && rows.length) {
|
|
261
235
|
rows = (await (0, js_lib_1.pMap)(rows, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
|
|
262
236
|
}
|
|
263
237
|
const partialQuery = !!q._selectedFieldNames;
|
|
264
|
-
const dbms = partialQuery
|
|
238
|
+
const dbms = partialQuery ? rows : this.anyToDBMs(rows, opt);
|
|
265
239
|
this.logResult(started, op, dbms, q.table);
|
|
266
240
|
return { rows: dbms, ...queryResult };
|
|
267
241
|
}
|
|
268
|
-
async runQueryAsTM(q, opt) {
|
|
269
|
-
const { rows } = await this.runQueryExtendedAsTM(q, opt);
|
|
270
|
-
return rows;
|
|
271
|
-
}
|
|
272
|
-
async runQueryExtendedAsTM(q, opt = {}) {
|
|
273
|
-
q.table = opt.table || q.table;
|
|
274
|
-
const op = `runQueryAsTM(${q.pretty()})`;
|
|
275
|
-
const started = this.logStarted(op, q.table);
|
|
276
|
-
let { rows, ...queryResult } = await this.cfg.db.runQuery(q, opt);
|
|
277
|
-
if (!opt.raw && this.cfg.hooks.afterLoad && rows.length) {
|
|
278
|
-
rows = (await (0, js_lib_1.pMap)(rows, async (dbm) => await this.cfg.hooks.afterLoad(dbm))).filter(js_lib_1._isTruthy);
|
|
279
|
-
}
|
|
280
|
-
const partialQuery = !!q._selectedFieldNames;
|
|
281
|
-
const tms = partialQuery || opt.raw ? rows : this.bmsToTM(await this.dbmsToBM(rows, opt), opt);
|
|
282
|
-
this.logResult(started, op, tms, q.table);
|
|
283
|
-
return {
|
|
284
|
-
rows: tms,
|
|
285
|
-
...queryResult,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
242
|
async runQueryCount(q, opt = {}) {
|
|
289
243
|
q.table = opt.table || q.table;
|
|
290
244
|
const op = `runQueryCount(${q.pretty()})`;
|
|
@@ -308,7 +262,7 @@ class CommonDao {
|
|
|
308
262
|
this.cfg.db.streamQuery(q, opt),
|
|
309
263
|
(0, nodejs_lib_1.transformMap)(async (dbm) => {
|
|
310
264
|
count++;
|
|
311
|
-
if (partialQuery
|
|
265
|
+
if (partialQuery)
|
|
312
266
|
return dbm;
|
|
313
267
|
if (this.cfg.hooks.afterLoad) {
|
|
314
268
|
dbm = (await this.cfg.hooks.afterLoad(dbm));
|
|
@@ -347,7 +301,7 @@ class CommonDao {
|
|
|
347
301
|
this.cfg.db.streamQuery(q, opt),
|
|
348
302
|
(0, nodejs_lib_1.transformMap)(async (dbm) => {
|
|
349
303
|
count++;
|
|
350
|
-
if (partialQuery
|
|
304
|
+
if (partialQuery)
|
|
351
305
|
return dbm;
|
|
352
306
|
if (this.cfg.hooks.afterLoad) {
|
|
353
307
|
dbm = (await this.cfg.hooks.afterLoad(dbm));
|
|
@@ -383,7 +337,7 @@ class CommonDao {
|
|
|
383
337
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
384
338
|
const partialQuery = !!q._selectedFieldNames;
|
|
385
339
|
const stream = this.cfg.db.streamQuery(q, opt);
|
|
386
|
-
if (partialQuery
|
|
340
|
+
if (partialQuery)
|
|
387
341
|
return stream;
|
|
388
342
|
return stream
|
|
389
343
|
.on('error', err => stream.emit('error', err))
|
|
@@ -414,7 +368,7 @@ class CommonDao {
|
|
|
414
368
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
415
369
|
const stream = this.cfg.db.streamQuery(q, opt);
|
|
416
370
|
const partialQuery = !!q._selectedFieldNames;
|
|
417
|
-
if (partialQuery
|
|
371
|
+
if (partialQuery)
|
|
418
372
|
return stream;
|
|
419
373
|
return (stream
|
|
420
374
|
// optimization: 1 validation is enough
|
|
@@ -509,7 +463,7 @@ class CommonDao {
|
|
|
509
463
|
const idWasGenerated = !bm.id && this.cfg.generateId;
|
|
510
464
|
this.assignIdCreatedUpdated(bm, opt); // mutates
|
|
511
465
|
(0, js_lib_1._typeCast)(bm);
|
|
512
|
-
let dbm = await this.bmToDBM(bm, opt);
|
|
466
|
+
let dbm = await this.bmToDBM(bm, opt); // validates BM
|
|
513
467
|
if (this.cfg.hooks.beforeSave) {
|
|
514
468
|
dbm = (await this.cfg.hooks.beforeSave(dbm));
|
|
515
469
|
if (dbm === null)
|
|
@@ -636,14 +590,11 @@ class CommonDao {
|
|
|
636
590
|
const table = opt.table || this.cfg.table;
|
|
637
591
|
// assigning id in case it misses the id
|
|
638
592
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
if (opt.ensureUniqueId && idWasGenerated)
|
|
645
|
-
await this.ensureUniqueId(table, row);
|
|
646
|
-
}
|
|
593
|
+
const idWasGenerated = !dbm.id && this.cfg.generateId;
|
|
594
|
+
this.assignIdCreatedUpdated(dbm, opt); // mutates
|
|
595
|
+
let row = this.anyToDBM(dbm, opt);
|
|
596
|
+
if (opt.ensureUniqueId && idWasGenerated)
|
|
597
|
+
await this.ensureUniqueId(table, row);
|
|
647
598
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
648
599
|
opt = { ...opt, saveMethod: 'insert' };
|
|
649
600
|
}
|
|
@@ -705,13 +656,10 @@ class CommonDao {
|
|
|
705
656
|
return [];
|
|
706
657
|
this.requireWriteAccess();
|
|
707
658
|
const table = opt.table || this.cfg.table;
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if (opt.ensureUniqueId)
|
|
713
|
-
throw new js_lib_1.AppError('ensureUniqueId is not supported in saveBatch');
|
|
714
|
-
}
|
|
659
|
+
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)); // mutates
|
|
660
|
+
let rows = this.anyToDBMs(dbms, opt);
|
|
661
|
+
if (opt.ensureUniqueId)
|
|
662
|
+
throw new js_lib_1.AppError('ensureUniqueId is not supported in saveBatch');
|
|
715
663
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
716
664
|
opt = { ...opt, saveMethod: 'insert' };
|
|
717
665
|
}
|
|
@@ -882,9 +830,15 @@ class CommonDao {
|
|
|
882
830
|
dbm = this.cfg.hooks.anonymize(dbm);
|
|
883
831
|
}
|
|
884
832
|
// DBM > BM
|
|
885
|
-
|
|
833
|
+
let bm;
|
|
834
|
+
if (this.cfg.hooks.beforeDBMToBM) {
|
|
835
|
+
bm = await this.cfg.hooks.beforeDBMToBM(dbm);
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
bm = dbm;
|
|
839
|
+
}
|
|
886
840
|
// Validate/convert BM
|
|
887
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema,
|
|
841
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
888
842
|
}
|
|
889
843
|
async dbmsToBM(dbms, opt = {}) {
|
|
890
844
|
return await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.dbmToBM(dbm, opt));
|
|
@@ -892,16 +846,21 @@ class CommonDao {
|
|
|
892
846
|
async bmToDBM(bm, opt) {
|
|
893
847
|
if (bm === undefined)
|
|
894
848
|
return;
|
|
895
|
-
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
896
|
-
// Validate/convert BM
|
|
897
|
-
// bm gets assigned to the new reference
|
|
898
|
-
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
899
849
|
// should not do it on load, but only on save!
|
|
900
850
|
// this.assignIdCreatedUpdated(bm, opt)
|
|
851
|
+
// bm gets assigned to the new reference
|
|
852
|
+
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
901
853
|
// BM > DBM
|
|
902
|
-
|
|
854
|
+
let dbm;
|
|
855
|
+
if (this.cfg.hooks.beforeBMToDBM) {
|
|
856
|
+
dbm = { ...(await this.cfg.hooks.beforeBMToDBM(bm)) };
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
dbm = bm;
|
|
860
|
+
}
|
|
903
861
|
// Validate/convert DBM
|
|
904
|
-
return this.validateAndConvert(dbm, this.cfg.dbmSchema,
|
|
862
|
+
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
863
|
+
return dbm;
|
|
905
864
|
}
|
|
906
865
|
async bmsToDBM(bms, opt = {}) {
|
|
907
866
|
// try/catch?
|
|
@@ -913,41 +872,25 @@ class CommonDao {
|
|
|
913
872
|
// this shouldn't be happening on load! but should on save!
|
|
914
873
|
// this.assignIdCreatedUpdated(dbm, opt)
|
|
915
874
|
dbm = { ...dbm, ...this.cfg.hooks.parseNaturalId(dbm.id) };
|
|
875
|
+
// todo: is this the right place?
|
|
876
|
+
// todo: is anyToDBM even needed?
|
|
916
877
|
if (opt.anonymize) {
|
|
917
878
|
dbm = this.cfg.hooks.anonymize(dbm);
|
|
918
879
|
}
|
|
919
880
|
// Validate/convert DBM
|
|
920
|
-
return this.validateAndConvert(dbm, this.cfg.dbmSchema,
|
|
881
|
+
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
882
|
+
return dbm;
|
|
921
883
|
}
|
|
922
884
|
anyToDBMs(entities, opt = {}) {
|
|
923
885
|
return entities.map(entity => this.anyToDBM(entity, opt));
|
|
924
886
|
}
|
|
925
|
-
bmToTM(bm, opt) {
|
|
926
|
-
if (bm === undefined)
|
|
927
|
-
return;
|
|
928
|
-
// optimization: 1 validation is enough
|
|
929
|
-
// Validate/convert BM
|
|
930
|
-
// bm gets assigned to the new reference
|
|
931
|
-
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
932
|
-
// BM > TM
|
|
933
|
-
const tm = this.cfg.hooks.beforeBMToTM(bm);
|
|
934
|
-
// Validate/convert DBM
|
|
935
|
-
return this.validateAndConvert(tm, this.cfg.tmSchema, db_model_1.DBModelType.TM, opt);
|
|
936
|
-
}
|
|
937
|
-
bmsToTM(bms, opt = {}) {
|
|
938
|
-
// try/catch?
|
|
939
|
-
return bms.map(bm => this.bmToTM(bm, opt));
|
|
940
|
-
}
|
|
941
887
|
/**
|
|
942
888
|
* Returns *converted value*.
|
|
943
889
|
* Validates (unless `skipValidation=true` passed).
|
|
944
890
|
*
|
|
945
891
|
* Does NOT mutate the object.
|
|
946
892
|
*/
|
|
947
|
-
validateAndConvert(obj, schema,
|
|
948
|
-
// `raw` option completely bypasses any processing
|
|
949
|
-
if (opt.raw)
|
|
950
|
-
return obj;
|
|
893
|
+
validateAndConvert(obj, schema, opt = {}) {
|
|
951
894
|
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
952
895
|
// So, from now on we'll preserve them
|
|
953
896
|
// "undefined" values, I believe, are/were not saved to/from DB anyway (due to e.g JSON.stringify removing them)
|
|
@@ -957,23 +900,14 @@ class CommonDao {
|
|
|
957
900
|
// obj = _filterNullishValues(obj as any)
|
|
958
901
|
// We still filter `undefined` values here, because `beforeDBMToBM` can return undefined values
|
|
959
902
|
// and they can be annoying with snapshot tests
|
|
960
|
-
|
|
961
|
-
obj = (0, js_lib_1._filterNullishValues)(obj);
|
|
962
|
-
}
|
|
963
|
-
else {
|
|
964
|
-
obj = (0, js_lib_1._filterUndefinedValues)(obj);
|
|
965
|
-
}
|
|
966
|
-
// Pre-validation hooks
|
|
967
|
-
if (modelType === db_model_1.DBModelType.DBM) {
|
|
968
|
-
obj = this.cfg.hooks.beforeDBMValidate(obj);
|
|
969
|
-
}
|
|
903
|
+
obj = (0, js_lib_1._filterUndefinedValues)(obj);
|
|
970
904
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
971
905
|
if (!schema || opt.skipConversion) {
|
|
972
906
|
return obj;
|
|
973
907
|
}
|
|
974
908
|
// This will Convert and Validate
|
|
975
909
|
const table = opt.table || this.cfg.table;
|
|
976
|
-
const objectName = table
|
|
910
|
+
const objectName = table;
|
|
977
911
|
let error;
|
|
978
912
|
let convertedValue;
|
|
979
913
|
if (schema instanceof js_lib_1.ZodSchema) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseDBEntity, CommonLogger, ErrorMode, Promisable, ZodError, ZodSchema } from '@naturalcycles/js-lib';
|
|
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> {
|
|
6
6
|
/**
|
|
7
7
|
* Allows to override the id generation function.
|
|
8
8
|
* By default it uses `stringId` from nodejs-lib
|
|
@@ -28,19 +28,8 @@ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntit
|
|
|
28
28
|
* - patch, patchAsDBM
|
|
29
29
|
*/
|
|
30
30
|
beforeCreate: (bm: Partial<BM>) => Partial<BM>;
|
|
31
|
-
/**
|
|
32
|
-
* Called when loading things "as DBM" and validation is not skipped.
|
|
33
|
-
* When loading things as BM/TM - other hooks get involved instead:
|
|
34
|
-
* - beforeDBMToBM
|
|
35
|
-
* - beforeBMToTM
|
|
36
|
-
*
|
|
37
|
-
* TODO: maybe rename those to `validateAs(model)`
|
|
38
|
-
* as it only validates "final state", not intermediate
|
|
39
|
-
*/
|
|
40
|
-
beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>;
|
|
41
31
|
beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>;
|
|
42
32
|
beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>;
|
|
43
|
-
beforeBMToTM: (bm: BM) => Partial<TM>;
|
|
44
33
|
/**
|
|
45
34
|
* Allows to access the DBM just after it has been loaded from the DB.
|
|
46
35
|
*
|
|
@@ -104,15 +93,13 @@ export declare enum CommonDaoLogLevel {
|
|
|
104
93
|
*/
|
|
105
94
|
DATA_FULL = 30
|
|
106
95
|
}
|
|
107
|
-
export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM
|
|
96
|
+
export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
108
97
|
db: CommonDB;
|
|
109
98
|
table: string;
|
|
110
99
|
/**
|
|
111
100
|
* Joi, AjvSchema or ZodSchema is supported.
|
|
112
101
|
*/
|
|
113
|
-
dbmSchema?: ObjectSchema<DBM> | AjvSchema<DBM> | ZodSchema<DBM>;
|
|
114
102
|
bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodSchema<BM>;
|
|
115
|
-
tmSchema?: ObjectSchema<TM> | AjvSchema<TM> | ZodSchema<TM>;
|
|
116
103
|
excludeFromIndexes?: (keyof DBM)[];
|
|
117
104
|
/**
|
|
118
105
|
* Defaults to false.
|
|
@@ -141,7 +128,7 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
141
128
|
* @default false
|
|
142
129
|
*/
|
|
143
130
|
logStarted?: boolean;
|
|
144
|
-
hooks?: Partial<CommonDaoHooks<BM, DBM
|
|
131
|
+
hooks?: Partial<CommonDaoHooks<BM, DBM>>;
|
|
145
132
|
/**
|
|
146
133
|
* Defaults to true.
|
|
147
134
|
* Set to false to disable auto-generation of `id`.
|
|
@@ -163,16 +150,6 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
163
150
|
* Set to false to disable `updated` field management.
|
|
164
151
|
*/
|
|
165
152
|
useUpdatedProperty?: boolean;
|
|
166
|
-
/**
|
|
167
|
-
* Default is false.
|
|
168
|
-
* If true - will run `_filterNullishValues` inside `validateAndConvert` function
|
|
169
|
-
* (instead of `_filterUndefinedValues`).
|
|
170
|
-
* This was the old db-lib behavior.
|
|
171
|
-
* This option allows to keep backwards-compatible behavior.
|
|
172
|
-
*
|
|
173
|
-
* @deprecated
|
|
174
|
-
*/
|
|
175
|
-
filterNullishValues?: boolean;
|
|
176
153
|
/**
|
|
177
154
|
* Defaults to false.
|
|
178
155
|
* If true - run patch operations (patch, patchById) in a Transaction.
|
|
@@ -200,15 +177,6 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
200
177
|
* @default false
|
|
201
178
|
*/
|
|
202
179
|
skipConversion?: boolean;
|
|
203
|
-
/**
|
|
204
|
-
* If true - will SKIP ANY transformation/processing, will return DB objects as they are. Will also skip created/updated/id
|
|
205
|
-
* generation.
|
|
206
|
-
*
|
|
207
|
-
* Useful for performance/streaming/pipelines.
|
|
208
|
-
*
|
|
209
|
-
* @default false
|
|
210
|
-
*/
|
|
211
|
-
raw?: boolean;
|
|
212
180
|
/**
|
|
213
181
|
* @default false
|
|
214
182
|
*/
|
package/dist/db.model.d.ts
CHANGED
package/dist/db.model.js
CHANGED
package/dist/query/dbQuery.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AsyncMapper,
|
|
1
|
+
import { AsyncMapper, BaseDBEntity, ObjectWithId } from '@naturalcycles/js-lib';
|
|
2
2
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { CommonDaoOptions, CommonDaoStreamDeleteOptions, CommonDaoStreamForEachOptions, CommonDaoStreamOptions, DBPatch } from '..';
|
|
4
4
|
import { CommonDao } from '../commondao/common.dao';
|
|
@@ -84,19 +84,17 @@ export declare class DBQuery<ROW extends ObjectWithId> {
|
|
|
84
84
|
/**
|
|
85
85
|
* DBQuery that has additional method to support Fluent API style.
|
|
86
86
|
*/
|
|
87
|
-
export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM
|
|
88
|
-
dao: CommonDao<BM, DBM
|
|
87
|
+
export declare class RunnableDBQuery<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> extends DBQuery<DBM> {
|
|
88
|
+
dao: CommonDao<BM, DBM>;
|
|
89
89
|
/**
|
|
90
90
|
* Pass `table` to override table.
|
|
91
91
|
*/
|
|
92
|
-
constructor(dao: CommonDao<BM, DBM
|
|
92
|
+
constructor(dao: CommonDao<BM, DBM>, table?: string);
|
|
93
93
|
runQuery(opt?: CommonDaoOptions): Promise<BM[]>;
|
|
94
94
|
runQuerySingleColumn<T = any>(opt?: CommonDaoOptions): Promise<T[]>;
|
|
95
95
|
runQueryAsDBM(opt?: CommonDaoOptions): Promise<DBM[]>;
|
|
96
|
-
runQueryAsTM(opt?: CommonDaoOptions): Promise<TM[]>;
|
|
97
96
|
runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<BM>>;
|
|
98
97
|
runQueryExtendedAsDBM(opt?: CommonDaoOptions): Promise<RunQueryResult<DBM>>;
|
|
99
|
-
runQueryExtendedAsTM(opt?: CommonDaoOptions): Promise<RunQueryResult<TM>>;
|
|
100
98
|
runQueryCount(opt?: CommonDaoOptions): Promise<number>;
|
|
101
99
|
updateByQuery(patch: DBPatch<DBM>, opt?: CommonDaoOptions): Promise<number>;
|
|
102
100
|
streamQueryForEach(mapper: AsyncMapper<BM, void>, opt?: CommonDaoStreamForEachOptions<BM>): Promise<void>;
|
package/dist/query/dbQuery.js
CHANGED
|
@@ -153,18 +153,12 @@ 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
|
-
}
|
|
159
156
|
async runQueryExtended(opt) {
|
|
160
157
|
return await this.dao.runQueryExtended(this, opt);
|
|
161
158
|
}
|
|
162
159
|
async runQueryExtendedAsDBM(opt) {
|
|
163
160
|
return await this.dao.runQueryExtendedAsDBM(this, opt);
|
|
164
161
|
}
|
|
165
|
-
async runQueryExtendedAsTM(opt) {
|
|
166
|
-
return await this.dao.runQueryExtendedAsTM(this, opt);
|
|
167
|
-
}
|
|
168
162
|
async runQueryCount(opt) {
|
|
169
163
|
return await this.dao.runQueryCount(this, opt);
|
|
170
164
|
}
|
package/dist/testing/daoTest.js
CHANGED
|
@@ -13,9 +13,7 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
13
13
|
const dao = new common_dao_1.CommonDao({
|
|
14
14
|
table: test_model_1.TEST_TABLE,
|
|
15
15
|
db,
|
|
16
|
-
dbmSchema: test_model_1.testItemDBMSchema,
|
|
17
16
|
bmSchema: test_model_1.testItemBMSchema,
|
|
18
|
-
tmSchema: test_model_1.testItemTMSchema,
|
|
19
17
|
logStarted: true,
|
|
20
18
|
logLevel: __1.CommonDaoLogLevel.DATA_FULL,
|
|
21
19
|
});
|
|
@@ -33,7 +31,7 @@ function runCommonDaoTest(db, quirks = {}) {
|
|
|
33
31
|
// CREATE TABLE, DROP
|
|
34
32
|
if (support.createTable) {
|
|
35
33
|
test('createTable, dropIfExists=true', async () => {
|
|
36
|
-
await dao.createTable(test_model_1.
|
|
34
|
+
await dao.createTable(test_model_1.testItemBMJsonSchema, { dropIfExists: true });
|
|
37
35
|
});
|
|
38
36
|
}
|
|
39
37
|
if (support.queries) {
|
package/dist/testing/dbTest.js
CHANGED
|
@@ -20,7 +20,7 @@ function runCommonDBTest(db, quirks = {}) {
|
|
|
20
20
|
// CREATE TABLE, DROP
|
|
21
21
|
if (support.createTable) {
|
|
22
22
|
test('createTable, dropIfExists=true', async () => {
|
|
23
|
-
await db.createTable(test_model_1.TEST_TABLE, test_model_1.
|
|
23
|
+
await db.createTable(test_model_1.TEST_TABLE, test_model_1.testItemBMJsonSchema, { dropIfExists: true });
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
if (support.queries) {
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runCommonDaoTest } from './daoTest';
|
|
2
2
|
import { CommonDBImplementationQuirks, runCommonDBTest } from './dbTest';
|
|
3
3
|
import { runCommonKeyValueDBTest } from './keyValueDBTest';
|
|
4
|
-
import { createTestItemBM, createTestItemDBM, createTestItemsBM, createTestItemsDBM, TestItemBM, testItemBMJsonSchema, testItemBMSchema, TestItemDBM,
|
|
4
|
+
import { createTestItemBM, createTestItemDBM, createTestItemsBM, createTestItemsDBM, TestItemBM, testItemBMJsonSchema, testItemBMSchema, TestItemDBM, TestItemTM, testItemTMSchema, TEST_TABLE } from './test.model';
|
|
5
5
|
export type { TestItemDBM, TestItemBM, TestItemTM, CommonDBImplementationQuirks };
|
|
6
|
-
export { TEST_TABLE, createTestItemDBM, createTestItemBM, createTestItemsDBM, createTestItemsBM,
|
|
6
|
+
export { TEST_TABLE, createTestItemDBM, createTestItemBM, createTestItemsDBM, createTestItemsBM, testItemBMSchema, testItemTMSchema, testItemBMJsonSchema, runCommonDBTest, runCommonDaoTest, runCommonKeyValueDBTest, };
|
package/dist/testing/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runCommonKeyValueDBTest = exports.runCommonDaoTest = exports.runCommonDBTest = exports.
|
|
3
|
+
exports.runCommonKeyValueDBTest = exports.runCommonDaoTest = exports.runCommonDBTest = exports.testItemBMJsonSchema = exports.testItemTMSchema = exports.testItemBMSchema = exports.createTestItemsBM = exports.createTestItemsDBM = exports.createTestItemBM = exports.createTestItemDBM = exports.TEST_TABLE = void 0;
|
|
4
4
|
const daoTest_1 = require("./daoTest");
|
|
5
5
|
Object.defineProperty(exports, "runCommonDaoTest", { enumerable: true, get: function () { return daoTest_1.runCommonDaoTest; } });
|
|
6
6
|
const dbTest_1 = require("./dbTest");
|
|
@@ -14,7 +14,5 @@ Object.defineProperty(exports, "createTestItemsBM", { enumerable: true, get: fun
|
|
|
14
14
|
Object.defineProperty(exports, "createTestItemsDBM", { enumerable: true, get: function () { return test_model_1.createTestItemsDBM; } });
|
|
15
15
|
Object.defineProperty(exports, "testItemBMJsonSchema", { enumerable: true, get: function () { return test_model_1.testItemBMJsonSchema; } });
|
|
16
16
|
Object.defineProperty(exports, "testItemBMSchema", { enumerable: true, get: function () { return test_model_1.testItemBMSchema; } });
|
|
17
|
-
Object.defineProperty(exports, "testItemDBMJsonSchema", { enumerable: true, get: function () { return test_model_1.testItemDBMJsonSchema; } });
|
|
18
|
-
Object.defineProperty(exports, "testItemDBMSchema", { enumerable: true, get: function () { return test_model_1.testItemDBMSchema; } });
|
|
19
17
|
Object.defineProperty(exports, "testItemTMSchema", { enumerable: true, get: function () { return test_model_1.testItemTMSchema; } });
|
|
20
18
|
Object.defineProperty(exports, "TEST_TABLE", { enumerable: true, get: function () { return test_model_1.TEST_TABLE; } });
|