@oxog/vld 1.2.0 → 1.3.1
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/CHANGELOG.md +73 -0
- package/README.md +1128 -1111
- package/dist/coercion/boolean.d.ts.map +1 -1
- package/dist/coercion/boolean.js +6 -2
- package/dist/coercion/boolean.js.map +1 -1
- package/dist/coercion/string.d.ts.map +1 -1
- package/dist/coercion/string.js +146 -10
- package/dist/coercion/string.js.map +1 -1
- package/dist/locales/af.js +3 -3
- package/dist/locales/af.js.map +1 -1
- package/dist/locales/ar.js +3 -3
- package/dist/locales/ar.js.map +1 -1
- package/dist/locales/bn.js +3 -3
- package/dist/locales/bn.js.map +1 -1
- package/dist/locales/da.js +3 -3
- package/dist/locales/da.js.map +1 -1
- package/dist/locales/de.js +3 -3
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.js +3 -3
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es-MX.js +3 -3
- package/dist/locales/es-MX.js.map +1 -1
- package/dist/locales/es.js +3 -3
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fi.js +3 -3
- package/dist/locales/fi.js.map +1 -1
- package/dist/locales/fr.js +3 -3
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/hi.js +3 -3
- package/dist/locales/hi.js.map +1 -1
- package/dist/locales/id.js +3 -3
- package/dist/locales/id.js.map +1 -1
- package/dist/locales/it.js +3 -3
- package/dist/locales/it.js.map +1 -1
- package/dist/locales/ja.js +3 -3
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +3 -3
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/nl.js +3 -3
- package/dist/locales/nl.js.map +1 -1
- package/dist/locales/no.js +3 -3
- package/dist/locales/no.js.map +1 -1
- package/dist/locales/pl.js +3 -3
- package/dist/locales/pl.js.map +1 -1
- package/dist/locales/pt-BR.js +3 -3
- package/dist/locales/pt-BR.js.map +1 -1
- package/dist/locales/pt.js +3 -3
- package/dist/locales/pt.js.map +1 -1
- package/dist/locales/ru.js +3 -3
- package/dist/locales/ru.js.map +1 -1
- package/dist/locales/sv.js +3 -3
- package/dist/locales/sv.js.map +1 -1
- package/dist/locales/sw.js +3 -3
- package/dist/locales/sw.js.map +1 -1
- package/dist/locales/th.js +3 -3
- package/dist/locales/th.js.map +1 -1
- package/dist/locales/tr.js +3 -3
- package/dist/locales/tr.js.map +1 -1
- package/dist/locales/types.d.ts +3 -3
- package/dist/locales/types.d.ts.map +1 -1
- package/dist/locales/types.js.map +1 -1
- package/dist/locales/vi.js +3 -3
- package/dist/locales/vi.js.map +1 -1
- package/dist/locales/zh.js +3 -3
- package/dist/locales/zh.js.map +1 -1
- package/dist/utils/codec-utils.d.ts +1 -1
- package/dist/utils/codec-utils.d.ts.map +1 -1
- package/dist/utils/codec-utils.js +92 -5
- package/dist/utils/codec-utils.js.map +1 -1
- package/dist/utils/deep-merge.d.ts +1 -0
- package/dist/utils/deep-merge.d.ts.map +1 -1
- package/dist/utils/deep-merge.js +33 -8
- package/dist/utils/deep-merge.js.map +1 -1
- package/dist/validators/array.d.ts +5 -0
- package/dist/validators/array.d.ts.map +1 -1
- package/dist/validators/array.js +30 -1
- package/dist/validators/array.js.map +1 -1
- package/dist/validators/base64.d.ts.map +1 -1
- package/dist/validators/base64.js +5 -2
- package/dist/validators/base64.js.map +1 -1
- package/dist/validators/date.d.ts +5 -1
- package/dist/validators/date.d.ts.map +1 -1
- package/dist/validators/date.js +53 -29
- package/dist/validators/date.js.map +1 -1
- package/dist/validators/number.d.ts.map +1 -1
- package/dist/validators/number.js +16 -3
- package/dist/validators/number.js.map +1 -1
- package/dist/validators/object.d.ts +5 -0
- package/dist/validators/object.d.ts.map +1 -1
- package/dist/validators/object.js +58 -6
- package/dist/validators/object.js.map +1 -1
- package/dist/validators/record.d.ts.map +1 -1
- package/dist/validators/record.js +6 -0
- package/dist/validators/record.js.map +1 -1
- package/dist/validators/string.d.ts.map +1 -1
- package/dist/validators/string.js +86 -4
- package/dist/validators/string.js.map +1 -1
- package/dist/validators/uint8array.js +3 -3
- package/dist/validators/uint8array.js.map +1 -1
- package/dist/validators/union.d.ts +1 -0
- package/dist/validators/union.d.ts.map +1 -1
- package/dist/validators/union.js +31 -20
- package/dist/validators/union.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/validators/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAe9C;;GAEG;AACH,qBAAa,QAAQ,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IAEjD;;OAEG;IACH,OAAO;IAKP;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAIjE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE;IA6C1B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC;IAQ3C;;OAEG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQlD;;OAEG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQlD;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAUrD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQvC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQrC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;CAQjE"}
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/validators/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAe9C;;GAEG;AACH,qBAAa,QAAQ,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IAEjD;;OAEG;IACH,OAAO;IAKP;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAIjE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE;IA6C1B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC;IAQ3C;;;OAGG;IACH,OAAO,CAAC,eAAe;IA2BvB;;OAEG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQlD;;OAEG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQlD;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAUrD;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQvC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAQrC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;CAQjE"}
|
package/dist/validators/array.js
CHANGED
|
@@ -48,7 +48,7 @@ export class VldArray extends VldBase {
|
|
|
48
48
|
if (this.config.unique) {
|
|
49
49
|
const seen = new Set();
|
|
50
50
|
for (const item of result) {
|
|
51
|
-
const key = typeof item === 'object' ?
|
|
51
|
+
const key = typeof item === 'object' ? this.stableStringify(item) : item;
|
|
52
52
|
if (seen.has(key)) {
|
|
53
53
|
throw new Error('Array must contain unique items');
|
|
54
54
|
}
|
|
@@ -68,6 +68,35 @@ export class VldArray extends VldBase {
|
|
|
68
68
|
return { success: false, error: error };
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a stable string representation of an object for hashing
|
|
73
|
+
* Handles circular references gracefully
|
|
74
|
+
*/
|
|
75
|
+
stableStringify(obj) {
|
|
76
|
+
const seen = new WeakSet();
|
|
77
|
+
const replacer = (_key, value) => {
|
|
78
|
+
if (typeof value === 'object' && value !== null) {
|
|
79
|
+
if (seen.has(value)) {
|
|
80
|
+
return '[Circular]';
|
|
81
|
+
}
|
|
82
|
+
seen.add(value);
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
};
|
|
86
|
+
try {
|
|
87
|
+
const allKeys = [];
|
|
88
|
+
JSON.stringify(obj, (key, value) => {
|
|
89
|
+
allKeys.push(key);
|
|
90
|
+
return replacer(key, value);
|
|
91
|
+
});
|
|
92
|
+
allKeys.sort();
|
|
93
|
+
return JSON.stringify(obj, (_key, value) => replacer(_key, value));
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
// Fallback to safe representation if stringify fails
|
|
97
|
+
return String(obj);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
71
100
|
/**
|
|
72
101
|
* Create a new validator with minimum length constraint
|
|
73
102
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../src/validators/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAczC;;GAEG;AACH,MAAM,OAAO,QAAY,SAAQ,OAAuB;IAGtD;;OAEG;IACH,YAAoB,MAA+B;QACjD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAI,aAAkC;QACjD,OAAO,IAAI,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAc;QAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,YAAY,CAAC,CAAC;QAC1E,CAAC;QAED,8BAA8B;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACtF,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAClG,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAChF,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7F,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAChF,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7F,CAAC;QAED,uDAAuD;QACvD,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YACzE,CAAC;YACD,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,wCAAwC;QACxE,CAAC;QAED,+BAA+B;QAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAO,CAAC;YAC5B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBACrD,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,KAAc;QACtB,IAAI,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,MAAc,EAAE,OAAgB;QAClC,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,SAAS,EAAE,MAAM;YACjB,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,MAAc,EAAE,OAAgB;QAClC,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,SAAS,EAAE,MAAM;YACjB,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAc,EAAE,OAAgB;QACrC,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,WAAW,EAAE,MAAM;YACnB,SAAS,EAAE,SAAS;YACpB,SAAS,EAAE,SAAS;YACpB,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,OAAgB;QACvB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,SAAS,EAAE,CAAC;YACZ,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,UAAU;SAClD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAgB;QACrB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,MAAM,EAAE,IAAI;YACZ,YAAY,EAAE,OAAO,IAAI,iCAAiC;SAC3D,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,GAAW,EAAE,GAAW,EAAE,OAAgB;QAChD,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,IAAI,CAAC,MAAM;YACd,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;YACd,YAAY,EAAE,OAAO,IAAI,gCAAgC,GAAG,QAAQ,GAAG,EAAE;SAC1E,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { VldBase, ParseResult } from './base';\nimport { getMessages } from '../locales';\n\n/**\n * Configuration for array validator\n */\ninterface ArrayValidatorConfig<T> {\n readonly itemValidator: VldBase<unknown, T>;\n readonly minLength?: number;\n readonly maxLength?: number;\n readonly exactLength?: number;\n readonly unique?: boolean;\n readonly errorMessage?: string;\n}\n\n/**\n * Immutable array validator with chainable methods\n */\nexport class VldArray<T> extends VldBase<unknown[], T[]> {\n private readonly config: ArrayValidatorConfig<T>;\n \n /**\n * Private constructor to enforce immutability\n */\n private constructor(config: ArrayValidatorConfig<T>) {\n super();\n this.config = config;\n }\n \n /**\n * Create a new array validator\n */\n static create<T>(itemValidator: VldBase<unknown, T>): VldArray<T> {\n return new VldArray({ itemValidator });\n }\n \n /**\n * Parse and validate an array value\n */\n parse(value: unknown): T[] {\n if (!Array.isArray(value)) {\n throw new Error(this.config.errorMessage || getMessages().invalidArray);\n }\n \n // Validate length constraints\n if (this.config.exactLength !== undefined && value.length !== this.config.exactLength) {\n throw new Error(this.config.errorMessage || getMessages().arrayLength(this.config.exactLength));\n }\n \n if (this.config.minLength !== undefined && value.length < this.config.minLength) {\n throw new Error(this.config.errorMessage || getMessages().arrayMin(this.config.minLength));\n }\n \n if (this.config.maxLength !== undefined && value.length > this.config.maxLength) {\n throw new Error(this.config.errorMessage || getMessages().arrayMax(this.config.maxLength));\n }\n \n // Validate each item with optimized loop and safeParse\n const result: T[] = [];\n const length = value.length;\n \n for (let i = 0; i < length; i++) {\n const parseResult = this.config.itemValidator.safeParse(value[i]);\n if (!parseResult.success) {\n throw new Error(getMessages().arrayItem(i, parseResult.error.message));\n }\n result[i] = parseResult.data; // Direct assignment is faster than push\n }\n \n // Check uniqueness if required\n if (this.config.unique) {\n const seen = new Set<any>();\n for (const item of result) {\n const key = typeof item === 'object' ? JSON.stringify(item) : item;\n if (seen.has(key)) {\n throw new Error('Array must contain unique items');\n }\n seen.add(key);\n }\n }\n \n return result;\n }\n \n /**\n * Safely parse and validate an array value\n */\n safeParse(value: unknown): ParseResult<T[]> {\n try {\n return { success: true, data: this.parse(value) };\n } catch (error) {\n return { success: false, error: error as Error };\n }\n }\n \n /**\n * Create a new validator with minimum length constraint\n */\n min(length: number, message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n minLength: length,\n errorMessage: message || getMessages().arrayMin(length)\n });\n }\n \n /**\n * Create a new validator with maximum length constraint\n */\n max(length: number, message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n maxLength: length,\n errorMessage: message || getMessages().arrayMax(length)\n });\n }\n \n /**\n * Create a new validator with exact length constraint\n */\n length(length: number, message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n exactLength: length,\n minLength: undefined,\n maxLength: undefined,\n errorMessage: message || getMessages().arrayLength(length)\n });\n }\n \n /**\n * Create a new validator that ensures array is not empty\n */\n nonempty(message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n minLength: 1,\n errorMessage: message || getMessages().arrayEmpty\n });\n }\n \n /**\n * Create a new validator that ensures array contains unique items\n */\n unique(message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n unique: true,\n errorMessage: message || 'Array must contain unique items'\n });\n }\n \n /**\n * Create a new validator with a range constraint for length\n */\n between(min: number, max: number, message?: string): VldArray<T> {\n return new VldArray({\n ...this.config,\n minLength: min,\n maxLength: max,\n errorMessage: message || `Array length must be between ${min} and ${max}`\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../src/validators/array.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\r\nimport { getMessages } from '../locales';\r\n\r\n/**\r\n * Configuration for array validator\r\n */\r\ninterface ArrayValidatorConfig<T> {\r\n readonly itemValidator: VldBase<unknown, T>;\r\n readonly minLength?: number;\r\n readonly maxLength?: number;\r\n readonly exactLength?: number;\r\n readonly unique?: boolean;\r\n readonly errorMessage?: string;\r\n}\r\n\r\n/**\r\n * Immutable array validator with chainable methods\r\n */\r\nexport class VldArray<T> extends VldBase<unknown[], T[]> {\r\n private readonly config: ArrayValidatorConfig<T>;\r\n \r\n /**\r\n * Private constructor to enforce immutability\r\n */\r\n private constructor(config: ArrayValidatorConfig<T>) {\r\n super();\r\n this.config = config;\r\n }\r\n \r\n /**\r\n * Create a new array validator\r\n */\r\n static create<T>(itemValidator: VldBase<unknown, T>): VldArray<T> {\r\n return new VldArray({ itemValidator });\r\n }\r\n \r\n /**\r\n * Parse and validate an array value\r\n */\r\n parse(value: unknown): T[] {\r\n if (!Array.isArray(value)) {\r\n throw new Error(this.config.errorMessage || getMessages().invalidArray);\r\n }\r\n \r\n // Validate length constraints\r\n if (this.config.exactLength !== undefined && value.length !== this.config.exactLength) {\r\n throw new Error(this.config.errorMessage || getMessages().arrayLength(this.config.exactLength));\r\n }\r\n \r\n if (this.config.minLength !== undefined && value.length < this.config.minLength) {\r\n throw new Error(this.config.errorMessage || getMessages().arrayMin(this.config.minLength));\r\n }\r\n \r\n if (this.config.maxLength !== undefined && value.length > this.config.maxLength) {\r\n throw new Error(this.config.errorMessage || getMessages().arrayMax(this.config.maxLength));\r\n }\r\n \r\n // Validate each item with optimized loop and safeParse\r\n const result: T[] = [];\r\n const length = value.length;\r\n \r\n for (let i = 0; i < length; i++) {\r\n const parseResult = this.config.itemValidator.safeParse(value[i]);\r\n if (!parseResult.success) {\r\n throw new Error(getMessages().arrayItem(i, parseResult.error.message));\r\n }\r\n result[i] = parseResult.data; // Direct assignment is faster than push\r\n }\r\n \r\n // Check uniqueness if required\r\n if (this.config.unique) {\r\n const seen = new Set<any>();\r\n for (const item of result) {\r\n const key = typeof item === 'object' ? this.stableStringify(item) : item;\r\n if (seen.has(key)) {\r\n throw new Error('Array must contain unique items');\r\n }\r\n seen.add(key);\r\n }\r\n }\r\n \r\n return result;\r\n }\r\n \r\n /**\r\n * Safely parse and validate an array value\r\n */\r\n safeParse(value: unknown): ParseResult<T[]> {\r\n try {\r\n return { success: true, data: this.parse(value) };\r\n } catch (error) {\r\n return { success: false, error: error as Error };\r\n }\r\n }\r\n\r\n /**\r\n * Create a stable string representation of an object for hashing\r\n * Handles circular references gracefully\r\n */\r\n private stableStringify(obj: any): string {\r\n const seen = new WeakSet();\r\n\r\n const replacer = (_key: string, value: any): any => {\r\n if (typeof value === 'object' && value !== null) {\r\n if (seen.has(value)) {\r\n return '[Circular]';\r\n }\r\n seen.add(value);\r\n }\r\n return value;\r\n };\r\n\r\n try {\r\n const allKeys: string[] = [];\r\n JSON.stringify(obj, (key, value) => {\r\n allKeys.push(key);\r\n return replacer(key, value);\r\n });\r\n allKeys.sort();\r\n return JSON.stringify(obj, (_key, value) => replacer(_key, value));\r\n } catch (error) {\r\n // Fallback to safe representation if stringify fails\r\n return String(obj);\r\n }\r\n }\r\n \r\n /**\r\n * Create a new validator with minimum length constraint\r\n */\r\n min(length: number, message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n minLength: length,\r\n errorMessage: message || getMessages().arrayMin(length)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator with maximum length constraint\r\n */\r\n max(length: number, message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n maxLength: length,\r\n errorMessage: message || getMessages().arrayMax(length)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator with exact length constraint\r\n */\r\n length(length: number, message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n exactLength: length,\r\n minLength: undefined,\r\n maxLength: undefined,\r\n errorMessage: message || getMessages().arrayLength(length)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that ensures array is not empty\r\n */\r\n nonempty(message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n minLength: 1,\r\n errorMessage: message || getMessages().arrayEmpty\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that ensures array contains unique items\r\n */\r\n unique(message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n unique: true,\r\n errorMessage: message || 'Array must contain unique items'\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator with a range constraint for length\r\n */\r\n between(min: number, max: number, message?: string): VldArray<T> {\r\n return new VldArray({\r\n ...this.config,\r\n minLength: min,\r\n maxLength: max,\r\n errorMessage: message || `Array length must be between ${min} and ${max}`\r\n });\r\n }\r\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../../src/validators/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAI9C;;GAEG;AACH,qBAAa,SAAU,SAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAA4B;
|
|
1
|
+
{"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../../src/validators/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAI9C;;GAEG;AACH,qBAAa,SAAU,SAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAA4B;IAEhE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAEpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,OAAO,UAAQ;IAK3B,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAQ7B,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC;IAsC9C;;OAEG;IACH,WAAW,IAAI,SAAS;IAIxB,MAAM,CAAC,MAAM,CAAC,OAAO,UAAQ,GAAG,SAAS;CAG1C"}
|
|
@@ -36,8 +36,10 @@ export class VldBase64 extends VldBase {
|
|
|
36
36
|
])
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
//
|
|
40
|
-
|
|
39
|
+
// For standard base64, check length is multiple of 4 (after padding)
|
|
40
|
+
// Empty strings are valid (decode to empty buffer)
|
|
41
|
+
// For URL-safe base64, padding is not required
|
|
42
|
+
if (!this.urlSafe && value.length > 0 && value.length % 4 !== 0) {
|
|
41
43
|
return {
|
|
42
44
|
success: false,
|
|
43
45
|
error: new VldError([
|
|
@@ -58,5 +60,6 @@ export class VldBase64 extends VldBase {
|
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
VldBase64.BASE64_REGEX = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
63
|
+
// Note: RFC 4648 specifies URL-safe base64 should omit padding, but we allow it for compatibility
|
|
61
64
|
VldBase64.BASE64_URL_REGEX = /^[A-Za-z0-9_-]*={0,2}$/;
|
|
62
65
|
//# sourceMappingURL=base64.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/validators/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,OAAuB;
|
|
1
|
+
{"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/validators/base64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,OAAuB;IAOpD,YAAY,OAAO,GAAG,KAAK;QACzB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAc;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,KAAK,CAAC;QACrB,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,SAAS,CAAC,KAAc;QACtB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,IAAI,QAAQ,CAAC;oBAClB,WAAW,CAAC,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,cAAc,CAAC;iBAC9D,CAAC;aACH,CAAC;QACJ,CAAC;QAED,sCAAsC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;QAEjF,qBAAqB;QACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,IAAI,QAAQ,CAAC;oBAClB,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,aAAa,CAAC;iBACvD,CAAC;aACH,CAAC;QACJ,CAAC;QAED,qEAAqE;QACrE,mDAAmD;QACnD,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,IAAI,QAAQ,CAAC;oBAClB,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,aAAa,CAAC;iBACvD,CAAC;aACH,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,KAAK;QAC3B,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;;AAlEuB,sBAAY,GAAG,wBAAwB,CAAC;AAChE,kGAAkG;AAC1E,0BAAgB,GAAG,wBAAwB,CAAC","sourcesContent":["import { VldBase, ParseResult } from './base';\r\nimport { VldError, createIssue } from '../errors';\r\nimport { getMessages } from '../locales';\r\n\r\n/**\r\n * Base64 string validator\r\n */\r\nexport class VldBase64 extends VldBase<string, string> {\r\n private static readonly BASE64_REGEX = /^[A-Za-z0-9+/]*={0,2}$/;\r\n // Note: RFC 4648 specifies URL-safe base64 should omit padding, but we allow it for compatibility\r\n private static readonly BASE64_URL_REGEX = /^[A-Za-z0-9_-]*={0,2}$/;\r\n \r\n private readonly urlSafe: boolean;\r\n \r\n constructor(urlSafe = false) {\r\n super();\r\n this.urlSafe = urlSafe;\r\n }\r\n \r\n parse(value: unknown): string {\r\n const result = this.safeParse(value);\r\n if (!result.success) {\r\n throw result.error;\r\n }\r\n return result.data;\r\n }\r\n \r\n safeParse(value: unknown): ParseResult<string> {\r\n if (typeof value !== 'string') {\r\n return {\r\n success: false,\r\n error: new VldError([\r\n createIssue('invalid_type', [], getMessages().expectedString)\r\n ])\r\n };\r\n }\r\n \r\n // Check if it's a valid base64 string\r\n const regex = this.urlSafe ? VldBase64.BASE64_URL_REGEX : VldBase64.BASE64_REGEX;\r\n\r\n // Check basic format\r\n if (!regex.test(value)) {\r\n return {\r\n success: false,\r\n error: new VldError([\r\n createIssue('custom', [], getMessages().invalidBase64)\r\n ])\r\n };\r\n }\r\n\r\n // For standard base64, check length is multiple of 4 (after padding)\r\n // Empty strings are valid (decode to empty buffer)\r\n // For URL-safe base64, padding is not required\r\n if (!this.urlSafe && value.length > 0 && value.length % 4 !== 0) {\r\n return {\r\n success: false,\r\n error: new VldError([\r\n createIssue('custom', [], getMessages().invalidBase64)\r\n ])\r\n };\r\n }\r\n \r\n return { success: true, data: value };\r\n }\r\n \r\n /**\r\n * Create a URL-safe base64 validator\r\n */\r\n urlSafeMode(): VldBase64 {\r\n return new VldBase64(true);\r\n }\r\n \r\n static create(urlSafe = false): VldBase64 {\r\n return new VldBase64(urlSafe);\r\n }\r\n}"]}
|
|
@@ -2,7 +2,11 @@ import { VldBase, ParseResult } from './base';
|
|
|
2
2
|
/**
|
|
3
3
|
* Type for date validation check functions
|
|
4
4
|
*/
|
|
5
|
-
type
|
|
5
|
+
type DateCheckFn = (value: Date) => boolean;
|
|
6
|
+
interface DateCheck {
|
|
7
|
+
fn: DateCheckFn;
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
11
|
* Configuration for date validator
|
|
8
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/validators/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG9C;;GAEG;AACH,KAAK,
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/validators/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG9C;;GAEG;AACH,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC;AAE5C,UAAU,SAAS;IACjB,EAAE,EAAE,WAAW,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C;;OAEG;IACH,SAAS,aAAa,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAQ3D;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IA0B3B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC;IAQ5C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAW5D;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAW5D;;OAEG;IACH,OAAO,CACL,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC3B,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO;IAYV;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAU/B;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAUjC;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAehC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAalC;;OAEG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;CAYnC"}
|
package/dist/validators/date.js
CHANGED
|
@@ -40,8 +40,8 @@ export class VldDate extends VldBase {
|
|
|
40
40
|
}
|
|
41
41
|
// Apply all checks
|
|
42
42
|
for (const check of this.config.checks) {
|
|
43
|
-
if (!check(date)) {
|
|
44
|
-
throw new Error(
|
|
43
|
+
if (!check.fn(date)) {
|
|
44
|
+
throw new Error(check.message);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
return date;
|
|
@@ -63,8 +63,11 @@ export class VldDate extends VldBase {
|
|
|
63
63
|
min(date, message) {
|
|
64
64
|
const minDate = date instanceof Date ? date : new Date(date);
|
|
65
65
|
return new VldDate({
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
...this.config,
|
|
67
|
+
checks: [...this.config.checks, {
|
|
68
|
+
fn: (v) => v >= minDate,
|
|
69
|
+
message: message || getMessages().dateMin(minDate)
|
|
70
|
+
}]
|
|
68
71
|
});
|
|
69
72
|
}
|
|
70
73
|
/**
|
|
@@ -73,8 +76,11 @@ export class VldDate extends VldBase {
|
|
|
73
76
|
max(date, message) {
|
|
74
77
|
const maxDate = date instanceof Date ? date : new Date(date);
|
|
75
78
|
return new VldDate({
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
...this.config,
|
|
80
|
+
checks: [...this.config.checks, {
|
|
81
|
+
fn: (v) => v <= maxDate,
|
|
82
|
+
message: message || getMessages().dateMax(maxDate)
|
|
83
|
+
}]
|
|
78
84
|
});
|
|
79
85
|
}
|
|
80
86
|
/**
|
|
@@ -84,8 +90,11 @@ export class VldDate extends VldBase {
|
|
|
84
90
|
const minDate = min instanceof Date ? min : new Date(min);
|
|
85
91
|
const maxDate = max instanceof Date ? max : new Date(max);
|
|
86
92
|
return new VldDate({
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
...this.config,
|
|
94
|
+
checks: [...this.config.checks, {
|
|
95
|
+
fn: (v) => v >= minDate && v <= maxDate,
|
|
96
|
+
message: message || `Date must be between ${minDate.toISOString()} and ${maxDate.toISOString()}`
|
|
97
|
+
}]
|
|
89
98
|
});
|
|
90
99
|
}
|
|
91
100
|
/**
|
|
@@ -93,8 +102,11 @@ export class VldDate extends VldBase {
|
|
|
93
102
|
*/
|
|
94
103
|
past(message) {
|
|
95
104
|
return new VldDate({
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
...this.config,
|
|
106
|
+
checks: [...this.config.checks, {
|
|
107
|
+
fn: (v) => v < new Date(),
|
|
108
|
+
message: message || 'Date must be in the past'
|
|
109
|
+
}]
|
|
98
110
|
});
|
|
99
111
|
}
|
|
100
112
|
/**
|
|
@@ -102,8 +114,11 @@ export class VldDate extends VldBase {
|
|
|
102
114
|
*/
|
|
103
115
|
future(message) {
|
|
104
116
|
return new VldDate({
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
...this.config,
|
|
118
|
+
checks: [...this.config.checks, {
|
|
119
|
+
fn: (v) => v > new Date(),
|
|
120
|
+
message: message || 'Date must be in the future'
|
|
121
|
+
}]
|
|
107
122
|
});
|
|
108
123
|
}
|
|
109
124
|
/**
|
|
@@ -111,13 +126,16 @@ export class VldDate extends VldBase {
|
|
|
111
126
|
*/
|
|
112
127
|
today(message) {
|
|
113
128
|
return new VldDate({
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
v.
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
...this.config,
|
|
130
|
+
checks: [...this.config.checks, {
|
|
131
|
+
fn: (v) => {
|
|
132
|
+
const today = new Date();
|
|
133
|
+
return v.getFullYear() === today.getFullYear() &&
|
|
134
|
+
v.getMonth() === today.getMonth() &&
|
|
135
|
+
v.getDate() === today.getDate();
|
|
136
|
+
},
|
|
137
|
+
message: message || 'Date must be today'
|
|
138
|
+
}]
|
|
121
139
|
});
|
|
122
140
|
}
|
|
123
141
|
/**
|
|
@@ -125,11 +143,14 @@ export class VldDate extends VldBase {
|
|
|
125
143
|
*/
|
|
126
144
|
weekday(message) {
|
|
127
145
|
return new VldDate({
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
...this.config,
|
|
147
|
+
checks: [...this.config.checks, {
|
|
148
|
+
fn: (v) => {
|
|
149
|
+
const day = v.getDay();
|
|
150
|
+
return day >= 1 && day <= 5;
|
|
151
|
+
},
|
|
152
|
+
message: message || 'Date must be a weekday'
|
|
153
|
+
}]
|
|
133
154
|
});
|
|
134
155
|
}
|
|
135
156
|
/**
|
|
@@ -137,11 +158,14 @@ export class VldDate extends VldBase {
|
|
|
137
158
|
*/
|
|
138
159
|
weekend(message) {
|
|
139
160
|
return new VldDate({
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
161
|
+
...this.config,
|
|
162
|
+
checks: [...this.config.checks, {
|
|
163
|
+
fn: (v) => {
|
|
164
|
+
const day = v.getDay();
|
|
165
|
+
return day === 0 || day === 6;
|
|
166
|
+
},
|
|
167
|
+
message: message || 'Date must be a weekend'
|
|
168
|
+
}]
|
|
145
169
|
});
|
|
146
170
|
}
|
|
147
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/validators/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAezC;;GAEG;AACH,MAAM,OAAO,OAAQ,SAAQ,OAAmB;IAG9C;;OAEG;IACH,YAAsB,MAAqC;QACzD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG;YACZ,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE;YAC5B,YAAY,EAAE,MAAM,EAAE,YAAY;SACnC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,OAAO,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAc;QAClB,IAAI,IAAU,CAAC;QAEf,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YAC1B,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClE,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC;QACzE,CAAC;QAED,6BAA6B;QAC7B,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC;QACzE,CAAC;QAED,mBAAmB;QACnB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,KAAc;QACtB,IAAI,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAA4B,EAAE,OAAgB;QAChD,MAAM,OAAO,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC;YAC1D,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAA4B,EAAE,OAAgB;QAChD,MAAM,OAAO,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC;YAC1D,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CACL,GAA2B,EAC3B,GAA2B,EAC3B,OAAgB;QAEhB,MAAM,OAAO,GAAG,GAAG,YAAY,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,GAAG,YAAY,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1D,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,CAAC;YAC1E,YAAY,EAAE,OAAO,IAAI,wBAAwB,OAAO,CAAC,WAAW,EAAE,QAAQ,OAAO,CAAC,WAAW,EAAE,EAAE;SACtG,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAgB;QACnB,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YAC5D,YAAY,EAAE,OAAO,IAAI,0BAA0B;SACpD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAgB;QACrB,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YAC5D,YAAY,EAAE,OAAO,IAAI,4BAA4B;SACtD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAgB;QACpB,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE;oBAC1C,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;oBACzB,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE;wBACvC,CAAC,CAAC,QAAQ,EAAE,KAAK,KAAK,CAAC,QAAQ,EAAE;wBACjC,CAAC,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;gBACzC,CAAC,CAAC;YACF,YAAY,EAAE,OAAO,IAAI,oBAAoB;SAC9C,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,OAAgB;QACtB,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE;oBAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;oBACvB,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBAC9B,CAAC,CAAC;YACF,YAAY,EAAE,OAAO,IAAI,wBAAwB;SAClD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,OAAgB;QACtB,OAAO,IAAI,OAAO,CAAC;YACjB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAO,EAAE,EAAE;oBAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;oBACvB,OAAO,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAChC,CAAC,CAAC;YACF,YAAY,EAAE,OAAO,IAAI,wBAAwB;SAClD,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { VldBase, ParseResult } from './base';\nimport { getMessages } from '../locales';\n\n/**\n * Type for date validation check functions\n */\ntype DateCheck = (value: Date) => boolean;\n\n/**\n * Configuration for date validator\n */\ninterface DateValidatorConfig {\n readonly checks: ReadonlyArray<DateCheck>;\n readonly errorMessage?: string;\n}\n\n/**\n * Immutable date validator with chainable methods\n */\nexport class VldDate extends VldBase<Date, Date> {\n private readonly config: DateValidatorConfig;\n \n /**\n * Protected constructor to allow extension while maintaining immutability\n */\n protected constructor(config?: Partial<DateValidatorConfig>) {\n super();\n this.config = {\n checks: config?.checks || [],\n errorMessage: config?.errorMessage\n };\n }\n \n /**\n * Create a new date validator\n */\n static create(): VldDate {\n return new VldDate();\n }\n \n /**\n * Parse and validate a date value\n */\n parse(value: unknown): Date {\n let date: Date;\n \n if (value instanceof Date) {\n date = value;\n } else if (typeof value === 'string' || typeof value === 'number') {\n date = new Date(value);\n } else {\n throw new Error(this.config.errorMessage || getMessages().invalidDate);\n }\n \n // Check if the date is valid\n if (isNaN(date.getTime())) {\n throw new Error(this.config.errorMessage || getMessages().invalidDate);\n }\n \n // Apply all checks\n for (const check of this.config.checks) {\n if (!check(date)) {\n throw new Error(this.config.errorMessage || getMessages().invalidDate);\n }\n }\n \n return date;\n }\n \n /**\n * Safely parse and validate a date value\n */\n safeParse(value: unknown): ParseResult<Date> {\n try {\n return { success: true, data: this.parse(value) };\n } catch (error) {\n return { success: false, error: error as Error };\n }\n }\n \n /**\n * Create a new validator with minimum date constraint\n */\n min(date: Date | string | number, message?: string): VldDate {\n const minDate = date instanceof Date ? date : new Date(date);\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => v >= minDate],\n errorMessage: message || getMessages().dateMin(minDate)\n });\n }\n \n /**\n * Create a new validator with maximum date constraint\n */\n max(date: Date | string | number, message?: string): VldDate {\n const maxDate = date instanceof Date ? date : new Date(date);\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => v <= maxDate],\n errorMessage: message || getMessages().dateMax(maxDate)\n });\n }\n \n /**\n * Create a new validator with a range constraint\n */\n between(\n min: Date | string | number,\n max: Date | string | number,\n message?: string\n ): VldDate {\n const minDate = min instanceof Date ? min : new Date(min);\n const maxDate = max instanceof Date ? max : new Date(max);\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => v >= minDate && v <= maxDate],\n errorMessage: message || `Date must be between ${minDate.toISOString()} and ${maxDate.toISOString()}`\n });\n }\n \n /**\n * Create a new validator that checks if date is in the past\n */\n past(message?: string): VldDate {\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => v < new Date()],\n errorMessage: message || 'Date must be in the past'\n });\n }\n \n /**\n * Create a new validator that checks if date is in the future\n */\n future(message?: string): VldDate {\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => v > new Date()],\n errorMessage: message || 'Date must be in the future'\n });\n }\n \n /**\n * Create a new validator that checks if date is today\n */\n today(message?: string): VldDate {\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => {\n const today = new Date();\n return v.getFullYear() === today.getFullYear() &&\n v.getMonth() === today.getMonth() &&\n v.getDate() === today.getDate();\n }],\n errorMessage: message || 'Date must be today'\n });\n }\n \n /**\n * Create a new validator that checks if date is a weekday\n */\n weekday(message?: string): VldDate {\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => {\n const day = v.getDay();\n return day >= 1 && day <= 5;\n }],\n errorMessage: message || 'Date must be a weekday'\n });\n }\n \n /**\n * Create a new validator that checks if date is a weekend\n */\n weekend(message?: string): VldDate {\n return new VldDate({\n checks: [...this.config.checks, (v: Date) => {\n const day = v.getDay();\n return day === 0 || day === 6;\n }],\n errorMessage: message || 'Date must be a weekend'\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/validators/date.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\r\nimport { getMessages } from '../locales';\r\n\r\n/**\r\n * Type for date validation check functions\r\n */\r\ntype DateCheckFn = (value: Date) => boolean;\r\n\r\ninterface DateCheck {\r\n fn: DateCheckFn;\r\n message: string;\r\n}\r\n\r\n/**\r\n * Configuration for date validator\r\n */\r\ninterface DateValidatorConfig {\r\n readonly checks: ReadonlyArray<DateCheck>;\r\n readonly errorMessage?: string;\r\n}\r\n\r\n/**\r\n * Immutable date validator with chainable methods\r\n */\r\nexport class VldDate extends VldBase<Date, Date> {\r\n private readonly config: DateValidatorConfig;\r\n\r\n /**\r\n * Protected constructor to allow extension while maintaining immutability\r\n */\r\n protected constructor(config?: Partial<DateValidatorConfig>) {\r\n super();\r\n this.config = {\r\n checks: config?.checks || [],\r\n errorMessage: config?.errorMessage\r\n };\r\n }\r\n\r\n /**\r\n * Create a new date validator\r\n */\r\n static create(): VldDate {\r\n return new VldDate();\r\n }\r\n\r\n /**\r\n * Parse and validate a date value\r\n */\r\n parse(value: unknown): Date {\r\n let date: Date;\r\n\r\n if (value instanceof Date) {\r\n date = value;\r\n } else if (typeof value === 'string' || typeof value === 'number') {\r\n date = new Date(value);\r\n } else {\r\n throw new Error(this.config.errorMessage || getMessages().invalidDate);\r\n }\r\n\r\n // Check if the date is valid\r\n if (isNaN(date.getTime())) {\r\n throw new Error(this.config.errorMessage || getMessages().invalidDate);\r\n }\r\n\r\n // Apply all checks\r\n for (const check of this.config.checks) {\r\n if (!check.fn(date)) {\r\n throw new Error(check.message);\r\n }\r\n }\r\n\r\n return date;\r\n }\r\n\r\n /**\r\n * Safely parse and validate a date value\r\n */\r\n safeParse(value: unknown): ParseResult<Date> {\r\n try {\r\n return { success: true, data: this.parse(value) };\r\n } catch (error) {\r\n return { success: false, error: error as Error };\r\n }\r\n }\r\n\r\n /**\r\n * Create a new validator with minimum date constraint\r\n */\r\n min(date: Date | string | number, message?: string): VldDate {\r\n const minDate = date instanceof Date ? date : new Date(date);\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => v >= minDate,\r\n message: message || getMessages().dateMin(minDate)\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator with maximum date constraint\r\n */\r\n max(date: Date | string | number, message?: string): VldDate {\r\n const maxDate = date instanceof Date ? date : new Date(date);\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => v <= maxDate,\r\n message: message || getMessages().dateMax(maxDate)\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator with a range constraint\r\n */\r\n between(\r\n min: Date | string | number,\r\n max: Date | string | number,\r\n message?: string\r\n ): VldDate {\r\n const minDate = min instanceof Date ? min : new Date(min);\r\n const maxDate = max instanceof Date ? max : new Date(max);\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => v >= minDate && v <= maxDate,\r\n message: message || `Date must be between ${minDate.toISOString()} and ${maxDate.toISOString()}`\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator that checks if date is in the past\r\n */\r\n past(message?: string): VldDate {\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => v < new Date(),\r\n message: message || 'Date must be in the past'\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator that checks if date is in the future\r\n */\r\n future(message?: string): VldDate {\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => v > new Date(),\r\n message: message || 'Date must be in the future'\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator that checks if date is today\r\n */\r\n today(message?: string): VldDate {\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => {\r\n const today = new Date();\r\n return v.getFullYear() === today.getFullYear() &&\r\n v.getMonth() === today.getMonth() &&\r\n v.getDate() === today.getDate();\r\n },\r\n message: message || 'Date must be today'\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator that checks if date is a weekday\r\n */\r\n weekday(message?: string): VldDate {\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => {\r\n const day = v.getDay();\r\n return day >= 1 && day <= 5;\r\n },\r\n message: message || 'Date must be a weekday'\r\n }]\r\n });\r\n }\r\n\r\n /**\r\n * Create a new validator that checks if date is a weekend\r\n */\r\n weekend(message?: string): VldDate {\r\n return new VldDate({\r\n ...this.config,\r\n checks: [...this.config.checks, {\r\n fn: (v: Date) => {\r\n const day = v.getDay();\r\n return day === 0 || day === 6;\r\n },\r\n message: message || 'Date must be a weekend'\r\n }]\r\n });\r\n }\r\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number.d.ts","sourceRoot":"","sources":["../../src/validators/number.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG9C;;GAEG;AACH,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAE9C;;GAEG;AACH,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEjD;;OAEG;IACH,SAAS,aAAa,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAQ7D;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,SAAS;IAI1B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAe7B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC;IAQ9C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAO/C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAO/C;;OAEG;IACH,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOhC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOrC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOrC;;OAEG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOxC;;OAEG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOxC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOnC;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOjC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"number.d.ts","sourceRoot":"","sources":["../../src/validators/number.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG9C;;GAEG;AACH,KAAK,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAE9C;;GAEG;AACH,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEjD;;OAEG;IACH,SAAS,aAAa,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAQ7D;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,SAAS;IAI1B;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAe7B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC;IAQ9C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAO/C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAO/C;;OAEG;IACH,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOhC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOrC;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOrC;;OAEG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOxC;;OAEG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOxC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOnC;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAOjC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAWtD;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAIhD;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAO9D;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;IAWjC;;OAEG;IACH,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS;CAWjC"}
|
|
@@ -132,7 +132,11 @@ export class VldNumber extends VldBase {
|
|
|
132
132
|
*/
|
|
133
133
|
multipleOf(value, message) {
|
|
134
134
|
return new VldNumber({
|
|
135
|
-
checks: [...this.config.checks, (v) =>
|
|
135
|
+
checks: [...this.config.checks, (v) => {
|
|
136
|
+
// Use epsilon comparison for floating point precision
|
|
137
|
+
const remainder = Math.abs(v % value);
|
|
138
|
+
return remainder < Number.EPSILON || Math.abs(remainder - Math.abs(value)) < Number.EPSILON;
|
|
139
|
+
}],
|
|
136
140
|
errorMessage: message || getMessages().numberMultipleOf(value)
|
|
137
141
|
});
|
|
138
142
|
}
|
|
@@ -156,7 +160,11 @@ export class VldNumber extends VldBase {
|
|
|
156
160
|
*/
|
|
157
161
|
even(message) {
|
|
158
162
|
return new VldNumber({
|
|
159
|
-
checks: [...this.config.checks, (v) =>
|
|
163
|
+
checks: [...this.config.checks, (v) => {
|
|
164
|
+
// Use epsilon comparison for floating point precision
|
|
165
|
+
const remainder = Math.abs(v % 2);
|
|
166
|
+
return remainder < Number.EPSILON || Math.abs(remainder - 2) < Number.EPSILON;
|
|
167
|
+
}],
|
|
160
168
|
errorMessage: message || 'Number must be even'
|
|
161
169
|
});
|
|
162
170
|
}
|
|
@@ -165,7 +173,12 @@ export class VldNumber extends VldBase {
|
|
|
165
173
|
*/
|
|
166
174
|
odd(message) {
|
|
167
175
|
return new VldNumber({
|
|
168
|
-
checks: [...this.config.checks, (v) =>
|
|
176
|
+
checks: [...this.config.checks, (v) => {
|
|
177
|
+
// Use epsilon comparison for floating point precision
|
|
178
|
+
const remainder = Math.abs(v % 2);
|
|
179
|
+
const isEven = remainder < Number.EPSILON || Math.abs(remainder - 2) < Number.EPSILON;
|
|
180
|
+
return !isEven;
|
|
181
|
+
}],
|
|
169
182
|
errorMessage: message || 'Number must be odd'
|
|
170
183
|
});
|
|
171
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number.js","sourceRoot":"","sources":["../../src/validators/number.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\nimport { getMessages } from '../locales';\n\n/**\n * Type for number validation check functions\n */\ntype NumberCheck = (value: number) => boolean;\n\n/**\n * Configuration for number validator\n */\ninterface NumberValidatorConfig {\n readonly checks: ReadonlyArray<NumberCheck>;\n readonly errorMessage?: string;\n}\n\n/**\n * Immutable number validator with chainable methods\n */\nexport class VldNumber extends VldBase<number, number> {\n protected readonly config: NumberValidatorConfig;\n \n /**\n * Protected constructor to allow extension while maintaining immutability\n */\n protected constructor(config?: Partial<NumberValidatorConfig>) {\n super();\n this.config = {\n checks: config?.checks || [],\n errorMessage: config?.errorMessage\n };\n }\n \n /**\n * Create a new number validator\n */\n static create(): VldNumber {\n return new VldNumber();\n }\n \n /**\n * Parse and validate a number value\n */\n parse(value: unknown): number {\n if (typeof value !== 'number' || isNaN(value)) {\n throw new Error(this.config.errorMessage || getMessages().invalidNumber);\n }\n \n // Apply all checks\n for (const check of this.config.checks) {\n if (!check(value)) {\n throw new Error(this.config.errorMessage || getMessages().invalidNumber);\n }\n }\n \n return value;\n }\n \n /**\n * Safely parse and validate a number value\n */\n safeParse(value: unknown): ParseResult<number> {\n try {\n return { success: true, data: this.parse(value) };\n } catch (error) {\n return { success: false, error: error as Error };\n }\n }\n \n /**\n * Create a new validator with minimum value constraint\n */\n min(value: number, message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v >= value],\n errorMessage: message || getMessages().numberMin(value)\n });\n }\n \n /**\n * Create a new validator with maximum value constraint\n */\n max(value: number, message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v <= value],\n errorMessage: message || getMessages().numberMax(value)\n });\n }\n \n /**\n * Create a new validator that checks for integer values\n */\n int(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => Number.isInteger(v)],\n errorMessage: message || getMessages().numberInt\n });\n }\n \n /**\n * Create a new validator that checks for positive values\n */\n positive(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v > 0],\n errorMessage: message || getMessages().numberPositive\n });\n }\n \n /**\n * Create a new validator that checks for negative values\n */\n negative(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v < 0],\n errorMessage: message || getMessages().numberNegative\n });\n }\n \n /**\n * Create a new validator that checks for non-negative values\n */\n nonnegative(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v >= 0],\n errorMessage: message || getMessages().numberNonnegative\n });\n }\n \n /**\n * Create a new validator that checks for non-positive values\n */\n nonpositive(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v <= 0],\n errorMessage: message || getMessages().numberNonpositive\n });\n }\n \n /**\n * Create a new validator that checks for finite values\n */\n finite(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => Number.isFinite(v)],\n errorMessage: message || getMessages().numberFinite\n });\n }\n \n /**\n * Create a new validator that checks for safe integer values\n */\n safe(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => Number.isSafeInteger(v)],\n errorMessage: message || getMessages().numberSafe\n });\n }\n \n /**\n * Create a new validator that checks if value is multiple of another\n */\n multipleOf(value: number, message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v % value === 0],\n errorMessage: message || getMessages().numberMultipleOf(value)\n });\n }\n \n /**\n * Alias for multipleOf\n */\n step(value: number, message?: string): VldNumber {\n return this.multipleOf(value, message);\n }\n \n /**\n * Create a new validator with a range constraint\n */\n between(min: number, max: number, message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v >= min && v <= max],\n errorMessage: message || `Number must be between ${min} and ${max}`\n });\n }\n \n /**\n * Create a new validator that checks for even numbers\n */\n even(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v % 2 === 0],\n errorMessage: message || 'Number must be even'\n });\n }\n \n /**\n * Create a new validator that checks for odd numbers\n */\n odd(message?: string): VldNumber {\n return new VldNumber({\n checks: [...this.config.checks, (v: number) => v % 2 !== 0],\n errorMessage: message || 'Number must be odd'\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"number.js","sourceRoot":"","sources":["../../src/validators/number.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\r\nimport { getMessages } from '../locales';\r\n\r\n/**\r\n * Type for number validation check functions\r\n */\r\ntype NumberCheck = (value: number) => boolean;\r\n\r\n/**\r\n * Configuration for number validator\r\n */\r\ninterface NumberValidatorConfig {\r\n readonly checks: ReadonlyArray<NumberCheck>;\r\n readonly errorMessage?: string;\r\n}\r\n\r\n/**\r\n * Immutable number validator with chainable methods\r\n */\r\nexport class VldNumber extends VldBase<number, number> {\r\n protected readonly config: NumberValidatorConfig;\r\n \r\n /**\r\n * Protected constructor to allow extension while maintaining immutability\r\n */\r\n protected constructor(config?: Partial<NumberValidatorConfig>) {\r\n super();\r\n this.config = {\r\n checks: config?.checks || [],\r\n errorMessage: config?.errorMessage\r\n };\r\n }\r\n \r\n /**\r\n * Create a new number validator\r\n */\r\n static create(): VldNumber {\r\n return new VldNumber();\r\n }\r\n \r\n /**\r\n * Parse and validate a number value\r\n */\r\n parse(value: unknown): number {\r\n if (typeof value !== 'number' || isNaN(value)) {\r\n throw new Error(this.config.errorMessage || getMessages().invalidNumber);\r\n }\r\n \r\n // Apply all checks\r\n for (const check of this.config.checks) {\r\n if (!check(value)) {\r\n throw new Error(this.config.errorMessage || getMessages().invalidNumber);\r\n }\r\n }\r\n \r\n return value;\r\n }\r\n \r\n /**\r\n * Safely parse and validate a number value\r\n */\r\n safeParse(value: unknown): ParseResult<number> {\r\n try {\r\n return { success: true, data: this.parse(value) };\r\n } catch (error) {\r\n return { success: false, error: error as Error };\r\n }\r\n }\r\n \r\n /**\r\n * Create a new validator with minimum value constraint\r\n */\r\n min(value: number, message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v >= value],\r\n errorMessage: message || getMessages().numberMin(value)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator with maximum value constraint\r\n */\r\n max(value: number, message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v <= value],\r\n errorMessage: message || getMessages().numberMax(value)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for integer values\r\n */\r\n int(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => Number.isInteger(v)],\r\n errorMessage: message || getMessages().numberInt\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for positive values\r\n */\r\n positive(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v > 0],\r\n errorMessage: message || getMessages().numberPositive\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for negative values\r\n */\r\n negative(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v < 0],\r\n errorMessage: message || getMessages().numberNegative\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for non-negative values\r\n */\r\n nonnegative(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v >= 0],\r\n errorMessage: message || getMessages().numberNonnegative\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for non-positive values\r\n */\r\n nonpositive(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v <= 0],\r\n errorMessage: message || getMessages().numberNonpositive\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for finite values\r\n */\r\n finite(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => Number.isFinite(v)],\r\n errorMessage: message || getMessages().numberFinite\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for safe integer values\r\n */\r\n safe(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => Number.isSafeInteger(v)],\r\n errorMessage: message || getMessages().numberSafe\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks if value is multiple of another\r\n */\r\n multipleOf(value: number, message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => {\r\n // Use epsilon comparison for floating point precision\r\n const remainder = Math.abs(v % value);\r\n return remainder < Number.EPSILON || Math.abs(remainder - Math.abs(value)) < Number.EPSILON;\r\n }],\r\n errorMessage: message || getMessages().numberMultipleOf(value)\r\n });\r\n }\r\n \r\n /**\r\n * Alias for multipleOf\r\n */\r\n step(value: number, message?: string): VldNumber {\r\n return this.multipleOf(value, message);\r\n }\r\n \r\n /**\r\n * Create a new validator with a range constraint\r\n */\r\n between(min: number, max: number, message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => v >= min && v <= max],\r\n errorMessage: message || `Number must be between ${min} and ${max}`\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for even numbers\r\n */\r\n even(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => {\r\n // Use epsilon comparison for floating point precision\r\n const remainder = Math.abs(v % 2);\r\n return remainder < Number.EPSILON || Math.abs(remainder - 2) < Number.EPSILON;\r\n }],\r\n errorMessage: message || 'Number must be even'\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for odd numbers\r\n */\r\n odd(message?: string): VldNumber {\r\n return new VldNumber({\r\n checks: [...this.config.checks, (v: number) => {\r\n // Use epsilon comparison for floating point precision\r\n const remainder = Math.abs(v % 2);\r\n const isEven = remainder < Number.EPSILON || Math.abs(remainder - 2) < Number.EPSILON;\r\n return !isEven;\r\n }],\r\n errorMessage: message || 'Number must be odd'\r\n });\r\n }\r\n}"]}
|
|
@@ -27,6 +27,11 @@ export declare class VldObject<T extends Record<string, any>> extends VldBase<un
|
|
|
27
27
|
* Optimized version using pre-computed keys
|
|
28
28
|
*/
|
|
29
29
|
safeParse(value: unknown): ParseResult<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Comprehensive prototype pollution protection
|
|
32
|
+
* Checks for dangerous keys that could modify Object.prototype
|
|
33
|
+
*/
|
|
34
|
+
private isDangerousKey;
|
|
30
35
|
/**
|
|
31
36
|
* Create a new validator in strict mode (no extra keys allowed)
|
|
32
37
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/validators/object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAe,MAAM,QAAQ,CAAC;AAa3D;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAE3C;;OAEG;IACH,OAAO;IAQP;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzC,KAAK,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,GAChD,SAAS,CAAC,CAAC,CAAC;IAIf;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/validators/object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAe,MAAM,QAAQ,CAAC;AAa3D;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAE3C;;OAEG;IACH,OAAO;IAQP;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzC,KAAK,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,GAChD,SAAS,CAAC,CAAC,CAAC;IAIf;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC;IAmFxB;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC;IAgEzC;;;OAGG;IACH,OAAO,CAAC,cAAc;IA0DtB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAStC;;OAEG;IACH,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC;IAQ3B;;OAEG;IACH,OAAO,IAAI,SAAS,CAAC;SAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IAW/C;;OAEG;IACH,WAAW,IAAI,SAAS,CAAC,GAAG,CAAC;IAgB7B;;OAEG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAa5D;;OAEG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAc5D;;OAEG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClC,SAAS,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,GACpD,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;IAOnB;;OAEG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAClB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;IAOnB;;OAEG;IACH,QAAQ,IAAI,SAAS,CAAC;SAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;CAgBlD"}
|
|
@@ -89,14 +89,13 @@ export class VldObject extends VldBase {
|
|
|
89
89
|
throw new Error(getMessages().unexpectedKeys(extraKeys));
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
// Handle passthrough mode - optimized with prototype pollution protection
|
|
92
|
+
// Handle passthrough mode - optimized with comprehensive prototype pollution protection
|
|
93
93
|
if (this.config.passthrough) {
|
|
94
|
-
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
95
94
|
const objKeys = Object.keys(obj);
|
|
96
95
|
for (let i = 0; i < objKeys.length; i++) {
|
|
97
96
|
const key = objKeys[i];
|
|
98
97
|
// Skip dangerous keys to prevent prototype pollution
|
|
99
|
-
if (!this.shapeKeysSet.has(key) && !
|
|
98
|
+
if (!this.shapeKeysSet.has(key) && !this.isDangerousKey(key)) {
|
|
100
99
|
result[key] = obj[key];
|
|
101
100
|
}
|
|
102
101
|
}
|
|
@@ -149,20 +148,73 @@ export class VldObject extends VldBase {
|
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
}
|
|
152
|
-
// Handle passthrough mode with prototype pollution protection
|
|
151
|
+
// Handle passthrough mode with comprehensive prototype pollution protection
|
|
153
152
|
if (this.config.passthrough) {
|
|
154
|
-
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
155
153
|
const objKeys = Object.keys(obj);
|
|
156
154
|
for (let i = 0; i < objKeys.length; i++) {
|
|
157
155
|
const key = objKeys[i];
|
|
158
156
|
// Skip dangerous keys to prevent prototype pollution
|
|
159
|
-
if (!this.shapeKeysSet.has(key) && !
|
|
157
|
+
if (!this.shapeKeysSet.has(key) && !this.isDangerousKey(key)) {
|
|
160
158
|
result[key] = obj[key];
|
|
161
159
|
}
|
|
162
160
|
}
|
|
163
161
|
}
|
|
164
162
|
return { success: true, data: result };
|
|
165
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Comprehensive prototype pollution protection
|
|
166
|
+
* Checks for dangerous keys that could modify Object.prototype
|
|
167
|
+
*/
|
|
168
|
+
isDangerousKey(key) {
|
|
169
|
+
// Direct dangerous keys
|
|
170
|
+
const directDangerousKeys = ['__proto__', 'constructor', 'prototype'];
|
|
171
|
+
if (directDangerousKeys.includes(key)) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
// Nested prototype manipulation vectors
|
|
175
|
+
// These patterns could allow prototype pollution through nested access
|
|
176
|
+
const nestedPatterns = [
|
|
177
|
+
'constructor.prototype',
|
|
178
|
+
'__proto__.toString',
|
|
179
|
+
'prototype.constructor',
|
|
180
|
+
'__defineGetter__',
|
|
181
|
+
'__defineSetter__',
|
|
182
|
+
'__lookupGetter__',
|
|
183
|
+
'__lookupSetter__'
|
|
184
|
+
];
|
|
185
|
+
// Check for nested patterns
|
|
186
|
+
for (const pattern of nestedPatterns) {
|
|
187
|
+
if (key.includes(pattern)) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Check for property access chains that could lead to prototype pollution
|
|
192
|
+
// This covers patterns like "x.constructor.prototype.polluted"
|
|
193
|
+
const dangerousChains = [
|
|
194
|
+
'constructor.',
|
|
195
|
+
'__proto__.',
|
|
196
|
+
'prototype.'
|
|
197
|
+
];
|
|
198
|
+
for (const chain of dangerousChains) {
|
|
199
|
+
if (key.includes(chain)) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Additional protection: reject keys that could be used for property shadowing
|
|
204
|
+
const shadowingPatterns = [
|
|
205
|
+
'hasOwnProperty',
|
|
206
|
+
'toString',
|
|
207
|
+
'valueOf',
|
|
208
|
+
'isPrototypeOf',
|
|
209
|
+
'propertyIsEnumerable'
|
|
210
|
+
];
|
|
211
|
+
for (const pattern of shadowingPatterns) {
|
|
212
|
+
if (key === pattern || key.includes(`.${pattern}`)) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
166
218
|
/**
|
|
167
219
|
* Create a new validator in strict mode (no extra keys allowed)
|
|
168
220
|
*/
|