@naturalcycles/db-lib 9.8.0 → 9.9.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.
|
@@ -149,7 +149,8 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
149
149
|
* Does NOT mutate the object.
|
|
150
150
|
* Validates (unless `skipValidation=true` passed).
|
|
151
151
|
*/
|
|
152
|
-
validateAndConvert<T>(obj: Partial<T>, schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined,
|
|
152
|
+
validateAndConvert<T>(obj: Partial<T>, schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined, op?: 'load' | 'save', // this is to skip validation if validateOnLoad/Save is false
|
|
153
|
+
opt?: CommonDaoOptions): any;
|
|
153
154
|
getTableSchema(): Promise<JsonSchemaRootObject<DBM>>;
|
|
154
155
|
createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void>;
|
|
155
156
|
/**
|
|
@@ -27,6 +27,8 @@ class CommonDao {
|
|
|
27
27
|
assignGeneratedIds: false,
|
|
28
28
|
useCreatedProperty: true,
|
|
29
29
|
useUpdatedProperty: true,
|
|
30
|
+
validateOnLoad: true,
|
|
31
|
+
validateOnSave: true,
|
|
30
32
|
logger: console,
|
|
31
33
|
...cfg,
|
|
32
34
|
hooks: {
|
|
@@ -49,7 +51,7 @@ class CommonDao {
|
|
|
49
51
|
const bm = this.cfg.hooks.beforeCreate(part);
|
|
50
52
|
// First assignIdCreatedUpdated, then validate!
|
|
51
53
|
this.assignIdCreatedUpdated(bm, opt);
|
|
52
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
54
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, undefined, opt);
|
|
53
55
|
}
|
|
54
56
|
async getById(id, opt = {}) {
|
|
55
57
|
if (!id)
|
|
@@ -245,7 +247,6 @@ class CommonDao {
|
|
|
245
247
|
async streamQueryForEach(q, mapper, opt = {}) {
|
|
246
248
|
q.table = opt.table || q.table;
|
|
247
249
|
opt.skipValidation = opt.skipValidation !== false; // default true
|
|
248
|
-
opt.skipConversion = opt.skipConversion !== false; // default true
|
|
249
250
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
250
251
|
const partialQuery = !!q._selectedFieldNames;
|
|
251
252
|
const op = `streamQueryForEach(${q.pretty()})`;
|
|
@@ -284,7 +285,6 @@ class CommonDao {
|
|
|
284
285
|
async streamQueryAsDBMForEach(q, mapper, opt = {}) {
|
|
285
286
|
q.table = opt.table || q.table;
|
|
286
287
|
opt.skipValidation = opt.skipValidation !== false; // default true
|
|
287
|
-
opt.skipConversion = opt.skipConversion !== false; // default true
|
|
288
288
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
289
289
|
const partialQuery = !!q._selectedFieldNames;
|
|
290
290
|
const op = `streamQueryAsDBMForEach(${q.pretty()})`;
|
|
@@ -326,7 +326,6 @@ class CommonDao {
|
|
|
326
326
|
streamQueryAsDBM(q, opt = {}) {
|
|
327
327
|
q.table = opt.table || q.table;
|
|
328
328
|
opt.skipValidation = opt.skipValidation !== false; // default true
|
|
329
|
-
opt.skipConversion = opt.skipConversion !== false; // default true
|
|
330
329
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
331
330
|
const partialQuery = !!q._selectedFieldNames;
|
|
332
331
|
const stream = this.cfg.db.streamQuery(q, opt);
|
|
@@ -357,7 +356,6 @@ class CommonDao {
|
|
|
357
356
|
streamQuery(q, opt = {}) {
|
|
358
357
|
q.table = opt.table || q.table;
|
|
359
358
|
opt.skipValidation = opt.skipValidation !== false; // default true
|
|
360
|
-
opt.skipConversion = opt.skipConversion !== false; // default true
|
|
361
359
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
362
360
|
const stream = this.cfg.db.streamQuery(q, opt);
|
|
363
361
|
const partialQuery = !!q._selectedFieldNames;
|
|
@@ -537,7 +535,7 @@ class CommonDao {
|
|
|
537
535
|
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
538
536
|
// which should be removed post-validation, but it breaks the "equality check"
|
|
539
537
|
// Post-validation the equality check should work as intended
|
|
540
|
-
const convertedBM = this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
538
|
+
const convertedBM = this.validateAndConvert(bm, this.cfg.bmSchema, 'save', opt);
|
|
541
539
|
if ((0, js_lib_1._deepJsonEquals)(convertedBM, opt.skipIfEquals)) {
|
|
542
540
|
// Skipping the save operation
|
|
543
541
|
return bm;
|
|
@@ -682,7 +680,6 @@ class CommonDao {
|
|
|
682
680
|
this.requireWriteAccess();
|
|
683
681
|
const table = opt.table || this.cfg.table;
|
|
684
682
|
opt.skipValidation ??= true;
|
|
685
|
-
opt.skipConversion ??= true;
|
|
686
683
|
opt.errorMode ||= js_lib_1.ErrorMode.SUPPRESS;
|
|
687
684
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
688
685
|
opt = { ...opt, saveMethod: 'insert' };
|
|
@@ -817,7 +814,7 @@ class CommonDao {
|
|
|
817
814
|
// DBM > BM
|
|
818
815
|
const bm = ((await this.cfg.hooks.beforeDBMToBM?.(dbm)) || dbm);
|
|
819
816
|
// Validate/convert BM
|
|
820
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
817
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, 'load', opt);
|
|
821
818
|
}
|
|
822
819
|
async dbmsToBM(dbms, opt = {}) {
|
|
823
820
|
return await (0, js_lib_1.pMap)(dbms, async (dbm) => await this.dbmToBM(dbm, opt));
|
|
@@ -826,7 +823,7 @@ class CommonDao {
|
|
|
826
823
|
if (bm === undefined)
|
|
827
824
|
return;
|
|
828
825
|
// bm gets assigned to the new reference
|
|
829
|
-
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt);
|
|
826
|
+
bm = this.validateAndConvert(bm, this.cfg.bmSchema, 'save', opt);
|
|
830
827
|
// BM > DBM
|
|
831
828
|
return ((await this.cfg.hooks.beforeBMToDBM?.(bm)) || bm);
|
|
832
829
|
}
|
|
@@ -857,7 +854,8 @@ class CommonDao {
|
|
|
857
854
|
* Does NOT mutate the object.
|
|
858
855
|
* Validates (unless `skipValidation=true` passed).
|
|
859
856
|
*/
|
|
860
|
-
validateAndConvert(obj, schema,
|
|
857
|
+
validateAndConvert(obj, schema, op, // this is to skip validation if validateOnLoad/Save is false
|
|
858
|
+
opt = {}) {
|
|
861
859
|
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
862
860
|
// So, from now on we'll preserve them
|
|
863
861
|
// "undefined" values, I believe, are/were not saved to/from DB anyway (due to e.g JSON.stringify removing them)
|
|
@@ -869,7 +867,10 @@ class CommonDao {
|
|
|
869
867
|
// and they can be annoying with snapshot tests
|
|
870
868
|
obj = (0, js_lib_1._filterUndefinedValues)(obj);
|
|
871
869
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
872
|
-
if (!schema ||
|
|
870
|
+
if (!schema ||
|
|
871
|
+
opt.skipValidation ||
|
|
872
|
+
(op === 'load' && !this.cfg.validateOnLoad) ||
|
|
873
|
+
(op === 'save' && !this.cfg.validateOnSave)) {
|
|
873
874
|
return obj;
|
|
874
875
|
}
|
|
875
876
|
// This will Convert and Validate
|
|
@@ -897,7 +898,7 @@ class CommonDao {
|
|
|
897
898
|
convertedValue = vr.value;
|
|
898
899
|
}
|
|
899
900
|
// If we care about validation and there's an error
|
|
900
|
-
if (error
|
|
901
|
+
if (error) {
|
|
901
902
|
const processedError = this.cfg.hooks.onValidationError(error);
|
|
902
903
|
if (processedError)
|
|
903
904
|
throw processedError;
|
|
@@ -101,6 +101,16 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
101
101
|
*/
|
|
102
102
|
bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodSchema<BM>;
|
|
103
103
|
excludeFromIndexes?: (keyof DBM)[];
|
|
104
|
+
/**
|
|
105
|
+
* Defaults to true.
|
|
106
|
+
* If set to false - load (read) operations will skip validation (and conversion).
|
|
107
|
+
*/
|
|
108
|
+
validateOnLoad?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Defaults to true.
|
|
111
|
+
* If set to false - save (write) operations will skip validation (and conversion).
|
|
112
|
+
*/
|
|
113
|
+
validateOnSave?: boolean;
|
|
104
114
|
/**
|
|
105
115
|
* Defaults to false.
|
|
106
116
|
* Setting it to true will set saveMethod to `insert` for save/saveBatch, which will
|
|
@@ -163,20 +173,12 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
163
173
|
*/
|
|
164
174
|
export interface CommonDaoOptions extends CommonDBOptions {
|
|
165
175
|
/**
|
|
166
|
-
*
|
|
167
|
-
* (according to Joi schema).
|
|
168
|
-
*
|
|
169
|
-
* Set skipConversion=true (or raw=true) to bypass conversion step as well (e.g for performance reasons).
|
|
176
|
+
* Defaults to false.
|
|
170
177
|
*
|
|
171
|
-
*
|
|
178
|
+
* If set to true - will disable validation (and conversion).
|
|
179
|
+
* One possible use case of doing this is - performance (as validation/conversion takes time, especially with Joi).
|
|
172
180
|
*/
|
|
173
181
|
skipValidation?: boolean;
|
|
174
|
-
/**
|
|
175
|
-
* If true - will SKIP the joi validation AND conversion steps alltogether. To improve performance of DAO.
|
|
176
|
-
*
|
|
177
|
-
* @default false
|
|
178
|
-
*/
|
|
179
|
-
skipConversion?: boolean;
|
|
180
182
|
/**
|
|
181
183
|
* @default false
|
|
182
184
|
*/
|
|
@@ -241,10 +243,6 @@ export interface CommonDaoStreamOptions<IN> extends CommonDaoOptions, TransformL
|
|
|
241
243
|
* @default true (for streams)
|
|
242
244
|
*/
|
|
243
245
|
skipValidation?: boolean;
|
|
244
|
-
/**
|
|
245
|
-
* @default true (for streams)
|
|
246
|
-
*/
|
|
247
|
-
skipConversion?: boolean;
|
|
248
246
|
/**
|
|
249
247
|
* @default ErrorMode.SUPPRESS for returning ReadableStream, because .pipe() has no concept of "error propagation"
|
|
250
248
|
* @default ErrorMode.SUPPRESS for .forEach() streams as well, but overridable
|
package/package.json
CHANGED
|
@@ -129,6 +129,18 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
129
129
|
|
|
130
130
|
excludeFromIndexes?: (keyof DBM)[]
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Defaults to true.
|
|
134
|
+
* If set to false - load (read) operations will skip validation (and conversion).
|
|
135
|
+
*/
|
|
136
|
+
validateOnLoad?: boolean
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Defaults to true.
|
|
140
|
+
* If set to false - save (write) operations will skip validation (and conversion).
|
|
141
|
+
*/
|
|
142
|
+
validateOnSave?: boolean
|
|
143
|
+
|
|
132
144
|
/**
|
|
133
145
|
* Defaults to false.
|
|
134
146
|
* Setting it to true will set saveMethod to `insert` for save/saveBatch, which will
|
|
@@ -203,22 +215,13 @@ export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
203
215
|
*/
|
|
204
216
|
export interface CommonDaoOptions extends CommonDBOptions {
|
|
205
217
|
/**
|
|
206
|
-
*
|
|
207
|
-
* (according to Joi schema).
|
|
208
|
-
*
|
|
209
|
-
* Set skipConversion=true (or raw=true) to bypass conversion step as well (e.g for performance reasons).
|
|
218
|
+
* Defaults to false.
|
|
210
219
|
*
|
|
211
|
-
*
|
|
220
|
+
* If set to true - will disable validation (and conversion).
|
|
221
|
+
* One possible use case of doing this is - performance (as validation/conversion takes time, especially with Joi).
|
|
212
222
|
*/
|
|
213
223
|
skipValidation?: boolean
|
|
214
224
|
|
|
215
|
-
/**
|
|
216
|
-
* If true - will SKIP the joi validation AND conversion steps alltogether. To improve performance of DAO.
|
|
217
|
-
*
|
|
218
|
-
* @default false
|
|
219
|
-
*/
|
|
220
|
-
skipConversion?: boolean
|
|
221
|
-
|
|
222
225
|
/**
|
|
223
226
|
* @default false
|
|
224
227
|
*/
|
|
@@ -302,11 +305,6 @@ export interface CommonDaoStreamOptions<IN>
|
|
|
302
305
|
*/
|
|
303
306
|
skipValidation?: boolean
|
|
304
307
|
|
|
305
|
-
/**
|
|
306
|
-
* @default true (for streams)
|
|
307
|
-
*/
|
|
308
|
-
skipConversion?: boolean
|
|
309
|
-
|
|
310
308
|
/**
|
|
311
309
|
* @default ErrorMode.SUPPRESS for returning ReadableStream, because .pipe() has no concept of "error propagation"
|
|
312
310
|
* @default ErrorMode.SUPPRESS for .forEach() streams as well, but overridable
|
|
@@ -81,6 +81,8 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
81
81
|
assignGeneratedIds: false,
|
|
82
82
|
useCreatedProperty: true,
|
|
83
83
|
useUpdatedProperty: true,
|
|
84
|
+
validateOnLoad: true,
|
|
85
|
+
validateOnSave: true,
|
|
84
86
|
logger: console,
|
|
85
87
|
...cfg,
|
|
86
88
|
hooks: {
|
|
@@ -104,7 +106,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
104
106
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
105
107
|
// First assignIdCreatedUpdated, then validate!
|
|
106
108
|
this.assignIdCreatedUpdated(bm, opt)
|
|
107
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
109
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, undefined, opt)
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
// GET
|
|
@@ -353,7 +355,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
353
355
|
): Promise<void> {
|
|
354
356
|
q.table = opt.table || q.table
|
|
355
357
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
356
|
-
opt.skipConversion = opt.skipConversion !== false // default true
|
|
357
358
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
358
359
|
|
|
359
360
|
const partialQuery = !!q._selectedFieldNames
|
|
@@ -403,7 +404,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
403
404
|
): Promise<void> {
|
|
404
405
|
q.table = opt.table || q.table
|
|
405
406
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
406
|
-
opt.skipConversion = opt.skipConversion !== false // default true
|
|
407
407
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
408
408
|
|
|
409
409
|
const partialQuery = !!q._selectedFieldNames
|
|
@@ -452,7 +452,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
452
452
|
streamQueryAsDBM(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<DBM> = {}): ReadableTyped<DBM> {
|
|
453
453
|
q.table = opt.table || q.table
|
|
454
454
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
455
|
-
opt.skipConversion = opt.skipConversion !== false // default true
|
|
456
455
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
457
456
|
|
|
458
457
|
const partialQuery = !!q._selectedFieldNames
|
|
@@ -491,7 +490,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
491
490
|
streamQuery(q: DBQuery<DBM>, opt: CommonDaoStreamOptions<BM> = {}): ReadableTyped<BM> {
|
|
492
491
|
q.table = opt.table || q.table
|
|
493
492
|
opt.skipValidation = opt.skipValidation !== false // default true
|
|
494
|
-
opt.skipConversion = opt.skipConversion !== false // default true
|
|
495
493
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
496
494
|
|
|
497
495
|
const stream = this.cfg.db.streamQuery<DBM>(q, opt)
|
|
@@ -721,7 +719,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
721
719
|
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
722
720
|
// which should be removed post-validation, but it breaks the "equality check"
|
|
723
721
|
// Post-validation the equality check should work as intended
|
|
724
|
-
const convertedBM = this.validateAndConvert(bm as Partial<BM>, this.cfg.bmSchema, opt)
|
|
722
|
+
const convertedBM = this.validateAndConvert(bm as Partial<BM>, this.cfg.bmSchema, 'save', opt)
|
|
725
723
|
if (_deepJsonEquals(convertedBM, opt.skipIfEquals)) {
|
|
726
724
|
// Skipping the save operation
|
|
727
725
|
return bm as BM
|
|
@@ -900,7 +898,6 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
900
898
|
|
|
901
899
|
const table = opt.table || this.cfg.table
|
|
902
900
|
opt.skipValidation ??= true
|
|
903
|
-
opt.skipConversion ??= true
|
|
904
901
|
opt.errorMode ||= ErrorMode.SUPPRESS
|
|
905
902
|
|
|
906
903
|
if (this.cfg.immutable && !opt.allowMutability && !opt.saveMethod) {
|
|
@@ -1077,7 +1074,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1077
1074
|
const bm = ((await this.cfg.hooks!.beforeDBMToBM?.(dbm)) || dbm) as Partial<BM>
|
|
1078
1075
|
|
|
1079
1076
|
// Validate/convert BM
|
|
1080
|
-
return this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1077
|
+
return this.validateAndConvert(bm, this.cfg.bmSchema, 'load', opt)
|
|
1081
1078
|
}
|
|
1082
1079
|
|
|
1083
1080
|
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
@@ -1094,7 +1091,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1094
1091
|
if (bm === undefined) return
|
|
1095
1092
|
|
|
1096
1093
|
// bm gets assigned to the new reference
|
|
1097
|
-
bm = this.validateAndConvert(bm, this.cfg.bmSchema, opt)
|
|
1094
|
+
bm = this.validateAndConvert(bm, this.cfg.bmSchema, 'save', opt)
|
|
1098
1095
|
|
|
1099
1096
|
// BM > DBM
|
|
1100
1097
|
return ((await this.cfg.hooks!.beforeBMToDBM?.(bm!)) || bm) as DBM
|
|
@@ -1138,6 +1135,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1138
1135
|
validateAndConvert<T>(
|
|
1139
1136
|
obj: Partial<T>,
|
|
1140
1137
|
schema: ObjectSchema<T> | AjvSchema<T> | ZodSchema<T> | undefined,
|
|
1138
|
+
op?: 'load' | 'save', // this is to skip validation if validateOnLoad/Save is false
|
|
1141
1139
|
opt: CommonDaoOptions = {},
|
|
1142
1140
|
): any {
|
|
1143
1141
|
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
@@ -1152,7 +1150,12 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1152
1150
|
obj = _filterUndefinedValues(obj)
|
|
1153
1151
|
|
|
1154
1152
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
1155
|
-
if (
|
|
1153
|
+
if (
|
|
1154
|
+
!schema ||
|
|
1155
|
+
opt.skipValidation ||
|
|
1156
|
+
(op === 'load' && !this.cfg.validateOnLoad) ||
|
|
1157
|
+
(op === 'save' && !this.cfg.validateOnSave)
|
|
1158
|
+
) {
|
|
1156
1159
|
return obj
|
|
1157
1160
|
}
|
|
1158
1161
|
|
|
@@ -1183,7 +1186,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM> {
|
|
|
1183
1186
|
}
|
|
1184
1187
|
|
|
1185
1188
|
// If we care about validation and there's an error
|
|
1186
|
-
if (error
|
|
1189
|
+
if (error) {
|
|
1187
1190
|
const processedError = this.cfg.hooks!.onValidationError!(error)
|
|
1188
1191
|
|
|
1189
1192
|
if (processedError) throw processedError
|