koatty_validation 1.6.1 → 1.6.6
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/.rollup.config.js +10 -4
- package/.turbo/turbo-build.log +171 -0
- package/.turbo/turbo-test.log +8 -0
- package/CHANGELOG.md +59 -26
- package/dist/index.d.ts +29 -9
- package/dist/index.js +228 -204
- package/dist/index.mjs +228 -204
- package/dist/package.json +10 -14
- package/package.json +21 -26
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @Author: richen
|
|
3
|
-
* @Date:
|
|
3
|
+
* @Date: 2026-01-28 17:22:04
|
|
4
4
|
* @License: BSD (3-Clause)
|
|
5
5
|
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
6
6
|
* @HomePage: https://koatty.org/
|
|
@@ -799,6 +799,209 @@ function plateNumber(value) {
|
|
|
799
799
|
}
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
/**
|
|
803
|
+
* Improved error handling mechanism
|
|
804
|
+
* @author richen
|
|
805
|
+
*/
|
|
806
|
+
/**
|
|
807
|
+
* Error message internationalization
|
|
808
|
+
*/
|
|
809
|
+
const ERROR_MESSAGES = {
|
|
810
|
+
zh: {
|
|
811
|
+
// Chinese localization validation
|
|
812
|
+
IsCnName: '必须是有效的中文姓名',
|
|
813
|
+
IsIdNumber: '必须是有效的身份证号码',
|
|
814
|
+
IsZipCode: '必须是有效的邮政编码',
|
|
815
|
+
IsMobile: '必须是有效的手机号码',
|
|
816
|
+
IsPlateNumber: '必须是有效的车牌号码',
|
|
817
|
+
// Basic validation
|
|
818
|
+
IsNotEmpty: '不能为空',
|
|
819
|
+
IsDate: '必须是有效的日期',
|
|
820
|
+
IsEmail: '必须是有效的邮箱地址',
|
|
821
|
+
IsIP: '必须是有效的IP地址',
|
|
822
|
+
IsPhoneNumber: '必须是有效的电话号码',
|
|
823
|
+
IsUrl: '必须是有效的URL地址',
|
|
824
|
+
IsHash: '必须是有效的哈希值',
|
|
825
|
+
// Comparison validation
|
|
826
|
+
Equals: '必须等于 {comparison}',
|
|
827
|
+
NotEquals: '不能等于 {comparison}',
|
|
828
|
+
Contains: '必须包含 {seed}',
|
|
829
|
+
IsIn: '必须是以下值之一: {possibleValues}',
|
|
830
|
+
IsNotIn: '不能是以下值之一: {possibleValues}',
|
|
831
|
+
Gt: '必须大于 {min}',
|
|
832
|
+
Gte: '必须大于或等于 {min}',
|
|
833
|
+
Lt: '必须小于 {max}',
|
|
834
|
+
Lte: '必须小于或等于 {max}',
|
|
835
|
+
// Common errors
|
|
836
|
+
invalidParameter: '参数 {field} 无效',
|
|
837
|
+
validationFailed: '验证失败',
|
|
838
|
+
},
|
|
839
|
+
en: {
|
|
840
|
+
// Chinese localization validators
|
|
841
|
+
IsCnName: 'must be a valid Chinese name',
|
|
842
|
+
IsIdNumber: 'must be a valid ID number',
|
|
843
|
+
IsZipCode: 'must be a valid zip code',
|
|
844
|
+
IsMobile: 'must be a valid mobile number',
|
|
845
|
+
IsPlateNumber: 'must be a valid plate number',
|
|
846
|
+
// Basic validators
|
|
847
|
+
IsNotEmpty: 'should not be empty',
|
|
848
|
+
IsDate: 'must be a valid date',
|
|
849
|
+
IsEmail: 'must be a valid email',
|
|
850
|
+
IsIP: 'must be a valid IP address',
|
|
851
|
+
IsPhoneNumber: 'must be a valid phone number',
|
|
852
|
+
IsUrl: 'must be a valid URL',
|
|
853
|
+
IsHash: 'must be a valid hash',
|
|
854
|
+
// Comparison validators
|
|
855
|
+
Equals: 'must equal to {comparison}',
|
|
856
|
+
NotEquals: 'should not equal to {comparison}',
|
|
857
|
+
Contains: 'must contain {seed}',
|
|
858
|
+
IsIn: 'must be one of the following values: {possibleValues}',
|
|
859
|
+
IsNotIn: 'should not be one of the following values: {possibleValues}',
|
|
860
|
+
Gt: 'must be greater than {min}',
|
|
861
|
+
Gte: 'must be greater than or equal to {min}',
|
|
862
|
+
Lt: 'must be less than {max}',
|
|
863
|
+
Lte: 'must be less than or equal to {max}',
|
|
864
|
+
// Common errors
|
|
865
|
+
invalidParameter: 'invalid parameter {field}',
|
|
866
|
+
validationFailed: 'validation failed',
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
/**
|
|
870
|
+
* Enhanced validation error class
|
|
871
|
+
*/
|
|
872
|
+
class KoattyValidationError extends Error {
|
|
873
|
+
constructor(errors, message) {
|
|
874
|
+
const errorMessage = message || 'Validation failed';
|
|
875
|
+
super(errorMessage);
|
|
876
|
+
this.name = 'KoattyValidationError';
|
|
877
|
+
this.errors = errors;
|
|
878
|
+
this.statusCode = 400;
|
|
879
|
+
this.timestamp = new Date();
|
|
880
|
+
// Ensure correct prototype chain
|
|
881
|
+
Object.setPrototypeOf(this, KoattyValidationError.prototype);
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Get the first error message
|
|
885
|
+
*/
|
|
886
|
+
getFirstError() {
|
|
887
|
+
return this.errors[0];
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Get errors for a specific field
|
|
891
|
+
*/
|
|
892
|
+
getFieldErrors(field) {
|
|
893
|
+
return this.errors.filter(error => error.field === field);
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Convert to JSON format
|
|
897
|
+
*/
|
|
898
|
+
toJSON() {
|
|
899
|
+
return {
|
|
900
|
+
name: this.name,
|
|
901
|
+
message: this.message,
|
|
902
|
+
statusCode: this.statusCode,
|
|
903
|
+
timestamp: this.timestamp,
|
|
904
|
+
errors: this.errors
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Error message formatter
|
|
910
|
+
*/
|
|
911
|
+
class ErrorMessageFormatter {
|
|
912
|
+
constructor(language = 'zh') {
|
|
913
|
+
this.language = 'zh';
|
|
914
|
+
this.language = language;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Set language
|
|
918
|
+
*/
|
|
919
|
+
setLanguage(language) {
|
|
920
|
+
this.language = language;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Format error message
|
|
924
|
+
*/
|
|
925
|
+
formatMessage(constraint, field, value, context) {
|
|
926
|
+
const messages = ERROR_MESSAGES[this.language];
|
|
927
|
+
let template = messages[constraint] || messages.invalidParameter;
|
|
928
|
+
// Replace placeholders
|
|
929
|
+
template = template.replace('{field}', field);
|
|
930
|
+
// Prioritize values from context, then use passed value
|
|
931
|
+
if (context) {
|
|
932
|
+
Object.entries(context).forEach(([key, val]) => {
|
|
933
|
+
template = template.replace(`{${key}}`, this.formatValue(val));
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
// If there's still a {value} placeholder and value was passed, replace it
|
|
937
|
+
if (value !== undefined && template.includes('{value}')) {
|
|
938
|
+
template = template.replace('{value}', this.formatValue(value));
|
|
939
|
+
}
|
|
940
|
+
return template;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Format value for message display
|
|
944
|
+
* @private
|
|
945
|
+
*/
|
|
946
|
+
formatValue(value) {
|
|
947
|
+
if (value === null)
|
|
948
|
+
return 'null';
|
|
949
|
+
if (value === undefined)
|
|
950
|
+
return 'undefined';
|
|
951
|
+
if (typeof value === 'number')
|
|
952
|
+
return String(value);
|
|
953
|
+
if (typeof value === 'string')
|
|
954
|
+
return `"${value}"`;
|
|
955
|
+
if (Array.isArray(value))
|
|
956
|
+
return `[${value.map(v => this.formatValue(v)).join(', ')}]`;
|
|
957
|
+
if (typeof value === 'object') {
|
|
958
|
+
try {
|
|
959
|
+
return JSON.stringify(value);
|
|
960
|
+
}
|
|
961
|
+
catch {
|
|
962
|
+
// Handle circular references
|
|
963
|
+
return '[Circular Reference]';
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return String(value);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Global error message formatter instance
|
|
971
|
+
*/
|
|
972
|
+
const errorFormatter = new ErrorMessageFormatter();
|
|
973
|
+
/**
|
|
974
|
+
* Set global language
|
|
975
|
+
*/
|
|
976
|
+
function setValidationLanguage(language) {
|
|
977
|
+
errorFormatter.setLanguage(language);
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Create validation error
|
|
981
|
+
*/
|
|
982
|
+
function createValidationError(field, value, constraint, customMessage, context) {
|
|
983
|
+
const message = customMessage || errorFormatter.formatMessage(constraint, field, value, context);
|
|
984
|
+
return {
|
|
985
|
+
field,
|
|
986
|
+
value,
|
|
987
|
+
constraint,
|
|
988
|
+
message,
|
|
989
|
+
context
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Create validation errors in batch
|
|
994
|
+
*/
|
|
995
|
+
function createValidationErrors(errors, separator = '; ') {
|
|
996
|
+
const validationErrors = errors.map(error => createValidationError(error.field, error.value, error.constraint, error.message, error.context));
|
|
997
|
+
// Generate combined message from all errors
|
|
998
|
+
const combinedMessage = validationErrors
|
|
999
|
+
.map(err => err.message)
|
|
1000
|
+
.filter(msg => msg && msg.trim())
|
|
1001
|
+
.join(separator) || 'Validation failed';
|
|
1002
|
+
return new KoattyValidationError(validationErrors, combinedMessage);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
802
1005
|
/*
|
|
803
1006
|
* @Description:
|
|
804
1007
|
* @Usage:
|
|
@@ -858,10 +1061,11 @@ class ValidateClass {
|
|
|
858
1061
|
* @param {*} Clazz
|
|
859
1062
|
* @param {*} data
|
|
860
1063
|
* @param {boolean} [convert=false] auto convert parameters type
|
|
1064
|
+
* @param {ValidationOptions} [options] validation options (returnAllErrors, errorSeparator)
|
|
861
1065
|
* @returns {Promise<any>}
|
|
862
1066
|
* @memberof ValidateClass
|
|
863
1067
|
*/
|
|
864
|
-
async valid(Clazz, data, convert = false) {
|
|
1068
|
+
async valid(Clazz, data, convert = false, options) {
|
|
865
1069
|
let obj = {};
|
|
866
1070
|
if (data instanceof Clazz) {
|
|
867
1071
|
obj = data;
|
|
@@ -877,7 +1081,21 @@ class ValidateClass {
|
|
|
877
1081
|
errors = await validate(obj, { skipMissingProperties: true });
|
|
878
1082
|
}
|
|
879
1083
|
if (errors.length > 0) {
|
|
880
|
-
|
|
1084
|
+
// Check if user wants all errors or just the first one
|
|
1085
|
+
if (options === null || options === void 0 ? void 0 : options.returnAllErrors) {
|
|
1086
|
+
// Throw KoattyValidationError with all error details
|
|
1087
|
+
throw createValidationErrors(errors.map(e => ({
|
|
1088
|
+
field: e.property,
|
|
1089
|
+
value: e.value,
|
|
1090
|
+
constraint: Object.keys(e.constraints || {})[0] || 'unknown',
|
|
1091
|
+
message: Object.values(e.constraints || {})[0] || 'Validation failed',
|
|
1092
|
+
context: e.constraints
|
|
1093
|
+
})), options.errorSeparator || '; ');
|
|
1094
|
+
}
|
|
1095
|
+
else {
|
|
1096
|
+
// Default behavior (backward compatible): return only first error
|
|
1097
|
+
throw new Error(Object.values(errors[0].constraints)[0]);
|
|
1098
|
+
}
|
|
881
1099
|
}
|
|
882
1100
|
return obj;
|
|
883
1101
|
}
|
|
@@ -1149,8 +1367,9 @@ function createValidationDecorator(options) {
|
|
|
1149
1367
|
},
|
|
1150
1368
|
defaultMessage(validationArguments) {
|
|
1151
1369
|
const property = validationArguments.property;
|
|
1152
|
-
|
|
1153
|
-
|
|
1370
|
+
const customMessage = (validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.message) || defaultMessage;
|
|
1371
|
+
return customMessage
|
|
1372
|
+
? customMessage.replace('$property', property)
|
|
1154
1373
|
: `Invalid value for ${property}`;
|
|
1155
1374
|
}
|
|
1156
1375
|
}
|
|
@@ -1189,204 +1408,6 @@ function createParameterizedDecorator(name, validator, defaultMessage) {
|
|
|
1189
1408
|
});
|
|
1190
1409
|
}
|
|
1191
1410
|
|
|
1192
|
-
/**
|
|
1193
|
-
* Improved error handling mechanism
|
|
1194
|
-
* @author richen
|
|
1195
|
-
*/
|
|
1196
|
-
/**
|
|
1197
|
-
* Error message internationalization
|
|
1198
|
-
*/
|
|
1199
|
-
const ERROR_MESSAGES = {
|
|
1200
|
-
zh: {
|
|
1201
|
-
// Chinese localization validation
|
|
1202
|
-
IsCnName: '必须是有效的中文姓名',
|
|
1203
|
-
IsIdNumber: '必须是有效的身份证号码',
|
|
1204
|
-
IsZipCode: '必须是有效的邮政编码',
|
|
1205
|
-
IsMobile: '必须是有效的手机号码',
|
|
1206
|
-
IsPlateNumber: '必须是有效的车牌号码',
|
|
1207
|
-
// Basic validation
|
|
1208
|
-
IsNotEmpty: '不能为空',
|
|
1209
|
-
IsDate: '必须是有效的日期',
|
|
1210
|
-
IsEmail: '必须是有效的邮箱地址',
|
|
1211
|
-
IsIP: '必须是有效的IP地址',
|
|
1212
|
-
IsPhoneNumber: '必须是有效的电话号码',
|
|
1213
|
-
IsUrl: '必须是有效的URL地址',
|
|
1214
|
-
IsHash: '必须是有效的哈希值',
|
|
1215
|
-
// Comparison validation
|
|
1216
|
-
Equals: '必须等于 {comparison}',
|
|
1217
|
-
NotEquals: '不能等于 {comparison}',
|
|
1218
|
-
Contains: '必须包含 {seed}',
|
|
1219
|
-
IsIn: '必须是以下值之一: {possibleValues}',
|
|
1220
|
-
IsNotIn: '不能是以下值之一: {possibleValues}',
|
|
1221
|
-
Gt: '必须大于 {min}',
|
|
1222
|
-
Gte: '必须大于或等于 {min}',
|
|
1223
|
-
Lt: '必须小于 {max}',
|
|
1224
|
-
Lte: '必须小于或等于 {max}',
|
|
1225
|
-
// Common errors
|
|
1226
|
-
invalidParameter: '参数 {field} 无效',
|
|
1227
|
-
validationFailed: '验证失败',
|
|
1228
|
-
},
|
|
1229
|
-
en: {
|
|
1230
|
-
// Chinese localization validators
|
|
1231
|
-
IsCnName: 'must be a valid Chinese name',
|
|
1232
|
-
IsIdNumber: 'must be a valid ID number',
|
|
1233
|
-
IsZipCode: 'must be a valid zip code',
|
|
1234
|
-
IsMobile: 'must be a valid mobile number',
|
|
1235
|
-
IsPlateNumber: 'must be a valid plate number',
|
|
1236
|
-
// Basic validators
|
|
1237
|
-
IsNotEmpty: 'should not be empty',
|
|
1238
|
-
IsDate: 'must be a valid date',
|
|
1239
|
-
IsEmail: 'must be a valid email',
|
|
1240
|
-
IsIP: 'must be a valid IP address',
|
|
1241
|
-
IsPhoneNumber: 'must be a valid phone number',
|
|
1242
|
-
IsUrl: 'must be a valid URL',
|
|
1243
|
-
IsHash: 'must be a valid hash',
|
|
1244
|
-
// Comparison validators
|
|
1245
|
-
Equals: 'must equal to {comparison}',
|
|
1246
|
-
NotEquals: 'should not equal to {comparison}',
|
|
1247
|
-
Contains: 'must contain {seed}',
|
|
1248
|
-
IsIn: 'must be one of the following values: {possibleValues}',
|
|
1249
|
-
IsNotIn: 'should not be one of the following values: {possibleValues}',
|
|
1250
|
-
Gt: 'must be greater than {min}',
|
|
1251
|
-
Gte: 'must be greater than or equal to {min}',
|
|
1252
|
-
Lt: 'must be less than {max}',
|
|
1253
|
-
Lte: 'must be less than or equal to {max}',
|
|
1254
|
-
// Common errors
|
|
1255
|
-
invalidParameter: 'invalid parameter {field}',
|
|
1256
|
-
validationFailed: 'validation failed',
|
|
1257
|
-
}
|
|
1258
|
-
};
|
|
1259
|
-
/**
|
|
1260
|
-
* Enhanced validation error class
|
|
1261
|
-
*/
|
|
1262
|
-
class KoattyValidationError extends Error {
|
|
1263
|
-
constructor(errors, message) {
|
|
1264
|
-
const errorMessage = message || 'Validation failed';
|
|
1265
|
-
super(errorMessage);
|
|
1266
|
-
this.name = 'KoattyValidationError';
|
|
1267
|
-
this.errors = errors;
|
|
1268
|
-
this.statusCode = 400;
|
|
1269
|
-
this.timestamp = new Date();
|
|
1270
|
-
// Ensure correct prototype chain
|
|
1271
|
-
Object.setPrototypeOf(this, KoattyValidationError.prototype);
|
|
1272
|
-
}
|
|
1273
|
-
/**
|
|
1274
|
-
* Get the first error message
|
|
1275
|
-
*/
|
|
1276
|
-
getFirstError() {
|
|
1277
|
-
return this.errors[0];
|
|
1278
|
-
}
|
|
1279
|
-
/**
|
|
1280
|
-
* Get errors for a specific field
|
|
1281
|
-
*/
|
|
1282
|
-
getFieldErrors(field) {
|
|
1283
|
-
return this.errors.filter(error => error.field === field);
|
|
1284
|
-
}
|
|
1285
|
-
/**
|
|
1286
|
-
* Convert to JSON format
|
|
1287
|
-
*/
|
|
1288
|
-
toJSON() {
|
|
1289
|
-
return {
|
|
1290
|
-
name: this.name,
|
|
1291
|
-
message: this.message,
|
|
1292
|
-
statusCode: this.statusCode,
|
|
1293
|
-
timestamp: this.timestamp,
|
|
1294
|
-
errors: this.errors
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
/**
|
|
1299
|
-
* Error message formatter
|
|
1300
|
-
*/
|
|
1301
|
-
class ErrorMessageFormatter {
|
|
1302
|
-
constructor(language = 'zh') {
|
|
1303
|
-
this.language = 'zh';
|
|
1304
|
-
this.language = language;
|
|
1305
|
-
}
|
|
1306
|
-
/**
|
|
1307
|
-
* Set language
|
|
1308
|
-
*/
|
|
1309
|
-
setLanguage(language) {
|
|
1310
|
-
this.language = language;
|
|
1311
|
-
}
|
|
1312
|
-
/**
|
|
1313
|
-
* Format error message
|
|
1314
|
-
*/
|
|
1315
|
-
formatMessage(constraint, field, value, context) {
|
|
1316
|
-
const messages = ERROR_MESSAGES[this.language];
|
|
1317
|
-
let template = messages[constraint] || messages.invalidParameter;
|
|
1318
|
-
// Replace placeholders
|
|
1319
|
-
template = template.replace('{field}', field);
|
|
1320
|
-
// Prioritize values from context, then use passed value
|
|
1321
|
-
if (context) {
|
|
1322
|
-
Object.entries(context).forEach(([key, val]) => {
|
|
1323
|
-
template = template.replace(`{${key}}`, this.formatValue(val));
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
// If there's still a {value} placeholder and value was passed, replace it
|
|
1327
|
-
if (value !== undefined && template.includes('{value}')) {
|
|
1328
|
-
template = template.replace('{value}', this.formatValue(value));
|
|
1329
|
-
}
|
|
1330
|
-
return template;
|
|
1331
|
-
}
|
|
1332
|
-
/**
|
|
1333
|
-
* Format value for message display
|
|
1334
|
-
* @private
|
|
1335
|
-
*/
|
|
1336
|
-
formatValue(value) {
|
|
1337
|
-
if (value === null)
|
|
1338
|
-
return 'null';
|
|
1339
|
-
if (value === undefined)
|
|
1340
|
-
return 'undefined';
|
|
1341
|
-
if (typeof value === 'number')
|
|
1342
|
-
return String(value);
|
|
1343
|
-
if (typeof value === 'string')
|
|
1344
|
-
return `"${value}"`;
|
|
1345
|
-
if (Array.isArray(value))
|
|
1346
|
-
return `[${value.map(v => this.formatValue(v)).join(', ')}]`;
|
|
1347
|
-
if (typeof value === 'object') {
|
|
1348
|
-
try {
|
|
1349
|
-
return JSON.stringify(value);
|
|
1350
|
-
}
|
|
1351
|
-
catch {
|
|
1352
|
-
// Handle circular references
|
|
1353
|
-
return '[Circular Reference]';
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
return String(value);
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
/**
|
|
1360
|
-
* Global error message formatter instance
|
|
1361
|
-
*/
|
|
1362
|
-
const errorFormatter = new ErrorMessageFormatter();
|
|
1363
|
-
/**
|
|
1364
|
-
* Set global language
|
|
1365
|
-
*/
|
|
1366
|
-
function setValidationLanguage(language) {
|
|
1367
|
-
errorFormatter.setLanguage(language);
|
|
1368
|
-
}
|
|
1369
|
-
/**
|
|
1370
|
-
* Create validation error
|
|
1371
|
-
*/
|
|
1372
|
-
function createValidationError(field, value, constraint, customMessage, context) {
|
|
1373
|
-
const message = customMessage || errorFormatter.formatMessage(constraint, field, value, context);
|
|
1374
|
-
return {
|
|
1375
|
-
field,
|
|
1376
|
-
value,
|
|
1377
|
-
constraint,
|
|
1378
|
-
message,
|
|
1379
|
-
context
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
/**
|
|
1383
|
-
* Create validation errors in batch
|
|
1384
|
-
*/
|
|
1385
|
-
function createValidationErrors(errors) {
|
|
1386
|
-
const validationErrors = errors.map(error => createValidationError(error.field, error.value, error.constraint, error.message, error.context));
|
|
1387
|
-
return new KoattyValidationError(validationErrors);
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
1411
|
/**
|
|
1391
1412
|
* Refactored decorator definitions - Using factory functions to eliminate duplication
|
|
1392
1413
|
* @author richen
|
|
@@ -1413,7 +1434,10 @@ const Lt = createParameterizedDecorator('Lt', (value, max) => helper.toNumber(va
|
|
|
1413
1434
|
const Lte = createParameterizedDecorator('Lte', (value, max) => helper.toNumber(value) <= max, 'must be less than or equal to $constraint1');
|
|
1414
1435
|
// 复杂验证装饰器(需要特殊处理)
|
|
1415
1436
|
function IsEmail(options, validationOptions) {
|
|
1416
|
-
|
|
1437
|
+
// Handle case where options is actually ValidationOptions (message only)
|
|
1438
|
+
const actualOptions = (options === null || options === void 0 ? void 0 : options.message) ? {} : options;
|
|
1439
|
+
const actualValidationOptions = (options === null || options === void 0 ? void 0 : options.message) ? options : validationOptions;
|
|
1440
|
+
return createParameterizedDecorator('IsEmail', (value) => isEmail(value, actualOptions), 'must be a valid email')(actualValidationOptions);
|
|
1417
1441
|
}
|
|
1418
1442
|
function IsIP(version, validationOptions) {
|
|
1419
1443
|
return createParameterizedDecorator('IsIP', (value) => isIP(value, version), 'must be a valid IP address')(validationOptions);
|
package/dist/package.json
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koatty_validation",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.6",
|
|
4
4
|
"description": "Validation Util for Koatty and ThinkORM.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
|
|
7
7
|
"build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
|
|
8
8
|
"build:js": "del-cli --force dist && npx rollup --bundleConfigAsCjs -c .rollup.config.js",
|
|
9
9
|
"build:doc": "del-cli --force docs/api && npx api-documenter markdown --input temp --output docs/api",
|
|
10
|
-
"build:dts": "
|
|
10
|
+
"build:dts": "bash ../../scripts/build-dts.sh",
|
|
11
11
|
"eslint": "eslint --ext .ts,.js ./",
|
|
12
12
|
"lock": "npm i --package-lock-only",
|
|
13
13
|
"prepublishOnly": "npm test && npm run build && git push --follow-tags origin",
|
|
14
14
|
"prerelease": "npm test && npm run build",
|
|
15
|
-
"release": "standard-version",
|
|
16
|
-
"release:pre": "npm run release -- --prerelease",
|
|
17
|
-
"release:major": "npm run release -- --release-as major",
|
|
18
|
-
"release:minor": "npm run release -- --release-as minor",
|
|
19
15
|
"test": "npm run eslint && jest --passWithNoTests"
|
|
20
16
|
},
|
|
21
17
|
"main": "./dist/index.js",
|
|
@@ -77,15 +73,15 @@
|
|
|
77
73
|
"typescript": "^5.x.x"
|
|
78
74
|
},
|
|
79
75
|
"dependencies": {
|
|
80
|
-
"class-validator": "^0.14.
|
|
81
|
-
"koatty_container": "^1.
|
|
82
|
-
"koatty_lib": "^1.
|
|
83
|
-
"koatty_logger": "^2.
|
|
84
|
-
"lru-cache": "^11.2.
|
|
76
|
+
"class-validator": "^0.14.3",
|
|
77
|
+
"koatty_container": "^1.17.4",
|
|
78
|
+
"koatty_lib": "^1.4.5",
|
|
79
|
+
"koatty_logger": "^2.3.4",
|
|
80
|
+
"lru-cache": "^11.2.5"
|
|
85
81
|
},
|
|
86
82
|
"peerDependencies": {
|
|
87
|
-
"koatty_container": "^1.
|
|
88
|
-
"koatty_lib": "^1.
|
|
89
|
-
"koatty_logger": "^2.
|
|
83
|
+
"koatty_container": "^1.17.4",
|
|
84
|
+
"koatty_lib": "^1.4.5",
|
|
85
|
+
"koatty_logger": "^2.3.4"
|
|
90
86
|
}
|
|
91
87
|
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koatty_validation",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.6",
|
|
4
4
|
"description": "Validation Util for Koatty and ThinkORM.",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
|
|
7
|
-
"build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
|
|
8
|
-
"build:js": "del-cli --force dist && npx rollup --bundleConfigAsCjs -c .rollup.config.js",
|
|
9
|
-
"build:doc": "del-cli --force docs/api && npx api-documenter markdown --input temp --output docs/api",
|
|
10
|
-
"build:dts": "del-cli --force temp && npx tsc && npx api-extractor run --local --verbose",
|
|
11
|
-
"eslint": "eslint --ext .ts,.js ./",
|
|
12
|
-
"lock": "npm i --package-lock-only",
|
|
13
|
-
"prepublishOnly": "npm test && npm run build && git push --follow-tags origin",
|
|
14
|
-
"prerelease": "npm test && npm run build",
|
|
15
|
-
"release": "standard-version",
|
|
16
|
-
"release:pre": "npm run release -- --prerelease",
|
|
17
|
-
"release:major": "npm run release -- --release-as major",
|
|
18
|
-
"release:minor": "npm run release -- --release-as minor",
|
|
19
|
-
"test": "npm run eslint && jest --passWithNoTests"
|
|
20
|
-
},
|
|
21
5
|
"main": "./dist/index.js",
|
|
22
6
|
"exports": {
|
|
23
7
|
"require": "./dist/index.js",
|
|
@@ -77,15 +61,26 @@
|
|
|
77
61
|
"typescript": "^5.x.x"
|
|
78
62
|
},
|
|
79
63
|
"dependencies": {
|
|
80
|
-
"class-validator": "^0.14.
|
|
81
|
-
"koatty_container": "^1.
|
|
82
|
-
"koatty_lib": "^1.
|
|
83
|
-
"koatty_logger": "^2.
|
|
84
|
-
"lru-cache": "^11.2.
|
|
64
|
+
"class-validator": "^0.14.3",
|
|
65
|
+
"koatty_container": "^1.17.4",
|
|
66
|
+
"koatty_lib": "^1.4.5",
|
|
67
|
+
"koatty_logger": "^2.3.4",
|
|
68
|
+
"lru-cache": "^11.2.5"
|
|
85
69
|
},
|
|
86
70
|
"peerDependencies": {
|
|
87
|
-
"koatty_container": "^1.
|
|
88
|
-
"koatty_lib": "^1.
|
|
89
|
-
"koatty_logger": "^2.
|
|
71
|
+
"koatty_container": "^1.17.4",
|
|
72
|
+
"koatty_lib": "^1.4.5",
|
|
73
|
+
"koatty_logger": "^2.3.4"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
|
|
77
|
+
"build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
|
|
78
|
+
"build:js": "del-cli --force dist && npx rollup --bundleConfigAsCjs -c .rollup.config.js",
|
|
79
|
+
"build:doc": "del-cli --force docs/api && npx api-documenter markdown --input temp --output docs/api",
|
|
80
|
+
"build:dts": "bash ../../scripts/build-dts.sh",
|
|
81
|
+
"eslint": "eslint --ext .ts,.js ./",
|
|
82
|
+
"lock": "npm i --package-lock-only",
|
|
83
|
+
"prerelease": "npm test && npm run build",
|
|
84
|
+
"test": "npm run eslint && jest --passWithNoTests"
|
|
90
85
|
}
|
|
91
|
-
}
|
|
86
|
+
}
|