@naturalcycles/db-lib 10.10.1 → 10.12.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 +1 -5
- package/dist/commondao/common.dao.js +16 -51
- package/dist/commondao/common.dao.model.d.ts +16 -13
- package/dist/testing/commonDaoTest.js +2 -1
- package/package.json +1 -1
- package/src/commondao/common.dao.model.ts +17 -16
- package/src/commondao/common.dao.ts +19 -59
- package/src/testing/commonDaoTest.ts +2 -1
|
@@ -2,9 +2,6 @@ import type { Transform } from 'node:stream';
|
|
|
2
2
|
import type { JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib/json-schema';
|
|
3
3
|
import type { CommonLogger } from '@naturalcycles/js-lib/log';
|
|
4
4
|
import type { AsyncIndexedMapper, BaseDBEntity, StringMap, UnixTimestampMillis, Unsaved } from '@naturalcycles/js-lib/types';
|
|
5
|
-
import { ZodType } from '@naturalcycles/js-lib/zod';
|
|
6
|
-
import { AjvSchema } from '@naturalcycles/nodejs-lib/ajv';
|
|
7
|
-
import { type ObjectSchema } from '@naturalcycles/nodejs-lib/joi';
|
|
8
5
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream';
|
|
9
6
|
import type { CommonDBTransactionOptions, DBTransaction, RunQueryResult } from '../db.model.js';
|
|
10
7
|
import type { DBQuery } from '../query/dbQuery.js';
|
|
@@ -163,8 +160,7 @@ export declare class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity
|
|
|
163
160
|
* Does NOT mutate the object.
|
|
164
161
|
* Validates (unless `skipValidation=true` passed).
|
|
165
162
|
*/
|
|
166
|
-
validateAndConvert
|
|
167
|
-
opt?: CommonDaoOptions): any;
|
|
163
|
+
private validateAndConvert;
|
|
168
164
|
getTableSchema(): Promise<JsonSchemaRootObject<DBM>>;
|
|
169
165
|
createTable(schema: JsonSchemaObject<DBM>, opt?: CommonDaoCreateOptions): Promise<void>;
|
|
170
166
|
/**
|
|
@@ -8,10 +8,7 @@ import { _deepCopy, _filterUndefinedValues, _objectAssignExact, } from '@natural
|
|
|
8
8
|
import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
|
|
9
9
|
import { _truncate } from '@naturalcycles/js-lib/string/string.util.js';
|
|
10
10
|
import { _passthroughPredicate, _typeCast, SKIP } from '@naturalcycles/js-lib/types';
|
|
11
|
-
import { ZodType, zSafeValidate } from '@naturalcycles/js-lib/zod';
|
|
12
11
|
import { stringId } from '@naturalcycles/nodejs-lib';
|
|
13
|
-
import { AjvSchema } from '@naturalcycles/nodejs-lib/ajv';
|
|
14
|
-
import { getValidationResult, } from '@naturalcycles/nodejs-lib/joi';
|
|
15
12
|
import { _pipeline, transformChunk, transformLogProgress, transformMap, transformNoOp, writableVoid, } from '@naturalcycles/nodejs-lib/stream';
|
|
16
13
|
import { DBLibError } from '../cnst.js';
|
|
17
14
|
import { RunnableDBQuery } from '../query/dbQuery.js';
|
|
@@ -57,7 +54,7 @@ export class CommonDao {
|
|
|
57
54
|
const bm = this.cfg.hooks.beforeCreate(part);
|
|
58
55
|
// First assignIdCreatedUpdated, then validate!
|
|
59
56
|
this.assignIdCreatedUpdated(bm, opt);
|
|
60
|
-
return this.validateAndConvert(bm,
|
|
57
|
+
return this.validateAndConvert(bm, undefined, opt);
|
|
61
58
|
}
|
|
62
59
|
// GET
|
|
63
60
|
// overrides are disabled now, as they obfuscate errors when ID branded type is used
|
|
@@ -592,7 +589,7 @@ export class CommonDao {
|
|
|
592
589
|
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
593
590
|
// which should be removed post-validation, but it breaks the "equality check"
|
|
594
591
|
// Post-validation the equality check should work as intended
|
|
595
|
-
const convertedBM = this.validateAndConvert(bm,
|
|
592
|
+
const convertedBM = this.validateAndConvert(bm, 'save', opt);
|
|
596
593
|
if (_deepJsonEquals(convertedBM, opt.skipIfEquals)) {
|
|
597
594
|
// Skipping the save operation
|
|
598
595
|
return bm;
|
|
@@ -901,7 +898,7 @@ export class CommonDao {
|
|
|
901
898
|
// DBM > BM
|
|
902
899
|
const bm = ((await this.cfg.hooks.beforeDBMToBM?.(dbm)) || dbm);
|
|
903
900
|
// Validate/convert BM
|
|
904
|
-
return this.validateAndConvert(bm,
|
|
901
|
+
return this.validateAndConvert(bm, 'load', opt);
|
|
905
902
|
}
|
|
906
903
|
async dbmsToBM(dbms, opt = {}) {
|
|
907
904
|
return await pMap(dbms, async (dbm) => await this.dbmToBM(dbm, opt));
|
|
@@ -910,7 +907,7 @@ export class CommonDao {
|
|
|
910
907
|
if (bm === undefined)
|
|
911
908
|
return;
|
|
912
909
|
// bm gets assigned to the new reference
|
|
913
|
-
bm = this.validateAndConvert(bm,
|
|
910
|
+
bm = this.validateAndConvert(bm, 'save', opt);
|
|
914
911
|
// BM > DBM
|
|
915
912
|
return ((await this.cfg.hooks.beforeBMToDBM?.(bm)) || bm);
|
|
916
913
|
}
|
|
@@ -941,58 +938,26 @@ export class CommonDao {
|
|
|
941
938
|
* Does NOT mutate the object.
|
|
942
939
|
* Validates (unless `skipValidation=true` passed).
|
|
943
940
|
*/
|
|
944
|
-
validateAndConvert(
|
|
941
|
+
validateAndConvert(input, op, // this is to skip validation if validateOnLoad/Save is false
|
|
945
942
|
opt = {}) {
|
|
946
|
-
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
947
|
-
// So, from now on we'll preserve them
|
|
948
|
-
// "undefined" values, I believe, are/were not saved to/from DB anyway (due to e.g JSON.stringify removing them)
|
|
949
|
-
// But let's keep watching it!
|
|
950
|
-
//
|
|
951
|
-
// Filter null and undefined values
|
|
952
|
-
// obj = _filterNullishValues(obj as any)
|
|
953
943
|
// We still filter `undefined` values here, because `beforeDBMToBM` can return undefined values
|
|
954
944
|
// and they can be annoying with snapshot tests
|
|
955
|
-
|
|
945
|
+
input = _filterUndefinedValues(input);
|
|
956
946
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
957
|
-
if (
|
|
947
|
+
if (!this.cfg.validateBM ||
|
|
958
948
|
opt.skipValidation ||
|
|
959
949
|
(op === 'load' && !this.cfg.validateOnLoad) ||
|
|
960
950
|
(op === 'save' && !this.cfg.validateOnSave)) {
|
|
961
|
-
return
|
|
962
|
-
}
|
|
963
|
-
// This will Convert and Validate
|
|
964
|
-
const table = opt.table || this.cfg.table;
|
|
965
|
-
const objectName = table;
|
|
966
|
-
let error;
|
|
967
|
-
let convertedValue;
|
|
968
|
-
if (this.cfg.validateBM) {
|
|
969
|
-
const [err, value] = this.cfg.validateBM(obj, {
|
|
970
|
-
inputName: table,
|
|
971
|
-
});
|
|
972
|
-
error = err;
|
|
973
|
-
convertedValue = value;
|
|
974
|
-
}
|
|
975
|
-
else if (schema instanceof ZodType) {
|
|
976
|
-
// Zod schema
|
|
977
|
-
const [err, value] = zSafeValidate(obj, schema);
|
|
978
|
-
error = err;
|
|
979
|
-
convertedValue = value;
|
|
951
|
+
return input;
|
|
980
952
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
}
|
|
989
|
-
else {
|
|
990
|
-
// Joi
|
|
991
|
-
const [err, value] = getValidationResult(obj, schema, objectName);
|
|
992
|
-
error = err;
|
|
993
|
-
convertedValue = value;
|
|
994
|
-
}
|
|
995
|
-
// If we care about validation and there's an error
|
|
953
|
+
const inputName = opt.table || this.cfg.table;
|
|
954
|
+
const [error, convertedValue] = this.cfg.validateBM(input, {
|
|
955
|
+
// Passing `mutateInput` through allows to do opt-in mutation
|
|
956
|
+
// for individual operations, e.g `someDao.save(myObj, { mutateInput: true })`,
|
|
957
|
+
// while still keeping safe non-mutating behavior by default
|
|
958
|
+
mutateInput: opt.mutateInput,
|
|
959
|
+
inputName,
|
|
960
|
+
});
|
|
996
961
|
if (error) {
|
|
997
962
|
const processedError = this.cfg.hooks.onValidationError(error);
|
|
998
963
|
if (processedError)
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { ValidationFunction } from '@naturalcycles/js-lib';
|
|
2
|
-
import type { ErrorMode } from '@naturalcycles/js-lib/error';
|
|
2
|
+
import type { AppError, ErrorMode } from '@naturalcycles/js-lib/error';
|
|
3
3
|
import type { CommonLogger } from '@naturalcycles/js-lib/log';
|
|
4
4
|
import type { BaseDBEntity, NumberOfMilliseconds, Promisable, UnixTimestamp } from '@naturalcycles/js-lib/types';
|
|
5
|
-
import type { ZodType, ZodValidationError } from '@naturalcycles/js-lib/zod';
|
|
6
|
-
import type { AjvSchema, AjvValidationError } from '@naturalcycles/nodejs-lib/ajv';
|
|
7
|
-
import type { JoiValidationError, ObjectSchema } from '@naturalcycles/nodejs-lib/joi';
|
|
8
5
|
import type { TransformLogProgressOptions, TransformMapOptions } from '@naturalcycles/nodejs-lib/stream';
|
|
9
6
|
import type { CommonDB } from '../commondb/common.db.js';
|
|
10
7
|
import type { CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions } from '../db.model.js';
|
|
@@ -79,7 +76,7 @@ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntit
|
|
|
79
76
|
* Return original `err` to pass the error through (will be thrown in CommonDao).
|
|
80
77
|
* Return modified/new `Error` if needed.
|
|
81
78
|
*/
|
|
82
|
-
onValidationError: (err:
|
|
79
|
+
onValidationError: (err: AppError) => Error | false;
|
|
83
80
|
}
|
|
84
81
|
export declare enum CommonDaoLogLevel {
|
|
85
82
|
/**
|
|
@@ -102,17 +99,11 @@ export declare enum CommonDaoLogLevel {
|
|
|
102
99
|
export interface CommonDaoCfg<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, ID = BM['id']> {
|
|
103
100
|
db: CommonDB;
|
|
104
101
|
table: string;
|
|
105
|
-
/**
|
|
106
|
-
* Joi, AjvSchema or ZodSchema is supported.
|
|
107
|
-
*/
|
|
108
|
-
bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodType<BM>;
|
|
109
102
|
/**
|
|
110
103
|
* Experimental alternative to bmSchema.
|
|
111
104
|
* "Bring your own validation function".
|
|
112
105
|
* It removes the knowledge from CommonDao about the validation library used
|
|
113
106
|
* and abstracts it away.
|
|
114
|
-
*
|
|
115
|
-
* @experimental
|
|
116
107
|
*/
|
|
117
108
|
validateBM?: ValidationFunction<BM, any>;
|
|
118
109
|
excludeFromIndexes?: (keyof DBM)[];
|
|
@@ -190,10 +181,22 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
190
181
|
/**
|
|
191
182
|
* Defaults to false.
|
|
192
183
|
*
|
|
193
|
-
* If set to true - will disable validation
|
|
194
|
-
* One possible use case of doing this is - performance (as validation/
|
|
184
|
+
* If set to true - will disable validation.
|
|
185
|
+
* One possible use case of doing this is - performance (as validation/transformation takes time, especially with Joi).
|
|
195
186
|
*/
|
|
196
187
|
skipValidation?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Default to false.
|
|
190
|
+
*
|
|
191
|
+
* False ensures that the input is not mutated by the Validation function (`validateBM`).
|
|
192
|
+
*
|
|
193
|
+
* True ensures the opposite - that the Validation function will mutate the input object
|
|
194
|
+
* if it needs to apply transformations, such as:
|
|
195
|
+
* - stripping unknown properties
|
|
196
|
+
* - converting types (e.g. string to number)
|
|
197
|
+
* - applying transformations (which as string trim, toLowerCase, etc)
|
|
198
|
+
*/
|
|
199
|
+
mutateInput?: boolean;
|
|
197
200
|
/**
|
|
198
201
|
* @default false
|
|
199
202
|
*/
|
|
@@ -2,6 +2,7 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js';
|
|
3
3
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
|
|
4
4
|
import { _deepCopy, _filterObject, _omit, _pick } from '@naturalcycles/js-lib/object';
|
|
5
|
+
import { getJoiValidationFunction } from '@naturalcycles/nodejs-lib/joi';
|
|
5
6
|
import { _pipeline } from '@naturalcycles/nodejs-lib/stream';
|
|
6
7
|
import { CommonDao } from '../commondao/common.dao.js';
|
|
7
8
|
import { CommonDaoLogLevel } from '../commondao/common.dao.model.js';
|
|
@@ -14,7 +15,7 @@ export async function runCommonDaoTest(db, quirks = {}) {
|
|
|
14
15
|
const dao = new CommonDao({
|
|
15
16
|
table: TEST_TABLE,
|
|
16
17
|
db,
|
|
17
|
-
|
|
18
|
+
validateBM: getJoiValidationFunction(testItemBMSchema),
|
|
18
19
|
logStarted: true,
|
|
19
20
|
logLevel: CommonDaoLogLevel.DATA_FULL,
|
|
20
21
|
});
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValidationFunction } from '@naturalcycles/js-lib'
|
|
2
|
-
import type { ErrorMode } from '@naturalcycles/js-lib/error'
|
|
2
|
+
import type { AppError, ErrorMode } from '@naturalcycles/js-lib/error'
|
|
3
3
|
import type { CommonLogger } from '@naturalcycles/js-lib/log'
|
|
4
4
|
import type {
|
|
5
5
|
BaseDBEntity,
|
|
@@ -7,9 +7,6 @@ import type {
|
|
|
7
7
|
Promisable,
|
|
8
8
|
UnixTimestamp,
|
|
9
9
|
} from '@naturalcycles/js-lib/types'
|
|
10
|
-
import type { ZodType, ZodValidationError } from '@naturalcycles/js-lib/zod'
|
|
11
|
-
import type { AjvSchema, AjvValidationError } from '@naturalcycles/nodejs-lib/ajv'
|
|
12
|
-
import type { JoiValidationError, ObjectSchema } from '@naturalcycles/nodejs-lib/joi'
|
|
13
10
|
import type {
|
|
14
11
|
TransformLogProgressOptions,
|
|
15
12
|
TransformMapOptions,
|
|
@@ -96,9 +93,7 @@ export interface CommonDaoHooks<BM extends BaseDBEntity, DBM extends BaseDBEntit
|
|
|
96
93
|
* Return original `err` to pass the error through (will be thrown in CommonDao).
|
|
97
94
|
* Return modified/new `Error` if needed.
|
|
98
95
|
*/
|
|
99
|
-
onValidationError: (
|
|
100
|
-
err: JoiValidationError | AjvValidationError | ZodValidationError,
|
|
101
|
-
) => Error | false
|
|
96
|
+
onValidationError: (err: AppError) => Error | false
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
export enum CommonDaoLogLevel {
|
|
@@ -128,18 +123,11 @@ export interface CommonDaoCfg<
|
|
|
128
123
|
db: CommonDB
|
|
129
124
|
table: string
|
|
130
125
|
|
|
131
|
-
/**
|
|
132
|
-
* Joi, AjvSchema or ZodSchema is supported.
|
|
133
|
-
*/
|
|
134
|
-
bmSchema?: ObjectSchema<BM> | AjvSchema<BM> | ZodType<BM>
|
|
135
|
-
|
|
136
126
|
/**
|
|
137
127
|
* Experimental alternative to bmSchema.
|
|
138
128
|
* "Bring your own validation function".
|
|
139
129
|
* It removes the knowledge from CommonDao about the validation library used
|
|
140
130
|
* and abstracts it away.
|
|
141
|
-
*
|
|
142
|
-
* @experimental
|
|
143
131
|
*/
|
|
144
132
|
validateBM?: ValidationFunction<BM, any>
|
|
145
133
|
|
|
@@ -233,11 +221,24 @@ export interface CommonDaoOptions extends CommonDBOptions {
|
|
|
233
221
|
/**
|
|
234
222
|
* Defaults to false.
|
|
235
223
|
*
|
|
236
|
-
* If set to true - will disable validation
|
|
237
|
-
* One possible use case of doing this is - performance (as validation/
|
|
224
|
+
* If set to true - will disable validation.
|
|
225
|
+
* One possible use case of doing this is - performance (as validation/transformation takes time, especially with Joi).
|
|
238
226
|
*/
|
|
239
227
|
skipValidation?: boolean
|
|
240
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Default to false.
|
|
231
|
+
*
|
|
232
|
+
* False ensures that the input is not mutated by the Validation function (`validateBM`).
|
|
233
|
+
*
|
|
234
|
+
* True ensures the opposite - that the Validation function will mutate the input object
|
|
235
|
+
* if it needs to apply transformations, such as:
|
|
236
|
+
* - stripping unknown properties
|
|
237
|
+
* - converting types (e.g. string to number)
|
|
238
|
+
* - applying transformations (which as string trim, toLowerCase, etc)
|
|
239
|
+
*/
|
|
240
|
+
mutateInput?: boolean
|
|
241
|
+
|
|
241
242
|
/**
|
|
242
243
|
* @default false
|
|
243
244
|
*/
|
|
@@ -23,15 +23,7 @@ import type {
|
|
|
23
23
|
Unsaved,
|
|
24
24
|
} from '@naturalcycles/js-lib/types'
|
|
25
25
|
import { _passthroughPredicate, _typeCast, SKIP } from '@naturalcycles/js-lib/types'
|
|
26
|
-
import type { ZodValidationError } from '@naturalcycles/js-lib/zod'
|
|
27
|
-
import { ZodType, zSafeValidate } from '@naturalcycles/js-lib/zod'
|
|
28
26
|
import { stringId } from '@naturalcycles/nodejs-lib'
|
|
29
|
-
import { AjvSchema, type AjvValidationError } from '@naturalcycles/nodejs-lib/ajv'
|
|
30
|
-
import {
|
|
31
|
-
getValidationResult,
|
|
32
|
-
type JoiValidationError,
|
|
33
|
-
type ObjectSchema,
|
|
34
|
-
} from '@naturalcycles/nodejs-lib/joi'
|
|
35
27
|
import type { ReadableTyped } from '@naturalcycles/nodejs-lib/stream'
|
|
36
28
|
import {
|
|
37
29
|
_pipeline,
|
|
@@ -102,7 +94,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
|
|
|
102
94
|
const bm = this.cfg.hooks!.beforeCreate!(part)
|
|
103
95
|
// First assignIdCreatedUpdated, then validate!
|
|
104
96
|
this.assignIdCreatedUpdated(bm, opt)
|
|
105
|
-
return this.validateAndConvert(bm,
|
|
97
|
+
return this.validateAndConvert(bm, undefined, opt)
|
|
106
98
|
}
|
|
107
99
|
|
|
108
100
|
// GET
|
|
@@ -767,7 +759,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
|
|
|
767
759
|
// We compare with convertedBM, to account for cases when some extra property is assigned to bm,
|
|
768
760
|
// which should be removed post-validation, but it breaks the "equality check"
|
|
769
761
|
// Post-validation the equality check should work as intended
|
|
770
|
-
const convertedBM = this.validateAndConvert(bm as Partial<BM>,
|
|
762
|
+
const convertedBM = this.validateAndConvert(bm as Partial<BM>, 'save', opt)
|
|
771
763
|
if (_deepJsonEquals(convertedBM, opt.skipIfEquals)) {
|
|
772
764
|
// Skipping the save operation
|
|
773
765
|
return bm as BM
|
|
@@ -1150,7 +1142,7 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
|
|
|
1150
1142
|
const bm = ((await this.cfg.hooks!.beforeDBMToBM?.(dbm)) || dbm) as Partial<BM>
|
|
1151
1143
|
|
|
1152
1144
|
// Validate/convert BM
|
|
1153
|
-
return this.validateAndConvert(bm,
|
|
1145
|
+
return this.validateAndConvert(bm, 'load', opt)
|
|
1154
1146
|
}
|
|
1155
1147
|
|
|
1156
1148
|
async dbmsToBM(dbms: DBM[], opt: CommonDaoOptions = {}): Promise<BM[]> {
|
|
@@ -1167,10 +1159,10 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
|
|
|
1167
1159
|
if (bm === undefined) return
|
|
1168
1160
|
|
|
1169
1161
|
// bm gets assigned to the new reference
|
|
1170
|
-
bm = this.validateAndConvert(bm,
|
|
1162
|
+
bm = this.validateAndConvert(bm, 'save', opt)
|
|
1171
1163
|
|
|
1172
1164
|
// BM > DBM
|
|
1173
|
-
return ((await this.cfg.hooks!.beforeBMToDBM?.(bm
|
|
1165
|
+
return ((await this.cfg.hooks!.beforeBMToDBM?.(bm)) || bm) as DBM
|
|
1174
1166
|
}
|
|
1175
1167
|
|
|
1176
1168
|
async bmsToDBM(bms: BM[], opt: CommonDaoOptions = {}): Promise<DBM[]> {
|
|
@@ -1208,69 +1200,37 @@ export class CommonDao<BM extends BaseDBEntity, DBM extends BaseDBEntity = BM, I
|
|
|
1208
1200
|
* Does NOT mutate the object.
|
|
1209
1201
|
* Validates (unless `skipValidation=true` passed).
|
|
1210
1202
|
*/
|
|
1211
|
-
validateAndConvert
|
|
1212
|
-
|
|
1213
|
-
schema: ObjectSchema<T> | AjvSchema<T> | ZodType<T> | undefined,
|
|
1203
|
+
private validateAndConvert(
|
|
1204
|
+
input: Partial<BM>,
|
|
1214
1205
|
op?: 'load' | 'save', // this is to skip validation if validateOnLoad/Save is false
|
|
1215
1206
|
opt: CommonDaoOptions = {},
|
|
1216
|
-
):
|
|
1217
|
-
// Kirill 2021-10-18: I realized that there's little reason to keep removing null values
|
|
1218
|
-
// So, from now on we'll preserve them
|
|
1219
|
-
// "undefined" values, I believe, are/were not saved to/from DB anyway (due to e.g JSON.stringify removing them)
|
|
1220
|
-
// But let's keep watching it!
|
|
1221
|
-
//
|
|
1222
|
-
// Filter null and undefined values
|
|
1223
|
-
// obj = _filterNullishValues(obj as any)
|
|
1207
|
+
): BM {
|
|
1224
1208
|
// We still filter `undefined` values here, because `beforeDBMToBM` can return undefined values
|
|
1225
1209
|
// and they can be annoying with snapshot tests
|
|
1226
|
-
|
|
1210
|
+
input = _filterUndefinedValues(input)
|
|
1227
1211
|
|
|
1228
1212
|
// Return as is if no schema is passed or if `skipConversion` is set
|
|
1229
1213
|
if (
|
|
1230
|
-
|
|
1214
|
+
!this.cfg.validateBM ||
|
|
1231
1215
|
opt.skipValidation ||
|
|
1232
1216
|
(op === 'load' && !this.cfg.validateOnLoad) ||
|
|
1233
1217
|
(op === 'save' && !this.cfg.validateOnSave)
|
|
1234
1218
|
) {
|
|
1235
|
-
return
|
|
1219
|
+
return input as BM
|
|
1236
1220
|
}
|
|
1237
1221
|
|
|
1238
|
-
|
|
1239
|
-
const table = opt.table || this.cfg.table
|
|
1240
|
-
const objectName = table
|
|
1222
|
+
const inputName = opt.table || this.cfg.table
|
|
1241
1223
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
error = err
|
|
1250
|
-
convertedValue = value
|
|
1251
|
-
} else if (schema instanceof ZodType) {
|
|
1252
|
-
// Zod schema
|
|
1253
|
-
const [err, value] = zSafeValidate(obj as T, schema)
|
|
1254
|
-
error = err
|
|
1255
|
-
convertedValue = value
|
|
1256
|
-
} else if (schema instanceof AjvSchema) {
|
|
1257
|
-
// Ajv schema
|
|
1258
|
-
const [err, value] = schema.getValidationResult(obj as T, {
|
|
1259
|
-
objectName,
|
|
1260
|
-
})
|
|
1261
|
-
error = err
|
|
1262
|
-
convertedValue = value
|
|
1263
|
-
} else {
|
|
1264
|
-
// Joi
|
|
1265
|
-
const [err, value] = getValidationResult(obj, schema, objectName)
|
|
1266
|
-
error = err
|
|
1267
|
-
convertedValue = value
|
|
1268
|
-
}
|
|
1224
|
+
const [error, convertedValue] = this.cfg.validateBM(input as BM, {
|
|
1225
|
+
// Passing `mutateInput` through allows to do opt-in mutation
|
|
1226
|
+
// for individual operations, e.g `someDao.save(myObj, { mutateInput: true })`,
|
|
1227
|
+
// while still keeping safe non-mutating behavior by default
|
|
1228
|
+
mutateInput: opt.mutateInput,
|
|
1229
|
+
inputName,
|
|
1230
|
+
})
|
|
1269
1231
|
|
|
1270
|
-
// If we care about validation and there's an error
|
|
1271
1232
|
if (error) {
|
|
1272
1233
|
const processedError = this.cfg.hooks!.onValidationError!(error)
|
|
1273
|
-
|
|
1274
1234
|
if (processedError) throw processedError
|
|
1275
1235
|
}
|
|
1276
1236
|
|
|
@@ -2,6 +2,7 @@ import { Readable } from 'node:stream'
|
|
|
2
2
|
import { _sortBy } from '@naturalcycles/js-lib/array/array.util.js'
|
|
3
3
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
|
|
4
4
|
import { _deepCopy, _filterObject, _omit, _pick } from '@naturalcycles/js-lib/object'
|
|
5
|
+
import { getJoiValidationFunction } from '@naturalcycles/nodejs-lib/joi'
|
|
5
6
|
import { _pipeline } from '@naturalcycles/nodejs-lib/stream'
|
|
6
7
|
import { CommonDao } from '../commondao/common.dao.js'
|
|
7
8
|
import { CommonDaoLogLevel } from '../commondao/common.dao.model.js'
|
|
@@ -28,7 +29,7 @@ export async function runCommonDaoTest(
|
|
|
28
29
|
const dao = new CommonDao({
|
|
29
30
|
table: TEST_TABLE,
|
|
30
31
|
db,
|
|
31
|
-
|
|
32
|
+
validateBM: getJoiValidationFunction(testItemBMSchema),
|
|
32
33
|
logStarted: true,
|
|
33
34
|
logLevel: CommonDaoLogLevel.DATA_FULL,
|
|
34
35
|
})
|