@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
|
@@ -15,10 +15,8 @@ export interface TestItemTM {
|
|
|
15
15
|
even?: boolean;
|
|
16
16
|
}
|
|
17
17
|
export declare const testItemBMSchema: import("joi").ObjectSchema<TestItemBM>;
|
|
18
|
-
export declare const testItemDBMSchema: import("joi").ObjectSchema<TestItemDBM>;
|
|
19
18
|
export declare const testItemTMSchema: import("joi").ObjectSchema<TestItemTM>;
|
|
20
19
|
export declare const testItemBMJsonSchema: JsonSchemaObject<TestItemBM>;
|
|
21
|
-
export declare const testItemDBMJsonSchema: JsonSchemaObject<TestItemDBM>;
|
|
22
20
|
export declare function createTestItemDBM(num?: number): TestItemDBM;
|
|
23
21
|
export declare function createTestItemBM(num?: number): TestItemBM;
|
|
24
22
|
export declare function createTestItemsDBM(count?: number): TestItemDBM[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createTestItemsBM = exports.createTestItemsDBM = exports.createTestItemBM = exports.createTestItemDBM = exports.
|
|
3
|
+
exports.createTestItemsBM = exports.createTestItemsDBM = exports.createTestItemBM = exports.createTestItemDBM = exports.testItemBMJsonSchema = exports.testItemTMSchema = exports.testItemBMSchema = exports.TEST_TABLE = 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 MOCK_TS_2018_06_21 = 1529539200;
|
|
@@ -12,13 +12,6 @@ exports.testItemBMSchema = (0, nodejs_lib_1.objectSchema)({
|
|
|
12
12
|
even: nodejs_lib_1.booleanSchema.optional(),
|
|
13
13
|
b1: nodejs_lib_1.binarySchema.optional(),
|
|
14
14
|
}).concat(nodejs_lib_1.baseDBEntitySchema);
|
|
15
|
-
exports.testItemDBMSchema = (0, nodejs_lib_1.objectSchema)({
|
|
16
|
-
k1: nodejs_lib_1.stringSchema,
|
|
17
|
-
k2: nodejs_lib_1.stringSchema.allow(null).optional(),
|
|
18
|
-
k3: nodejs_lib_1.numberSchema.optional(),
|
|
19
|
-
even: nodejs_lib_1.booleanSchema.optional(),
|
|
20
|
-
b1: nodejs_lib_1.binarySchema.optional(),
|
|
21
|
-
}).concat(nodejs_lib_1.baseDBEntitySchema);
|
|
22
15
|
exports.testItemTMSchema = (0, nodejs_lib_1.objectSchema)({
|
|
23
16
|
k1: nodejs_lib_1.stringSchema,
|
|
24
17
|
even: nodejs_lib_1.booleanSchema.optional(),
|
|
@@ -37,19 +30,6 @@ exports.testItemBMJsonSchema = js_lib_1.jsonSchema
|
|
|
37
30
|
})
|
|
38
31
|
.baseDBEntity()
|
|
39
32
|
.build();
|
|
40
|
-
exports.testItemDBMJsonSchema = js_lib_1.jsonSchema
|
|
41
|
-
.rootObject({
|
|
42
|
-
// todo: figure out how to not copy-paste these 3 fields
|
|
43
|
-
id: js_lib_1.jsonSchema.string(),
|
|
44
|
-
created: js_lib_1.jsonSchema.unixTimestamp(),
|
|
45
|
-
updated: js_lib_1.jsonSchema.unixTimestamp(),
|
|
46
|
-
k1: js_lib_1.jsonSchema.string(),
|
|
47
|
-
k2: js_lib_1.jsonSchema.string().optional(),
|
|
48
|
-
k3: js_lib_1.jsonSchema.number().optional(),
|
|
49
|
-
even: js_lib_1.jsonSchema.boolean().optional(),
|
|
50
|
-
b1: js_lib_1.jsonSchema.buffer().optional(),
|
|
51
|
-
})
|
|
52
|
-
.build();
|
|
53
33
|
function createTestItemDBM(num = 1) {
|
|
54
34
|
return {
|
|
55
35
|
id: `id${num}`,
|
package/package.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AnyObject,
|
|
3
2
|
BaseDBEntity,
|
|
4
3
|
CommonLogger,
|
|
5
4
|
ErrorMode,
|
|
@@ -18,7 +17,7 @@ import {
|
|
|
18
17
|
import { CommonDB } from '../common.db'
|
|
19
18
|
import { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model'
|
|
20
19
|
|
|
21
|
-
export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
20
|
+
export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntity> {
|
|
22
21
|
/**
|
|
23
22
|
* Allows to override the id generation function.
|
|
24
23
|
* By default it uses `stringId` from nodejs-lib
|
|
@@ -48,20 +47,8 @@ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntit
|
|
|
48
47
|
*/
|
|
49
48
|
beforeCreate: (bm: Partial<BM>) => Partial<BM>
|
|
50
49
|
|
|
51
|
-
/**
|
|
52
|
-
* Called when loading things "as DBM" and validation is not skipped.
|
|
53
|
-
* When loading things as BM/TM - other hooks get involved instead:
|
|
54
|
-
* - beforeDBMToBM
|
|
55
|
-
* - beforeBMToTM
|
|
56
|
-
*
|
|
57
|
-
* TODO: maybe rename those to `validateAs(model)`
|
|
58
|
-
* as it only validates "final state", not intermediate
|
|
59
|
-
*/
|
|
60
|
-
beforeDBMValidate: (dbm: Partial<DBM>) => Partial<DBM>
|
|
61
|
-
|
|
62
50
|
beforeDBMToBM: (dbm: DBM) => Partial<BM> | Promise<Partial<BM>>
|
|
63
51
|
beforeBMToDBM: (bm: BM) => Partial<DBM> | Promise<Partial<DBM>>
|
|
64
|
-
beforeBMToTM: (bm: BM) => Partial<TM>
|
|
65
52
|
|
|
66
53
|
/**
|
|
67
54
|
* Allows to access the DBM just after it has been loaded from the DB.
|
|
@@ -131,20 +118,14 @@ export enum CommonDaoLogLevel {
|
|
|
131
118
|
DATA_FULL = 30,
|
|
132
119
|
}
|
|
133
120
|
|
|
134
|
-
export interface CommonDaoCfg<
|
|
135
|
-
BM extends BaseDBEntity,
|
|
136
|
-
DBM extends BaseDBEntity = BM,
|
|
137
|
-
TM extends AnyObject = BM,
|
|
138
|
-
> {
|
|
121
|
+
export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
139
122
|
db: CommonDB
|
|
140
123
|
table: string
|
|
141
124
|
|
|
142
125
|
/**
|
|
143
126
|
* Joi, AjvSchema or ZodSchema is supported.
|
|
144
127
|
*/
|
|
145
|
-
dbmSchema?: ObjectSchema<DBM> | AjvSchema<DBM> | ZodSchema<DBM>
|
|
146
128
|
bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodSchema<BM>
|
|
147
|
-
tmSchema?: ObjectSchema<TM> | AjvSchema<TM> | ZodSchema<TM>
|
|
148
129
|
|
|
149
130
|
excludeFromIndexes?: (keyof DBM)[]
|
|
150
131
|
|
|
@@ -181,7 +162,7 @@ export interface CommonDaoCfg<
|
|
|
181
162
|
logStarted?: boolean
|
|
182
163
|
|
|
183
164
|
// Hooks are designed with inspiration from got/ky interface
|
|
184
|
-
hooks?: Partial<CommonDaoHooks<BM, DBM
|
|
165
|
+
hooks?: Partial<CommonDaoHooks<BM, DBM>>
|
|
185
166
|
|
|
186
167
|
/**
|
|
187
168
|
* Defaults to true.
|
|
@@ -208,17 +189,6 @@ export interface CommonDaoCfg<
|
|
|
208
189
|
*/
|
|
209
190
|
useUpdatedProperty?: boolean
|
|
210
191
|
|
|
211
|
-
/**
|
|
212
|
-
* Default is false.
|
|
213
|
-
* If true - will run `_filterNullishValues` inside `validateAndConvert` function
|
|
214
|
-
* (instead of `_filterUndefinedValues`).
|
|
215
|
-
* This was the old db-lib behavior.
|
|
216
|
-
* This option allows to keep backwards-compatible behavior.
|
|
217
|
-
*
|
|
218
|
-
* @deprecated
|
|
219
|
-
*/
|
|
220
|
-
filterNullishValues?: boolean
|
|
221
|
-
|
|
222
192
|
/**
|
|
223
193
|
* Defaults to false.
|
|
224
194
|
* If true - run patch operations (patch, patchById) in a Transaction.
|
|
@@ -249,16 +219,6 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
249
219
|
*/
|
|
250
220
|
skipConversion?: boolean
|
|
251
221
|
|
|
252
|
-
/**
|
|
253
|
-
* If true - will SKIP ANY transformation/processing, will return DB objects as they are. Will also skip created/updated/id
|
|
254
|
-
* generation.
|
|
255
|
-
*
|
|
256
|
-
* Useful for performance/streaming/pipelines.
|
|
257
|
-
*
|
|
258
|
-
* @default false
|
|
259
|
-
*/
|
|
260
|
-
raw?: boolean
|
|
261
|
-
|
|
262
222
|
/**
|
|
263
223
|
* @default false
|
|
264
224
|
*/
|
|
@@ -2,7 +2,6 @@ import { Transform } from 'node:stream'
|
|
|
2
2
|
import {
|
|
3
3
|
_assert,
|
|
4
4
|
_deepJsonEquals,
|
|
5
|
-
_filterNullishValues,
|
|
6
5
|
_filterUndefinedValues,
|
|
7
6
|
_isTruthy,
|
|
8
7
|
_objectAssignExact,
|
|
@@ -11,7 +10,6 @@ import {
|
|
|
11
10
|
_truncate,
|
|
12
11
|
_typeCast,
|
|
13
12
|
_uniqBy,
|
|
14
|
-
AnyObject,
|
|
15
13
|
AppError,
|
|
16
14
|
AsyncMapper,
|
|
17
15
|
BaseDBEntity,
|
|
@@ -44,13 +42,7 @@ import {
|
|
|
44
42
|
writableVoid,
|
|
45
43
|
} from '@naturalcycles/nodejs-lib'
|
|
46
44
|
import { DBLibError } from '../cnst'
|
|
47
|
-
import {
|
|
48
|
-
CommonDBTransactionOptions,
|
|
49
|
-
DBModelType,
|
|
50
|
-
DBPatch,
|
|
51
|
-
DBTransaction,
|
|
52
|
-
RunQueryResult,
|
|
53
|
-
} from '../db.model'
|
|
45
|
+
import { CommonDBTransactionOptions, DBPatch, DBTransaction, RunQueryResult } from '../db.model'
|
|
54
46
|
import { DBQuery, RunnableDBQuery } from '../query/dbQuery'
|
|
55
47
|
import {
|
|
56
48
|
CommonDaoCfg,
|
|
@@ -76,12 +68,8 @@ const isCI = !!process.env['CI']
|
|
|
76
68
|
* BM = Backend model (optimized for API access)
|
|
77
69
|
* TM = Transport model (optimized to be sent over the wire)
|
|
78
70
|
*/
|
|
79
|
-
export class CommonDao<
|
|
80
|
-
BM
|
|
81
|
-
DBM extends BaseDBEntity = BM,
|
|
82
|
-
TM extends AnyObject = BM,
|
|
83
|
-
> {
|
|
84
|
-
constructor(public cfg: CommonDaoCfg<BM, DBM, TM>) {
|
|
71
|
+
export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
72
|
+
constructor(public cfg: CommonDaoCfg<BM, DBM>) {
|
|
85
73
|
this.cfg = {
|
|
86
74
|
// Default is to NOT log in AppEngine and in CI,
|
|
87
75
|
// otherwise to log Operations
|
|
@@ -96,14 +84,10 @@ export class CommonDao<
|
|
|
96
84
|
hooks: {
|
|
97
85
|
parseNaturalId: () => ({}),
|
|
98
86
|
beforeCreate: bm => bm as BM,
|
|
99
|
-
beforeDBMValidate: dbm => dbm,
|
|
100
|
-
beforeDBMToBM: dbm => dbm as any,
|
|
101
|
-
beforeBMToDBM: bm => bm as any,
|
|
102
|
-
beforeBMToTM: bm => bm as any,
|
|
103
87
|
anonymize: dbm => dbm,
|
|
104
88
|
onValidationError: err => err,
|
|
105
89
|
...cfg.hooks,
|
|
106
|
-
} satisfies Partial<CommonDaoHooks<BM, DBM
|
|
90
|
+
} satisfies Partial<CommonDaoHooks<BM, DBM>>,
|
|
107
91
|
}
|
|
108
92
|
|
|
109
93
|
if (this.cfg.generateId) {
|
|
@@ -118,7 +102,7 @@ export class CommonDao<
|
|
|
118
102
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
119
103
|
// First assignIdCreatedUpdated, then validate!
|
|
120
104
|
this.assignIdCreatedUpdated(bm, opt)
|
|
121
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema,
|
|
105
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
122
106
|
}
|
|
123
107
|
|
|
124
108
|
// GET
|
|
@@ -131,11 +115,11 @@ export class CommonDao<
|
|
|
131
115
|
const started = this.logStarted(op, table)
|
|
132
116
|
|
|
133
117
|
let dbm = (await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id]))[0]
|
|
134
|
-
if (dbm &&
|
|
118
|
+
if (dbm && this.cfg.hooks!.afterLoad) {
|
|
135
119
|
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
136
120
|
}
|
|
137
121
|
|
|
138
|
-
const bm =
|
|
122
|
+
const bm = await this.dbmToBM(dbm, opt)
|
|
139
123
|
this.logResult(started, op, bm, table)
|
|
140
124
|
return bm || null
|
|
141
125
|
}
|
|
@@ -167,52 +151,28 @@ export class CommonDao<
|
|
|
167
151
|
const table = opt.table || this.cfg.table
|
|
168
152
|
const started = this.logStarted(op, table)
|
|
169
153
|
let [dbm] = await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id])
|
|
170
|
-
if (dbm &&
|
|
154
|
+
if (dbm && this.cfg.hooks!.afterLoad) {
|
|
171
155
|
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
172
156
|
}
|
|
173
157
|
|
|
174
|
-
|
|
175
|
-
dbm = this.anyToDBM(dbm!, opt)
|
|
176
|
-
}
|
|
158
|
+
dbm = this.anyToDBM(dbm!, opt)
|
|
177
159
|
this.logResult(started, op, dbm, table)
|
|
178
160
|
return dbm || null
|
|
179
161
|
}
|
|
180
162
|
|
|
181
|
-
async getByIdAsTM(id: undefined | null, opt?: CommonDaoOptions): Promise<null>
|
|
182
|
-
async getByIdAsTM(id?: string | null, opt?: CommonDaoOptions): Promise<TM | null>
|
|
183
|
-
async getByIdAsTM(id?: string | null, opt: CommonDaoOptions = {}): Promise<TM | null> {
|
|
184
|
-
if (!id) return null
|
|
185
|
-
const op = `getByIdAsTM(${id})`
|
|
186
|
-
const table = opt.table || this.cfg.table
|
|
187
|
-
const started = this.logStarted(op, table)
|
|
188
|
-
let [dbm] = await (opt.tx || this.cfg.db).getByIds<DBM>(table, [id])
|
|
189
|
-
if (dbm && !opt.raw && this.cfg.hooks!.afterLoad) {
|
|
190
|
-
dbm = (await this.cfg.hooks!.afterLoad(dbm)) || undefined
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (opt.raw) {
|
|
194
|
-
this.logResult(started, op, dbm, table)
|
|
195
|
-
return (dbm as any) || null
|
|
196
|
-
}
|
|
197
|
-
const bm = await this.dbmToBM(dbm, opt)
|
|
198
|
-
const tm = this.bmToTM(bm, opt)
|
|
199
|
-
this.logResult(started, op, tm, table)
|
|
200
|
-
return tm || null
|
|
201
|
-
}
|
|
202
|
-
|
|
203
163
|
async getByIds(ids: string[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
204
164
|
if (!ids.length) return []
|
|
205
165
|
const op = `getByIds ${ids.length} id(s) (${_truncate(ids.slice(0, 10).join(', '), 50)})`
|
|
206
166
|
const table = opt.table || this.cfg.table
|
|
207
167
|
const started = this.logStarted(op, table)
|
|
208
168
|
let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
|
|
209
|
-
if (
|
|
169
|
+
if (this.cfg.hooks!.afterLoad && dbms.length) {
|
|
210
170
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
211
171
|
_isTruthy,
|
|
212
172
|
)
|
|
213
173
|
}
|
|
214
174
|
|
|
215
|
-
const bms =
|
|
175
|
+
const bms = await this.dbmsToBM(dbms, opt)
|
|
216
176
|
this.logResult(started, op, bms, table)
|
|
217
177
|
return bms
|
|
218
178
|
}
|
|
@@ -223,7 +183,7 @@ export class CommonDao<
|
|
|
223
183
|
const table = opt.table || this.cfg.table
|
|
224
184
|
const started = this.logStarted(op, table)
|
|
225
185
|
let dbms = await (opt.tx || this.cfg.db).getByIds<DBM>(table, ids)
|
|
226
|
-
if (
|
|
186
|
+
if (this.cfg.hooks!.afterLoad && dbms.length) {
|
|
227
187
|
dbms = (await pMap(dbms, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
228
188
|
_isTruthy,
|
|
229
189
|
)
|
|
@@ -307,8 +267,8 @@ export class CommonDao<
|
|
|
307
267
|
/**
|
|
308
268
|
* Pass `table` to override table
|
|
309
269
|
*/
|
|
310
|
-
query(table?: string): RunnableDBQuery<BM, DBM
|
|
311
|
-
return new RunnableDBQuery<BM, DBM
|
|
270
|
+
query(table?: string): RunnableDBQuery<BM, DBM> {
|
|
271
|
+
return new RunnableDBQuery<BM, DBM>(this, table)
|
|
312
272
|
}
|
|
313
273
|
|
|
314
274
|
async runQuery(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<BM[]> {
|
|
@@ -346,13 +306,13 @@ export class CommonDao<
|
|
|
346
306
|
const started = this.logStarted(op, q.table)
|
|
347
307
|
let { rows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
|
|
348
308
|
const partialQuery = !!q._selectedFieldNames
|
|
349
|
-
if (
|
|
309
|
+
if (this.cfg.hooks!.afterLoad && rows.length) {
|
|
350
310
|
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
351
311
|
_isTruthy,
|
|
352
312
|
)
|
|
353
313
|
}
|
|
354
314
|
|
|
355
|
-
const bms = partialQuery
|
|
315
|
+
const bms = partialQuery ? (rows as any[]) : await this.dbmsToBM(rows, opt)
|
|
356
316
|
this.logResult(started, op, bms, q.table)
|
|
357
317
|
return {
|
|
358
318
|
rows: bms,
|
|
@@ -373,47 +333,18 @@ export class CommonDao<
|
|
|
373
333
|
const op = `runQueryAsDBM(${q.pretty()})`
|
|
374
334
|
const started = this.logStarted(op, q.table)
|
|
375
335
|
let { rows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
|
|
376
|
-
if (
|
|
336
|
+
if (this.cfg.hooks!.afterLoad && rows.length) {
|
|
377
337
|
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
378
338
|
_isTruthy,
|
|
379
339
|
)
|
|
380
340
|
}
|
|
381
341
|
|
|
382
342
|
const partialQuery = !!q._selectedFieldNames
|
|
383
|
-
const dbms = partialQuery
|
|
343
|
+
const dbms = partialQuery ? rows : this.anyToDBMs(rows, opt)
|
|
384
344
|
this.logResult(started, op, dbms, q.table)
|
|
385
345
|
return { rows: dbms, ...queryResult }
|
|
386
346
|
}
|
|
387
347
|
|
|
388
|
-
async runQueryAsTM(q: DBQuery<DBM>, opt?: CommonDaoOptions): Promise<TM[]> {
|
|
389
|
-
const { rows } = await this.runQueryExtendedAsTM(q, opt)
|
|
390
|
-
return rows
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async runQueryExtendedAsTM(
|
|
394
|
-
q: DBQuery<DBM>,
|
|
395
|
-
opt: CommonDaoOptions = {},
|
|
396
|
-
): Promise<RunQueryResult<TM>> {
|
|
397
|
-
q.table = opt.table || q.table
|
|
398
|
-
const op = `runQueryAsTM(${q.pretty()})`
|
|
399
|
-
const started = this.logStarted(op, q.table)
|
|
400
|
-
let { rows, ...queryResult } = await this.cfg.db.runQuery<DBM>(q, opt)
|
|
401
|
-
if (!opt.raw && this.cfg.hooks!.afterLoad && rows.length) {
|
|
402
|
-
rows = (await pMap(rows, async dbm => await this.cfg.hooks!.afterLoad!(dbm))).filter(
|
|
403
|
-
_isTruthy,
|
|
404
|
-
)
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
const partialQuery = !!q._selectedFieldNames
|
|
408
|
-
const tms =
|
|
409
|
-
partialQuery || opt.raw ? (rows as any[]) : this.bmsToTM(await this.dbmsToBM(rows, opt), opt)
|
|
410
|
-
this.logResult(started, op, tms, q.table)
|
|
411
|
-
return {
|
|
412
|
-
rows: tms,
|
|
413
|
-
...queryResult,
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
348
|
async runQueryCount(q: DBQuery<DBM>, opt: CommonDaoOptions = {}): Promise<number> {
|
|
418
349
|
q.table = opt.table || q.table
|
|
419
350
|
const op = `runQueryCount(${q.pretty()})`
|
|
@@ -445,7 +376,7 @@ export class CommonDao<
|
|
|
445
376
|
transformMap<DBM, BM>(
|
|
446
377
|
async dbm => {
|
|
447
378
|
count++
|
|
448
|
-
if (partialQuery
|
|
379
|
+
if (partialQuery) return dbm as any
|
|
449
380
|
|
|
450
381
|
if (this.cfg.hooks!.afterLoad) {
|
|
451
382
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -495,7 +426,7 @@ export class CommonDao<
|
|
|
495
426
|
transformMap<any, DBM>(
|
|
496
427
|
async dbm => {
|
|
497
428
|
count++
|
|
498
|
-
if (partialQuery
|
|
429
|
+
if (partialQuery) return dbm
|
|
499
430
|
|
|
500
431
|
if (this.cfg.hooks!.afterLoad) {
|
|
501
432
|
dbm = (await this.cfg.hooks!.afterLoad(dbm))!
|
|
@@ -537,7 +468,7 @@ export class CommonDao<
|
|
|
537
468
|
const partialQuery = !!q._selectedFieldNames
|
|
538
469
|
|
|
539
470
|
const stream = this.cfg.db.streamQuery<DBM>(q, opt)
|
|
540
|
-
if (partialQuery
|
|
471
|
+
if (partialQuery) return stream
|
|
541
472
|
|
|
542
473
|
return stream
|
|
543
474
|
.on('error', err => stream.emit('error', err))
|
|
@@ -575,7 +506,7 @@ export class CommonDao<
|
|
|
575
506
|
|
|
576
507
|
const stream = this.cfg.db.streamQuery<DBM>(q, opt)
|
|
577
508
|
const partialQuery = !!q._selectedFieldNames
|
|
578
|
-
if (partialQuery
|
|
509
|
+
if (partialQuery) return stream
|
|
579
510
|
|
|
580
511
|
return (
|
|
581
512
|
stream
|
|
@@ -698,7 +629,7 @@ export class CommonDao<
|
|
|
698
629
|
const idWasGenerated = !bm.id && this.cfg.generateId
|
|
699
630
|
this.assignIdCreatedUpdated(bm, opt) // mutates
|
|
700
631
|
_typeCast<BM>(bm)
|
|
701
|
-
let dbm = await this.bmToDBM(bm, opt)
|
|
632
|
+
let dbm = await this.bmToDBM(bm, opt) // validates BM
|
|
702
633
|
|
|
703
634
|
if (this.cfg.hooks!.beforeSave) {
|
|
704
635
|
dbm = (await this.cfg.hooks!.beforeSave(dbm))!
|
|
@@ -857,13 +788,11 @@ export class CommonDao<
|
|
|
857
788
|
|
|
858
789
|
// assigning id in case it misses the id
|
|
859
790
|
// will override/set `updated` field, unless opts.preserveUpdated is set
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, row)
|
|
866
|
-
}
|
|
791
|
+
const idWasGenerated = !dbm.id && this.cfg.generateId
|
|
792
|
+
this.assignIdCreatedUpdated(dbm, opt) // mutates
|
|
793
|
+
let row = this.anyToDBM(dbm, opt)
|
|
794
|
+
if (opt.ensureUniqueId && idWasGenerated) await this.ensureUniqueId(table, row)
|
|
795
|
+
|
|
867
796
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
868
797
|
opt = { ...opt, saveMethod: 'insert' }
|
|
869
798
|
}
|
|
@@ -942,12 +871,10 @@ export class CommonDao<
|
|
|
942
871
|
if (!dbms.length) return []
|
|
943
872
|
this.requireWriteAccess()
|
|
944
873
|
const table = opt.table || this.cfg.table
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
950
|
-
}
|
|
874
|
+
dbms.forEach(dbm => this.assignIdCreatedUpdated(dbm, opt)) // mutates
|
|
875
|
+
let rows = this.anyToDBMs(dbms as DBM[], opt)
|
|
876
|
+
if (opt.ensureUniqueId) throw new AppError('ensureUniqueId is not supported in saveBatch')
|
|
877
|
+
|
|
951
878
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
952
879
|
opt = { ...opt, saveMethod: 'insert' }
|
|
953
880
|
}
|
|
@@ -1176,11 +1103,16 @@ export class CommonDao<
|
|
|
1176
1103
|
}
|
|
1177
1104
|
|
|
1178
1105
|
// DBM > BM
|
|
1179
|
-
|
|
1106
|
+
let bm: Partial<BM>
|
|
1107
|
+
if (this.cfg.hooks!.beforeDBMToBM) {
|
|
1108
|
+
bm = await this.cfg.hooks!.beforeDBMToBM(dbm)
|
|
1109
|
+
} else {
|
|
1110
|
+
bm = dbm as any
|
|
1111
|
+
}
|
|
1180
1112
|
|
|
1181
1113
|
// Validate/convert BM
|
|
1182
1114
|
|
|
1183
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema,
|
|
1115
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1184
1116
|
}
|
|
1185
1117
|
|
|
1186
1118
|
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
@@ -1196,20 +1128,23 @@ export class CommonDao<
|
|
|
1196
1128
|
async bmToDBM(bm?: BM, opt?: CommonDaoOptions): Promise<DBM | undefined> {
|
|
1197
1129
|
if (bm === undefined) return
|
|
1198
1130
|
|
|
1199
|
-
// optimization: no need to run the BM validation, since DBM will be validated anyway
|
|
1200
|
-
// Validate/convert BM
|
|
1201
|
-
// bm gets assigned to the new reference
|
|
1202
|
-
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1203
|
-
|
|
1204
1131
|
// should not do it on load, but only on save!
|
|
1205
1132
|
// this.assignIdCreatedUpdated(bm, opt)
|
|
1206
1133
|
|
|
1134
|
+
// bm gets assigned to the new reference
|
|
1135
|
+
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1136
|
+
|
|
1207
1137
|
// BM > DBM
|
|
1208
|
-
|
|
1138
|
+
let dbm: DBM
|
|
1139
|
+
if (this.cfg.hooks!.beforeBMToDBM) {
|
|
1140
|
+
dbm = { ...((await this.cfg.hooks!.beforeBMToDBM(bm!)) as DBM) }
|
|
1141
|
+
} else {
|
|
1142
|
+
dbm = bm as any
|
|
1143
|
+
}
|
|
1209
1144
|
|
|
1210
1145
|
// Validate/convert DBM
|
|
1211
|
-
|
|
1212
|
-
return
|
|
1146
|
+
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1147
|
+
return dbm
|
|
1213
1148
|
}
|
|
1214
1149
|
|
|
1215
1150
|
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
@@ -1227,40 +1162,21 @@ export class CommonDao<
|
|
|
1227
1162
|
|
|
1228
1163
|
dbm = { ...dbm, ...this.cfg.hooks!.parseNaturalId!(dbm.id) }
|
|
1229
1164
|
|
|
1165
|
+
// todo: is this the right place?
|
|
1166
|
+
// todo: is anyToDBM even needed?
|
|
1230
1167
|
if (opt.anonymize) {
|
|
1231
1168
|
dbm = this.cfg.hooks!.anonymize!(dbm)
|
|
1232
1169
|
}
|
|
1233
1170
|
|
|
1234
1171
|
// Validate/convert DBM
|
|
1235
|
-
return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1172
|
+
// return this.validateAndConvert(dbm, this.cfg.dbmSchema, DBModelType.DBM, opt)
|
|
1173
|
+
return dbm
|
|
1236
1174
|
}
|
|
1237
1175
|
|
|
1238
1176
|
anyToDBMs(entities: DBM[], opt: CommonDaoOptions = {}): DBM[] {
|
|
1239
1177
|
return entities.map(entity => this.anyToDBM(entity, opt))
|
|
1240
1178
|
}
|
|
1241
1179
|
|
|
1242
|
-
bmToTM(bm: undefined, opt?: CommonDaoOptions): TM | undefined
|
|
1243
|
-
bmToTM(bm?: BM, opt?: CommonDaoOptions): TM
|
|
1244
|
-
bmToTM(bm?: BM, opt?: CommonDaoOptions): TM | undefined {
|
|
1245
|
-
if (bm === undefined) return
|
|
1246
|
-
|
|
1247
|
-
// optimization: 1 validation is enough
|
|
1248
|
-
// Validate/convert BM
|
|
1249
|
-
// bm gets assigned to the new reference
|
|
1250
|
-
// bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)
|
|
1251
|
-
|
|
1252
|
-
// BM > TM
|
|
1253
|
-
const tm = this.cfg.hooks!.beforeBMToTM!(bm)
|
|
1254
|
-
|
|
1255
|
-
// Validate/convert DBM
|
|
1256
|
-
return this.validateAndConvert(tm, this.cfg.tmSchema, DBModelType.TM, opt)
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
bmsToTM(bms: BM[], opt: CommonDaoOptions = {}): TM[] {
|
|
1260
|
-
// try/catch?
|
|
1261
|
-
return bms.map(bm => this.bmToTM(bm, opt))
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
1180
|
/**
|
|
1265
1181
|
* Returns *converted value*.
|
|
1266
1182
|
* Validates (unless `skipValidation=true` passed).
|
|
@@ -1270,12 +1186,8 @@ export class CommonDao<
|
|
|
1270
1186
|
validateAndConvert<T>(
|
|
1271
1187
|
obj: Partial<T>,
|
|
1272
1188
|
schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined,
|
|
1273
|
-
modelType: DBModelType,
|
|
1274
1189
|
opt: CommonDaoOptions = {},
|
|
1275
1190
|
): any {
|
|
1276
|
-
// `raw` option completely bypasses any processing
|
|
1277
|
-
if (opt.raw) return obj as any
|
|
1278
|
-
|
|
1279
1191
|
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
1280
1192
|
// So, from now on we'll preserve them
|
|
1281
1193
|
// "undefined" values, I believe, are/were not saved to/from DB anyway (due to e.g JSON.stringify removing them)
|
|
@@ -1285,16 +1197,7 @@ export class CommonDao<
|
|
|
1285
1197
|
// obj = _filterNullishValues(obj as any)
|
|
1286
1198
|
// We still filter `undefined` values here, because `beforeDBMToBM` can return undefined values
|
|
1287
1199
|
// and they can be annoying with snapshot tests
|
|
1288
|
-
|
|
1289
|
-
obj = _filterNullishValues(obj)
|
|
1290
|
-
} else {
|
|
1291
|
-
obj = _filterUndefinedValues(obj)
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
// Pre-validation hooks
|
|
1295
|
-
if (modelType === DBModelType.DBM) {
|
|
1296
|
-
obj = this.cfg.hooks!.beforeDBMValidate!(obj as any) as T
|
|
1297
|
-
}
|
|
1200
|
+
obj = _filterUndefinedValues(obj)
|
|
1298
1201
|
|
|
1299
1202
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
1300
1203
|
if (!schema || opt.skipConversion) {
|
|
@@ -1303,7 +1206,7 @@ export class CommonDao<
|
|
|
1303
1206
|
|
|
1304
1207
|
// This will Convert and Validate
|
|
1305
1208
|
const table = opt.table || this.cfg.table
|
|
1306
|
-
const objectName = table
|
|
1209
|
+
const objectName = table
|
|
1307
1210
|
|
|
1308
1211
|
let error: JoiValidationError | AjvValidationError | ZodValidationError<T> | undefined
|
|
1309
1212
|
let convertedValue: any
|
|
@@ -1460,7 +1363,7 @@ export class CommonDaoTransaction {
|
|
|
1460
1363
|
}
|
|
1461
1364
|
|
|
1462
1365
|
async getById<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1463
|
-
dao: CommonDao<BM, DBM
|
|
1366
|
+
dao: CommonDao<BM, DBM>,
|
|
1464
1367
|
id?: string | null,
|
|
1465
1368
|
opt?: CommonDaoOptions,
|
|
1466
1369
|
): Promise<BM | null> {
|
|
@@ -1468,7 +1371,7 @@ export class CommonDaoTransaction {
|
|
|
1468
1371
|
}
|
|
1469
1372
|
|
|
1470
1373
|
async getByIds<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1471
|
-
dao: CommonDao<BM, DBM
|
|
1374
|
+
dao: CommonDao<BM, DBM>,
|
|
1472
1375
|
ids: string[],
|
|
1473
1376
|
opt?: CommonDaoOptions,
|
|
1474
1377
|
): Promise<BM[]> {
|
|
@@ -1490,7 +1393,7 @@ export class CommonDaoTransaction {
|
|
|
1490
1393
|
// }
|
|
1491
1394
|
|
|
1492
1395
|
async save<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1493
|
-
dao: CommonDao<BM, DBM
|
|
1396
|
+
dao: CommonDao<BM, DBM>,
|
|
1494
1397
|
bm: Unsaved<BM>,
|
|
1495
1398
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1496
1399
|
): Promise<BM> {
|
|
@@ -1498,7 +1401,7 @@ export class CommonDaoTransaction {
|
|
|
1498
1401
|
}
|
|
1499
1402
|
|
|
1500
1403
|
async saveBatch<BM extends BaseDBEntity, DBM extends BaseDBEntity>(
|
|
1501
|
-
dao: CommonDao<BM, DBM
|
|
1404
|
+
dao: CommonDao<BM, DBM>,
|
|
1502
1405
|
bms: Unsaved<BM>[],
|
|
1503
1406
|
opt?: CommonDaoSaveBatchOptions<DBM>,
|
|
1504
1407
|
): Promise<BM[]> {
|
package/src/db.model.ts
CHANGED
package/src/query/dbQuery.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AsyncMapper,
|
|
3
3
|
_truncate,
|
|
4
|
-
AnyObject,
|
|
5
4
|
_objectAssign,
|
|
6
5
|
BaseDBEntity,
|
|
7
6
|
ObjectWithId,
|
|
@@ -238,13 +237,12 @@ export class DBQuery<ROW extends ObjectWithId> {
|
|
|
238
237
|
export class RunnableDBQuery<
|
|
239
238
|
BM extends BaseDBEntity,
|
|
240
239
|
DBM extends BaseDBEntity = BM,
|
|
241
|
-
TM extends AnyObject = BM,
|
|
242
240
|
> extends DBQuery<DBM> {
|
|
243
241
|
/**
|
|
244
242
|
* Pass `table` to override table.
|
|
245
243
|
*/
|
|
246
244
|
constructor(
|
|
247
|
-
public dao: CommonDao<BM, DBM
|
|
245
|
+
public dao: CommonDao<BM, DBM>,
|
|
248
246
|
table?: string,
|
|
249
247
|
) {
|
|
250
248
|
super(table || dao.cfg.table)
|
|
@@ -262,10 +260,6 @@ export class RunnableDBQuery<
|
|
|
262
260
|
return await this.dao.runQueryAsDBM(this, opt)
|
|
263
261
|
}
|
|
264
262
|
|
|
265
|
-
async runQueryAsTM(opt?: CommonDaoOptions): Promise<TM[]> {
|
|
266
|
-
return await this.dao.runQueryAsTM(this, opt)
|
|
267
|
-
}
|
|
268
|
-
|
|
269
263
|
async runQueryExtended(opt?: CommonDaoOptions): Promise<RunQueryResult<BM>> {
|
|
270
264
|
return await this.dao.runQueryExtended(this, opt)
|
|
271
265
|
}
|
|
@@ -274,10 +268,6 @@ export class RunnableDBQuery<
|
|
|
274
268
|
return await this.dao.runQueryExtendedAsDBM(this, opt)
|
|
275
269
|
}
|
|
276
270
|
|
|
277
|
-
async runQueryExtendedAsTM(opt?: CommonDaoOptions): Promise<RunQueryResult<TM>> {
|
|
278
|
-
return await this.dao.runQueryExtendedAsTM(this, opt)
|
|
279
|
-
}
|
|
280
|
-
|
|
281
271
|
async runQueryCount(opt?: CommonDaoOptions): Promise<number> {
|
|
282
272
|
return await this.dao.runQueryCount(this, opt)
|
|
283
273
|
}
|