@oxog/vld 1.4.0 → 2.0.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.
Files changed (242) hide show
  1. package/CHANGELOG.md +449 -333
  2. package/README.md +1171 -1130
  3. package/dist/chunks/bigint-ZKkWLdmi.js +1628 -0
  4. package/dist/chunks/bigint-ZKkWLdmi.js.map +1 -0
  5. package/dist/{coercion/string.js → chunks/date-7Iz2BGsL.js} +271 -5
  6. package/dist/chunks/date-7Iz2BGsL.js.map +1 -0
  7. package/dist/chunks/index-BoV-4S1F.js +894 -0
  8. package/dist/chunks/index-BoV-4S1F.js.map +1 -0
  9. package/dist/chunks/index-eWXdjyyy.js +426 -0
  10. package/dist/chunks/index-eWXdjyyy.js.map +1 -0
  11. package/dist/chunks/json-nIhyRPOU.js +1934 -0
  12. package/dist/chunks/json-nIhyRPOU.js.map +1 -0
  13. package/dist/{validators/unknown.js → chunks/unknown-CjSRcELI.js} +6 -3
  14. package/dist/chunks/unknown-CjSRcELI.js.map +1 -0
  15. package/dist/cjs/errors.cjs +387 -0
  16. package/dist/cjs/errors.cjs.map +1 -0
  17. package/dist/cjs/index.cjs +9815 -0
  18. package/dist/cjs/index.cjs.map +1 -0
  19. package/dist/cjs/locales/index.cjs +2877 -0
  20. package/dist/cjs/locales/index.cjs.map +1 -0
  21. package/dist/cjs/locales/lazy.cjs +3169 -0
  22. package/dist/cjs/locales/lazy.cjs.map +1 -0
  23. package/dist/cjs/mini.cjs +7161 -0
  24. package/dist/cjs/mini.cjs.map +1 -0
  25. package/dist/cli/bin.d.ts +8 -0
  26. package/dist/cli/bin.d.ts.map +1 -0
  27. package/dist/cli/commands/benchmark.d.ts +11 -0
  28. package/dist/cli/commands/benchmark.d.ts.map +1 -0
  29. package/dist/cli/commands/validate.d.ts +11 -0
  30. package/dist/cli/commands/validate.d.ts.map +1 -0
  31. package/dist/cli/index.d.ts +59 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/codecs/index.d.ts.map +1 -1
  34. package/dist/codecs/index.js +4 -256
  35. package/dist/codecs/index.js.map +1 -1
  36. package/dist/coercion/boolean.d.ts.map +1 -1
  37. package/dist/coercion/index.d.ts +11 -0
  38. package/dist/coercion/index.d.ts.map +1 -0
  39. package/dist/coercion/{bigint.js → index.js} +7 -4
  40. package/dist/coercion/index.js.map +1 -0
  41. package/dist/compat/emitter.d.ts +73 -0
  42. package/dist/compat/emitter.d.ts.map +1 -0
  43. package/dist/compat/emitter.js +181 -0
  44. package/dist/compat/emitter.js.map +1 -0
  45. package/dist/compat/index.d.ts +15 -0
  46. package/dist/compat/index.d.ts.map +1 -0
  47. package/dist/compat/result.d.ts +128 -0
  48. package/dist/compat/result.d.ts.map +1 -0
  49. package/dist/compat/result.js +171 -0
  50. package/dist/compat/result.js.map +1 -0
  51. package/dist/errors.d.ts +58 -1
  52. package/dist/errors.d.ts.map +1 -1
  53. package/dist/errors.js +106 -15
  54. package/dist/errors.js.map +1 -1
  55. package/dist/events.d.ts +140 -0
  56. package/dist/events.d.ts.map +1 -0
  57. package/dist/index.d.ts +13 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +230 -103
  60. package/dist/index.js.map +1 -1
  61. package/dist/kernel.d.ts +29 -0
  62. package/dist/kernel.d.ts.map +1 -0
  63. package/dist/kernel.js +405 -0
  64. package/dist/kernel.js.map +1 -0
  65. package/dist/locales/af.js +4 -2
  66. package/dist/locales/af.js.map +1 -1
  67. package/dist/locales/ar.js +4 -2
  68. package/dist/locales/ar.js.map +1 -1
  69. package/dist/locales/bn.js +4 -2
  70. package/dist/locales/bn.js.map +1 -1
  71. package/dist/locales/da.js +4 -2
  72. package/dist/locales/da.js.map +1 -1
  73. package/dist/locales/de.js +4 -2
  74. package/dist/locales/de.js.map +1 -1
  75. package/dist/locales/en.js +4 -2
  76. package/dist/locales/en.js.map +1 -1
  77. package/dist/locales/es-MX.js +4 -2
  78. package/dist/locales/es-MX.js.map +1 -1
  79. package/dist/locales/es.js +4 -2
  80. package/dist/locales/es.js.map +1 -1
  81. package/dist/locales/fi.js +4 -2
  82. package/dist/locales/fi.js.map +1 -1
  83. package/dist/locales/fr.js +4 -2
  84. package/dist/locales/fr.js.map +1 -1
  85. package/dist/locales/hi.js +4 -2
  86. package/dist/locales/hi.js.map +1 -1
  87. package/dist/locales/id.js +4 -2
  88. package/dist/locales/id.js.map +1 -1
  89. package/dist/locales/index.js +3 -91
  90. package/dist/locales/index.js.map +1 -1
  91. package/dist/locales/it.js +4 -2
  92. package/dist/locales/it.js.map +1 -1
  93. package/dist/locales/ja.js +4 -2
  94. package/dist/locales/ja.js.map +1 -1
  95. package/dist/locales/ko.js +4 -2
  96. package/dist/locales/ko.js.map +1 -1
  97. package/dist/locales/lazy.d.ts +111 -0
  98. package/dist/locales/lazy.d.ts.map +1 -0
  99. package/dist/locales/lazy.js +220 -0
  100. package/dist/locales/lazy.js.map +1 -0
  101. package/dist/locales/nl.js +4 -2
  102. package/dist/locales/nl.js.map +1 -1
  103. package/dist/locales/no.js +4 -2
  104. package/dist/locales/no.js.map +1 -1
  105. package/dist/locales/pl.js +4 -2
  106. package/dist/locales/pl.js.map +1 -1
  107. package/dist/locales/pt-BR.js +4 -2
  108. package/dist/locales/pt-BR.js.map +1 -1
  109. package/dist/locales/pt.js +4 -2
  110. package/dist/locales/pt.js.map +1 -1
  111. package/dist/locales/ru.js +4 -2
  112. package/dist/locales/ru.js.map +1 -1
  113. package/dist/locales/sv.js +4 -2
  114. package/dist/locales/sv.js.map +1 -1
  115. package/dist/locales/sw.js +4 -2
  116. package/dist/locales/sw.js.map +1 -1
  117. package/dist/locales/th.js +4 -2
  118. package/dist/locales/th.js.map +1 -1
  119. package/dist/locales/tr.js +4 -2
  120. package/dist/locales/tr.js.map +1 -1
  121. package/dist/locales/vi.js +4 -2
  122. package/dist/locales/vi.js.map +1 -1
  123. package/dist/locales/zh.js +4 -2
  124. package/dist/locales/zh.js.map +1 -1
  125. package/dist/logger.d.ts +94 -0
  126. package/dist/logger.d.ts.map +1 -0
  127. package/dist/mini.d.ts +182 -0
  128. package/dist/mini.d.ts.map +1 -0
  129. package/dist/mini.js +132 -0
  130. package/dist/mini.js.map +1 -0
  131. package/dist/pigment.d.ts +124 -0
  132. package/dist/pigment.d.ts.map +1 -0
  133. package/dist/pigment.js +178 -0
  134. package/dist/pigment.js.map +1 -0
  135. package/dist/plugins/index.d.ts +8 -0
  136. package/dist/plugins/index.d.ts.map +1 -0
  137. package/dist/plugins/types.d.ts +186 -0
  138. package/dist/plugins/types.d.ts.map +1 -0
  139. package/dist/utils/codec-utils.d.ts.map +1 -1
  140. package/dist/utils/ip-validation.d.ts.map +1 -1
  141. package/dist/validators/base.d.ts +3 -0
  142. package/dist/validators/base.d.ts.map +1 -1
  143. package/dist/validators/index.js +5 -45
  144. package/dist/validators/index.js.map +1 -1
  145. package/dist/validators/object.d.ts.map +1 -1
  146. package/dist/validators/template-literal.d.ts.map +1 -1
  147. package/package.json +153 -79
  148. package/dist/coercion/bigint.js.map +0 -1
  149. package/dist/coercion/boolean.js +0 -67
  150. package/dist/coercion/boolean.js.map +0 -1
  151. package/dist/coercion/date.js +0 -52
  152. package/dist/coercion/date.js.map +0 -1
  153. package/dist/coercion/number.js +0 -160
  154. package/dist/coercion/number.js.map +0 -1
  155. package/dist/coercion/string.js.map +0 -1
  156. package/dist/locales/backup-en.js +0 -105
  157. package/dist/locales/backup-en.js.map +0 -1
  158. package/dist/locales/types.js +0 -2
  159. package/dist/locales/types.js.map +0 -1
  160. package/dist/utils/codec-utils.js +0 -223
  161. package/dist/utils/codec-utils.js.map +0 -1
  162. package/dist/utils/deep-merge.js +0 -76
  163. package/dist/utils/deep-merge.js.map +0 -1
  164. package/dist/utils/ip-validation.js +0 -78
  165. package/dist/utils/ip-validation.js.map +0 -1
  166. package/dist/utils/security.js +0 -61
  167. package/dist/utils/security.js.map +0 -1
  168. package/dist/validators/any.js +0 -25
  169. package/dist/validators/any.js.map +0 -1
  170. package/dist/validators/array.js +0 -190
  171. package/dist/validators/array.js.map +0 -1
  172. package/dist/validators/base.js +0 -491
  173. package/dist/validators/base.js.map +0 -1
  174. package/dist/validators/base64.js +0 -65
  175. package/dist/validators/base64.js.map +0 -1
  176. package/dist/validators/bigint.js +0 -142
  177. package/dist/validators/bigint.js.map +0 -1
  178. package/dist/validators/boolean.js +0 -114
  179. package/dist/validators/boolean.js.map +0 -1
  180. package/dist/validators/codec.js +0 -182
  181. package/dist/validators/codec.js.map +0 -1
  182. package/dist/validators/custom.js +0 -50
  183. package/dist/validators/custom.js.map +0 -1
  184. package/dist/validators/date.js +0 -227
  185. package/dist/validators/date.js.map +0 -1
  186. package/dist/validators/discriminated-union.js +0 -98
  187. package/dist/validators/discriminated-union.js.map +0 -1
  188. package/dist/validators/enum.js +0 -82
  189. package/dist/validators/enum.js.map +0 -1
  190. package/dist/validators/file.js +0 -114
  191. package/dist/validators/file.js.map +0 -1
  192. package/dist/validators/function.js +0 -45
  193. package/dist/validators/function.js.map +0 -1
  194. package/dist/validators/hex.js +0 -62
  195. package/dist/validators/hex.js.map +0 -1
  196. package/dist/validators/intersection.js +0 -64
  197. package/dist/validators/intersection.js.map +0 -1
  198. package/dist/validators/json.js +0 -64
  199. package/dist/validators/json.js.map +0 -1
  200. package/dist/validators/lazy.js +0 -42
  201. package/dist/validators/lazy.js.map +0 -1
  202. package/dist/validators/literal.js +0 -45
  203. package/dist/validators/literal.js.map +0 -1
  204. package/dist/validators/map.js +0 -54
  205. package/dist/validators/map.js.map +0 -1
  206. package/dist/validators/nan.js +0 -32
  207. package/dist/validators/nan.js.map +0 -1
  208. package/dist/validators/never.js +0 -29
  209. package/dist/validators/never.js.map +0 -1
  210. package/dist/validators/null.js +0 -31
  211. package/dist/validators/null.js.map +0 -1
  212. package/dist/validators/number.js +0 -225
  213. package/dist/validators/number.js.map +0 -1
  214. package/dist/validators/object.js +0 -458
  215. package/dist/validators/object.js.map +0 -1
  216. package/dist/validators/record.js +0 -128
  217. package/dist/validators/record.js.map +0 -1
  218. package/dist/validators/set.js +0 -51
  219. package/dist/validators/set.js.map +0 -1
  220. package/dist/validators/string-bool.js +0 -127
  221. package/dist/validators/string-bool.js.map +0 -1
  222. package/dist/validators/string-formats.js +0 -120
  223. package/dist/validators/string-formats.js.map +0 -1
  224. package/dist/validators/string.js +0 -253
  225. package/dist/validators/string.js.map +0 -1
  226. package/dist/validators/symbol.js +0 -42
  227. package/dist/validators/symbol.js.map +0 -1
  228. package/dist/validators/template-literal.js +0 -101
  229. package/dist/validators/template-literal.js.map +0 -1
  230. package/dist/validators/tuple.js +0 -55
  231. package/dist/validators/tuple.js.map +0 -1
  232. package/dist/validators/uint8array.js +0 -98
  233. package/dist/validators/uint8array.js.map +0 -1
  234. package/dist/validators/undefined.js +0 -31
  235. package/dist/validators/undefined.js.map +0 -1
  236. package/dist/validators/union.js +0 -126
  237. package/dist/validators/union.js.map +0 -1
  238. package/dist/validators/unknown.js.map +0 -1
  239. package/dist/validators/void.js +0 -35
  240. package/dist/validators/void.js.map +0 -1
  241. package/dist/validators/xor.js +0 -64
  242. package/dist/validators/xor.js.map +0 -1
@@ -1,51 +0,0 @@
1
- import { VldBase } from './base.js';
2
- import { getMessages } from '../locales/index.js';
3
- /**
4
- * Immutable Set validator
5
- */
6
- export class VldSet extends VldBase {
7
- /**
8
- * Private constructor to enforce immutability
9
- */
10
- constructor(itemValidator, errorMessage) {
11
- super();
12
- this.itemValidator = itemValidator;
13
- this.errorMessage = errorMessage;
14
- }
15
- /**
16
- * Create a new Set validator
17
- */
18
- static create(itemValidator) {
19
- return new VldSet(itemValidator);
20
- }
21
- /**
22
- * Parse and validate a Set value
23
- */
24
- parse(value) {
25
- if (!(value instanceof Set)) {
26
- throw new Error(this.errorMessage || getMessages().invalidSet);
27
- }
28
- const result = new Set();
29
- for (const item of value) {
30
- try {
31
- result.add(this.itemValidator.parse(item));
32
- }
33
- catch (error) {
34
- throw new Error(error.message);
35
- }
36
- }
37
- return result;
38
- }
39
- /**
40
- * Safely parse and validate a Set value
41
- */
42
- safeParse(value) {
43
- try {
44
- return { success: true, data: this.parse(value) };
45
- }
46
- catch (error) {
47
- return { success: false, error: error };
48
- }
49
- }
50
- }
51
- //# sourceMappingURL=set.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"set.js","sourceRoot":"","sources":["../../src/validators/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,MAAM,OAAO,MAAU,SAAQ,OAAwB;IACrD;;OAEG;IACH,YACmB,aAAkC,EAClC,YAAqB;QAEtC,KAAK,EAAE,CAAC;QAHS,kBAAa,GAAb,aAAa,CAAqB;QAClC,iBAAY,GAAZ,YAAY,CAAS;IAGxC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAI,aAAkC;QACjD,OAAO,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAc;QAClB,IAAI,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,UAAU,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAK,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC;YAC5C,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;CACF","sourcesContent":["import { VldBase, ParseResult } from './base';\nimport { getMessages } from '../locales';\n\n/**\n * Immutable Set validator\n */\nexport class VldSet<T> extends VldBase<unknown, Set<T>> {\n /**\n * Private constructor to enforce immutability\n */\n private constructor(\n private readonly itemValidator: VldBase<unknown, T>,\n private readonly errorMessage?: string\n ) {\n super();\n }\n \n /**\n * Create a new Set validator\n */\n static create<T>(itemValidator: VldBase<unknown, T>): VldSet<T> {\n return new VldSet(itemValidator);\n }\n \n /**\n * Parse and validate a Set value\n */\n parse(value: unknown): Set<T> {\n if (!(value instanceof Set)) {\n throw new Error(this.errorMessage || getMessages().invalidSet);\n }\n \n const result = new Set<T>();\n for (const item of value) {\n try {\n result.add(this.itemValidator.parse(item));\n } catch (error) {\n throw new Error((error as Error).message);\n }\n }\n \n return result;\n }\n \n /**\n * Safely parse and validate a Set value\n */\n safeParse(value: unknown): ParseResult<Set<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}"]}
@@ -1,127 +0,0 @@
1
- import { VldBase } from './base.js';
2
- import { getMessages } from '../locales/index.js';
3
- /**
4
- * Default truthy and falsy value sets
5
- */
6
- const DEFAULT_TRUTHY = ['true', '1', 'yes', 'on', 'y', 'enabled'];
7
- const DEFAULT_FALSY = ['false', '0', 'no', 'off', 'n', 'disabled'];
8
- /**
9
- * Immutable string boolean validator for flexible boolean parsing
10
- * Supports string representations like "true", "yes", "on", "1", etc.
11
- */
12
- export class VldStringBool extends VldBase {
13
- constructor(options) {
14
- super();
15
- this.options = options;
16
- }
17
- /**
18
- * Create a new string boolean validator
19
- */
20
- static create(options = {}) {
21
- return new VldStringBool(options);
22
- }
23
- /**
24
- * Normalize a string value based on case sensitivity setting
25
- */
26
- normalizeValue(value) {
27
- return this.options.caseSensitive ? value : value.toLowerCase();
28
- }
29
- /**
30
- * Get the effective truthy values (custom or default)
31
- */
32
- getTruthyValues() {
33
- return this.options.truthy ?? DEFAULT_TRUTHY;
34
- }
35
- /**
36
- * Get the effective falsy values (custom or default)
37
- */
38
- getFalsyValues() {
39
- return this.options.falsy ?? DEFAULT_FALSY;
40
- }
41
- /**
42
- * Parse and validate a string boolean value
43
- */
44
- parse(value) {
45
- // First, ensure we have a string
46
- if (typeof value !== 'string') {
47
- // Also accept actual boolean values for convenience
48
- if (typeof value === 'boolean') {
49
- return value;
50
- }
51
- throw new Error(getMessages().stringExpected(typeof value, 'string'));
52
- }
53
- const normalized = this.normalizeValue(value);
54
- const truthyValues = this.getTruthyValues();
55
- const falsyValues = this.getFalsyValues();
56
- // Normalize the value sets for comparison
57
- const normalizedTruthy = this.options.caseSensitive
58
- ? truthyValues
59
- : truthyValues.map(v => v.toLowerCase());
60
- const normalizedFalsy = this.options.caseSensitive
61
- ? falsyValues
62
- : falsyValues.map(v => v.toLowerCase());
63
- // Check if value is in truthy set
64
- if (normalizedTruthy.includes(normalized)) {
65
- return true;
66
- }
67
- // Check if value is in falsy set
68
- if (normalizedFalsy.includes(normalized)) {
69
- return false;
70
- }
71
- // Value is not recognized
72
- const allValidValues = [...normalizedTruthy, ...normalizedFalsy];
73
- throw new Error(getMessages().stringBoolExpected(this.options.caseSensitive ? allValidValues.join(', ') : allValidValues.join(', '), value));
74
- }
75
- /**
76
- * Safely parse and validate a string boolean value
77
- */
78
- safeParse(value) {
79
- try {
80
- const result = this.parse(value);
81
- return { success: true, data: result };
82
- }
83
- catch (error) {
84
- return {
85
- success: false,
86
- error: error
87
- };
88
- }
89
- }
90
- /**
91
- * Create a new validator with custom truthy values
92
- */
93
- withTruthy(values) {
94
- return new VldStringBool({
95
- ...this.options,
96
- truthy: values
97
- });
98
- }
99
- /**
100
- * Create a new validator with custom falsy values
101
- */
102
- withFalsy(values) {
103
- return new VldStringBool({
104
- ...this.options,
105
- falsy: values
106
- });
107
- }
108
- /**
109
- * Create a new validator with case-sensitive matching
110
- */
111
- caseSensitive() {
112
- return new VldStringBool({
113
- ...this.options,
114
- caseSensitive: true
115
- });
116
- }
117
- /**
118
- * Create a new validator with case-insensitive matching (default)
119
- */
120
- caseInsensitive() {
121
- return new VldStringBool({
122
- ...this.options,
123
- caseSensitive: false
124
- });
125
- }
126
- }
127
- //# sourceMappingURL=string-bool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"string-bool.js","sourceRoot":"","sources":["../../src/validators/string-bool.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\nimport { getMessages } from '../locales';\n\n/**\n * Configuration for string boolean validation\n */\nexport interface StringBoolOptions {\n /** Custom truthy values (default: ['true', '1', 'yes', 'on', 'y', 'enabled']) */\n truthy?: readonly string[];\n /** Custom falsy values (default: ['false', '0', 'no', 'off', 'n', 'disabled']) */\n falsy?: readonly string[];\n /** Whether matching should be case-sensitive (default: false) */\n caseSensitive?: boolean;\n}\n\n/**\n * Default truthy and falsy value sets\n */\nconst DEFAULT_TRUTHY = ['true', '1', 'yes', 'on', 'y', 'enabled'] as const;\nconst DEFAULT_FALSY = ['false', '0', 'no', 'off', 'n', 'disabled'] as const;\n\n/**\n * Immutable string boolean validator for flexible boolean parsing\n * Supports string representations like \"true\", \"yes\", \"on\", \"1\", etc.\n */\nexport class VldStringBool extends VldBase<unknown, boolean> {\n private constructor(\n private readonly options: StringBoolOptions\n ) {\n super();\n }\n\n /**\n * Create a new string boolean validator\n */\n static create(options: StringBoolOptions = {}): VldStringBool {\n return new VldStringBool(options);\n }\n\n /**\n * Normalize a string value based on case sensitivity setting\n */\n private normalizeValue(value: string): string {\n return this.options.caseSensitive ? value : value.toLowerCase();\n }\n\n /**\n * Get the effective truthy values (custom or default)\n */\n private getTruthyValues(): readonly string[] {\n return this.options.truthy ?? DEFAULT_TRUTHY;\n }\n\n /**\n * Get the effective falsy values (custom or default)\n */\n private getFalsyValues(): readonly string[] {\n return this.options.falsy ?? DEFAULT_FALSY;\n }\n\n /**\n * Parse and validate a string boolean value\n */\n parse(value: unknown): boolean {\n // First, ensure we have a string\n if (typeof value !== 'string') {\n // Also accept actual boolean values for convenience\n if (typeof value === 'boolean') {\n return value;\n }\n throw new Error(\n getMessages().stringExpected(typeof value, 'string')\n );\n }\n\n const normalized = this.normalizeValue(value);\n const truthyValues = this.getTruthyValues();\n const falsyValues = this.getFalsyValues();\n\n // Normalize the value sets for comparison\n const normalizedTruthy = this.options.caseSensitive\n ? truthyValues\n : truthyValues.map(v => v.toLowerCase());\n\n const normalizedFalsy = this.options.caseSensitive\n ? falsyValues\n : falsyValues.map(v => v.toLowerCase());\n\n // Check if value is in truthy set\n if (normalizedTruthy.includes(normalized)) {\n return true;\n }\n\n // Check if value is in falsy set\n if (normalizedFalsy.includes(normalized)) {\n return false;\n }\n\n // Value is not recognized\n const allValidValues = [...normalizedTruthy, ...normalizedFalsy];\n throw new Error(\n getMessages().stringBoolExpected(\n this.options.caseSensitive ? allValidValues.join(', ') : allValidValues.join(', '),\n value\n )\n );\n }\n\n /**\n * Safely parse and validate a string boolean value\n */\n safeParse(value: unknown): ParseResult<boolean> {\n try {\n const result = this.parse(value);\n return { success: true, data: result };\n } catch (error) {\n return {\n success: false,\n error: error as Error\n };\n }\n }\n\n /**\n * Create a new validator with custom truthy values\n */\n withTruthy(values: readonly string[]): VldStringBool {\n return new VldStringBool({\n ...this.options,\n truthy: values\n });\n }\n\n /**\n * Create a new validator with custom falsy values\n */\n withFalsy(values: readonly string[]): VldStringBool {\n return new VldStringBool({\n ...this.options,\n falsy: values\n });\n }\n\n /**\n * Create a new validator with case-sensitive matching\n */\n caseSensitive(): VldStringBool {\n return new VldStringBool({\n ...this.options,\n caseSensitive: true\n });\n }\n\n /**\n * Create a new validator with case-insensitive matching (default)\n */\n caseInsensitive(): VldStringBool {\n return new VldStringBool({\n ...this.options,\n caseSensitive: false\n });\n }\n}\n"]}
@@ -1,120 +0,0 @@
1
- /**
2
- * Top-level string format validators
3
- * Part of Zod 4 API parity implementation
4
- * Provides convenient validators for common string formats
5
- */
6
- import { VldBase } from './base.js';
7
- import { VldString } from './string.js';
8
- /**
9
- * Pre-compiled regex patterns for performance
10
- */
11
- const REGEXES = {
12
- email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
13
- uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
14
- uuidv4: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
15
- uuidv6: /^[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
16
- uuidv7: /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
17
- hostname: /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$/,
18
- emoji: /^(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\u200D(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F))*$/u,
19
- base64: /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/,
20
- base64url: /^[A-Za-z0-9_-]*$/,
21
- hex: /^[0-9a-fA-F]*$/,
22
- jwt: /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/,
23
- nanoid: /^[A-Za-z0-9_-]{21}$/,
24
- cuid: /^c[^\s-]{8,}$/i,
25
- cuid2: /^[0-9a-z]+$/,
26
- ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,
27
- ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
28
- ipv6: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/,
29
- mac: /^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/,
30
- cidrv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(?:3[0-2]|[12]?[0-9])$/,
31
- cidrv6: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^(?:[0-9a-fA-F]{1,4}:){1,7}:\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,
32
- e164: /^\+[1-9]\d{1,14}$/,
33
- isoDate: /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/,
34
- isoTime: /^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?$/,
35
- isoDateTime: /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?Z?$/,
36
- md5: /^[a-f0-9]{32}$/i,
37
- sha1: /^[a-f0-9]{40}$/i,
38
- sha256: /^[a-f0-9]{64}$/i,
39
- sha384: /^[a-f0-9]{96}$/i,
40
- sha512: /^[a-f0-9]{128}$/i,
41
- };
42
- /**
43
- * Generic string format validator
44
- */
45
- class VldStringFormat extends VldBase {
46
- constructor(_format, _validator, _errorMessage) {
47
- super();
48
- this._format = _format;
49
- this._validator = _validator;
50
- this._errorMessage = _errorMessage;
51
- }
52
- static create(format, validator, errorMessage) {
53
- return new VldStringFormat(format, validator, errorMessage);
54
- }
55
- parse(value) {
56
- const result = VldString.create().parse(value);
57
- if (!this._validator(result)) {
58
- throw new Error(this._errorMessage || `Invalid ${this._format} format`);
59
- }
60
- return result;
61
- }
62
- safeParse(value) {
63
- const stringResult = VldString.create().safeParse(value);
64
- if (!stringResult.success) {
65
- return stringResult;
66
- }
67
- if (!this._validator(stringResult.data)) {
68
- return {
69
- success: false,
70
- error: new Error(this._errorMessage || `Invalid ${this._format} format`)
71
- };
72
- }
73
- return { success: true, data: stringResult.data };
74
- }
75
- }
76
- /**
77
- * Top-level string format validators
78
- */
79
- export const email = (options) => VldStringFormat.create('email', (val) => (options?.pattern ?? REGEXES.email).test(val));
80
- export const uuid = (options) => {
81
- const pattern = options?.version ? REGEXES[`uuid${options.version}`] : REGEXES.uuid;
82
- return VldStringFormat.create('uuid', (val) => pattern.test(val));
83
- };
84
- export const uuidv4 = () => VldStringFormat.create('uuid', (val) => REGEXES.uuidv4.test(val));
85
- export const hostname = () => VldStringFormat.create('hostname', (val) => REGEXES.hostname.test(val));
86
- export const emoji = () => VldStringFormat.create('emoji', (val) => REGEXES.emoji.test(val));
87
- export const base64 = () => VldStringFormat.create('base64', (val) => REGEXES.base64.test(val));
88
- export const base64url = () => VldStringFormat.create('base64url', (val) => REGEXES.base64url.test(val));
89
- export const hex = () => VldStringFormat.create('hex', (val) => REGEXES.hex.test(val));
90
- export const jwt = () => VldStringFormat.create('jwt', (val) => REGEXES.jwt.test(val));
91
- export const nanoid = () => VldStringFormat.create('nanoid', (val) => REGEXES.nanoid.test(val));
92
- export const cuid = () => VldStringFormat.create('cuid', (val) => REGEXES.cuid.test(val));
93
- export const cuid2 = () => VldStringFormat.create('cuid2', (val) => REGEXES.cuid2.test(val));
94
- export const ulid = () => VldStringFormat.create('ulid', (val) => REGEXES.ulid.test(val));
95
- export const ipv4 = () => VldStringFormat.create('ipv4', (val) => REGEXES.ipv4.test(val));
96
- export const ipv6 = () => VldStringFormat.create('ipv6', (val) => REGEXES.ipv6.test(val));
97
- export const mac = () => VldStringFormat.create('mac', (val) => REGEXES.mac.test(val));
98
- export const cidrv4 = () => VldStringFormat.create('cidrv4', (val) => REGEXES.cidrv4.test(val));
99
- export const cidrv6 = () => VldStringFormat.create('cidrv6', (val) => REGEXES.cidrv6.test(val));
100
- export const e164 = () => VldStringFormat.create('e164', (val) => REGEXES.e164.test(val));
101
- export const hash = (algorithm) => VldStringFormat.create('hash', (val) => REGEXES[algorithm]?.test(val) ?? false, `Invalid ${algorithm} hash`);
102
- /**
103
- * ISO date/time validators
104
- */
105
- export const iso = {
106
- date: () => VldStringFormat.create('date', (val) => REGEXES.isoDate.test(val)),
107
- time: () => VldStringFormat.create('time', (val) => REGEXES.isoTime.test(val)),
108
- dateTime: (_options) => VldStringFormat.create('datetime', (val) => REGEXES.isoDateTime.test(val)),
109
- duration: () => VldStringFormat.create('duration', (val) => /^P/.test(val)),
110
- };
111
- /**
112
- * Custom format validator
113
- */
114
- export const stringFormat = (name, validator) => {
115
- const fn = validator instanceof RegExp ? (val) => validator.test(val) : validator;
116
- return VldStringFormat.create(name, fn);
117
- };
118
- // Export regexes for external use
119
- export { REGEXES as regexes };
120
- //# sourceMappingURL=string-formats.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"string-formats.js","sourceRoot":"","sources":["../../src/validators/string-formats.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Top-level string format validators\n * Part of Zod 4 API parity implementation\n * Provides convenient validators for common string formats\n */\n\nimport { VldBase } from './base';\nimport { VldString } from './string';\nimport type { ParseResult } from './base';\n\n/**\n * Pre-compiled regex patterns for performance\n */\nconst REGEXES = {\n email: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n uuidv4: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n uuidv6: /^[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n uuidv7: /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n hostname: /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$/,\n emoji: /^(?:\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F)(?:\\u200D(?:\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F))*$/u,\n base64: /^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=)?$/,\n base64url: /^[A-Za-z0-9_-]*$/,\n hex: /^[0-9a-fA-F]*$/,\n jwt: /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]*$/,\n nanoid: /^[A-Za-z0-9_-]{21}$/,\n cuid: /^c[^\\s-]{8,}$/i,\n cuid2: /^[0-9a-z]+$/,\n ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,\n ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\n ipv6: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/,\n mac: /^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/,\n cidrv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(?:3[0-2]|[12]?[0-9])$/,\n cidrv6: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$|^(?:[0-9a-fA-F]{1,4}:){1,7}:\\/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,\n e164: /^\\+[1-9]\\d{1,14}$/,\n isoDate: /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\\d|3[01])$/,\n isoTime: /^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?$/,\n isoDateTime: /^\\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\\d|3[01])T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?Z?$/,\n md5: /^[a-f0-9]{32}$/i,\n sha1: /^[a-f0-9]{40}$/i,\n sha256: /^[a-f0-9]{64}$/i,\n sha384: /^[a-f0-9]{96}$/i,\n sha512: /^[a-f0-9]{128}$/i,\n} as const;\n\n/**\n * Generic string format validator\n */\nclass VldStringFormat extends VldBase<unknown, string> {\n public constructor(\n public readonly _format: string,\n public readonly _validator: (val: string) => boolean,\n public readonly _errorMessage?: string\n ) {\n super();\n }\n\n static create(\n format: string,\n validator: (val: string) => boolean,\n errorMessage?: string\n ): VldStringFormat {\n return new VldStringFormat(format, validator, errorMessage);\n }\n\n parse(value: unknown): string {\n const result = VldString.create().parse(value);\n\n if (!this._validator(result)) {\n throw new Error(\n this._errorMessage || `Invalid ${this._format} format`\n );\n }\n\n return result;\n }\n\n safeParse(value: unknown): ParseResult<string> {\n const stringResult = VldString.create().safeParse(value);\n if (!stringResult.success) {\n return stringResult;\n }\n\n if (!this._validator(stringResult.data)) {\n return {\n success: false,\n error: new Error(\n this._errorMessage || `Invalid ${this._format} format`\n )\n };\n }\n\n return { success: true, data: stringResult.data };\n }\n}\n\n/**\n * Top-level string format validators\n */\nexport const email = (options?: { pattern?: RegExp }): VldStringFormat =>\n VldStringFormat.create('email', (val) => (options?.pattern ?? REGEXES.email).test(val));\n\nexport const uuid = (options?: { version?: 'v4' | 'v6' | 'v7' }): VldStringFormat => {\n const pattern = options?.version ? REGEXES[`uuid${options.version}`] : REGEXES.uuid;\n return VldStringFormat.create('uuid', (val) => pattern.test(val));\n};\n\nexport const uuidv4 = (): VldStringFormat =>\n VldStringFormat.create('uuid', (val) => REGEXES.uuidv4.test(val));\n\nexport const hostname = (): VldStringFormat =>\n VldStringFormat.create('hostname', (val) => REGEXES.hostname.test(val));\n\nexport const emoji = (): VldStringFormat =>\n VldStringFormat.create('emoji', (val) => REGEXES.emoji.test(val));\n\nexport const base64 = (): VldStringFormat =>\n VldStringFormat.create('base64', (val) => REGEXES.base64.test(val));\n\nexport const base64url = (): VldStringFormat =>\n VldStringFormat.create('base64url', (val) => REGEXES.base64url.test(val));\n\nexport const hex = (): VldStringFormat =>\n VldStringFormat.create('hex', (val) => REGEXES.hex.test(val));\n\nexport const jwt = (): VldStringFormat =>\n VldStringFormat.create('jwt', (val) => REGEXES.jwt.test(val));\n\nexport const nanoid = (): VldStringFormat =>\n VldStringFormat.create('nanoid', (val) => REGEXES.nanoid.test(val));\n\nexport const cuid = (): VldStringFormat =>\n VldStringFormat.create('cuid', (val) => REGEXES.cuid.test(val));\n\nexport const cuid2 = (): VldStringFormat =>\n VldStringFormat.create('cuid2', (val) => REGEXES.cuid2.test(val));\n\nexport const ulid = (): VldStringFormat =>\n VldStringFormat.create('ulid', (val) => REGEXES.ulid.test(val));\n\nexport const ipv4 = (): VldStringFormat =>\n VldStringFormat.create('ipv4', (val) => REGEXES.ipv4.test(val));\n\nexport const ipv6 = (): VldStringFormat =>\n VldStringFormat.create('ipv6', (val) => REGEXES.ipv6.test(val));\n\nexport const mac = (): VldStringFormat =>\n VldStringFormat.create('mac', (val) => REGEXES.mac.test(val));\n\nexport const cidrv4 = (): VldStringFormat =>\n VldStringFormat.create('cidrv4', (val) => REGEXES.cidrv4.test(val));\n\nexport const cidrv6 = (): VldStringFormat =>\n VldStringFormat.create('cidrv6', (val) => REGEXES.cidrv6.test(val));\n\nexport const e164 = (): VldStringFormat =>\n VldStringFormat.create('e164', (val) => REGEXES.e164.test(val));\n\nexport const hash = (algorithm: 'md5' | 'sha1' | 'sha256' | 'sha384' | 'sha512'): VldStringFormat =>\n VldStringFormat.create('hash', (val) => (REGEXES as any)[algorithm]?.test(val) ?? false, `Invalid ${algorithm} hash`);\n\n/**\n * ISO date/time validators\n */\nexport const iso = {\n date: () => VldStringFormat.create('date', (val) => REGEXES.isoDate.test(val)),\n time: () => VldStringFormat.create('time', (val) => REGEXES.isoTime.test(val)),\n dateTime: (_options?: { offset?: boolean }) =>\n VldStringFormat.create('datetime', (val) => REGEXES.isoDateTime.test(val)),\n duration: () => VldStringFormat.create('duration', (val) => /^P/.test(val)),\n};\n\n/**\n * Custom format validator\n */\nexport const stringFormat = (\n name: string,\n validator: ((val: string) => boolean) | RegExp\n): VldStringFormat => {\n const fn = validator instanceof RegExp ? (val: string) => validator.test(val) : validator;\n return VldStringFormat.create(name, fn);\n};\n\n// Export regexes for external use\nexport { REGEXES as regexes };\n"]}
@@ -1,253 +0,0 @@
1
- import { VldBase } from './base.js';
2
- import { getMessages } from '../locales/index.js';
3
- import { isValidIPv6 } from '../utils/ip-validation.js';
4
- /**
5
- * Ultra-fast email validation using simplified regex for maximum performance
6
- */
7
- const FAST_EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8
- /**
9
- * Pre-compiled regex patterns for common validations
10
- * Optimized to prevent ReDoS attacks
11
- */
12
- const REGEX_PATTERNS = {
13
- email: FAST_EMAIL_REGEX, // Use simplified fast regex
14
- uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
15
- url: /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/, // Fixed unnecessary escapes
16
- ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
17
- // Simplified IPv6 regex to prevent ReDoS - splits into multiple checks for performance
18
- ipv6Basic: /^[0-9a-fA-F:]+$/,
19
- };
20
- /**
21
- * Immutable string validator with chainable methods
22
- */
23
- export class VldString extends VldBase {
24
- /**
25
- * Protected constructor to allow extension while maintaining immutability
26
- */
27
- constructor(config) {
28
- super();
29
- this.config = {
30
- checks: config?.checks || [],
31
- transforms: config?.transforms || [],
32
- errorMessage: config?.errorMessage
33
- };
34
- }
35
- /**
36
- * Create a new string validator
37
- */
38
- static create() {
39
- return new VldString();
40
- }
41
- /**
42
- * Parse and validate a string value - ultra-optimized
43
- */
44
- parse(value) {
45
- if (typeof value !== 'string') {
46
- throw new Error(this.config.errorMessage || getMessages().invalidString);
47
- }
48
- let result = value;
49
- // Apply transformations with optimized loop
50
- const transformsLength = this.config.transforms.length;
51
- for (let i = 0; i < transformsLength; i++) {
52
- result = this.config.transforms[i](result);
53
- }
54
- // Apply checks with optimized loop and early termination
55
- const checksLength = this.config.checks.length;
56
- for (let i = 0; i < checksLength; i++) {
57
- if (!this.config.checks[i](result)) {
58
- throw new Error(this.config.errorMessage || getMessages().invalidString);
59
- }
60
- }
61
- return result;
62
- }
63
- /**
64
- * Safely parse and validate a string value
65
- */
66
- safeParse(value) {
67
- try {
68
- return { success: true, data: this.parse(value) };
69
- }
70
- catch (error) {
71
- return { success: false, error: error };
72
- }
73
- }
74
- /**
75
- * Create a new validator with minimum length constraint
76
- */
77
- min(length, message) {
78
- return new VldString({
79
- checks: [...this.config.checks, (v) => v.length >= length],
80
- transforms: this.config.transforms,
81
- errorMessage: message || getMessages().stringMin(length)
82
- });
83
- }
84
- /**
85
- * Create a new validator with maximum length constraint
86
- */
87
- max(length, message) {
88
- return new VldString({
89
- checks: [...this.config.checks, (v) => v.length <= length],
90
- transforms: this.config.transforms,
91
- errorMessage: message || getMessages().stringMax(length)
92
- });
93
- }
94
- /**
95
- * Create a new validator with exact length constraint
96
- */
97
- length(length, message) {
98
- return new VldString({
99
- checks: [...this.config.checks, (v) => v.length === length],
100
- transforms: this.config.transforms,
101
- errorMessage: message || getMessages().stringLength(length)
102
- });
103
- }
104
- /**
105
- * Create a new validator that checks for valid email format
106
- */
107
- email(message) {
108
- return new VldString({
109
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.email.test(v)],
110
- transforms: this.config.transforms,
111
- errorMessage: message || getMessages().stringEmail
112
- });
113
- }
114
- /**
115
- * Create a new validator that checks for valid URL format
116
- */
117
- url(message) {
118
- return new VldString({
119
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.url.test(v)],
120
- transforms: this.config.transforms,
121
- errorMessage: message || getMessages().stringUrl
122
- });
123
- }
124
- /**
125
- * Create a new validator that checks for valid UUID format
126
- */
127
- uuid(message) {
128
- return new VldString({
129
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.uuid.test(v)],
130
- transforms: this.config.transforms,
131
- errorMessage: message || getMessages().stringUuid
132
- });
133
- }
134
- /**
135
- * Create a new validator with regex pattern matching
136
- */
137
- regex(pattern, message) {
138
- return new VldString({
139
- checks: [...this.config.checks, (v) => pattern.test(v)],
140
- transforms: this.config.transforms,
141
- errorMessage: message || getMessages().stringRegex
142
- });
143
- }
144
- /**
145
- * Create a new validator that trims whitespace
146
- */
147
- trim() {
148
- return new VldString({
149
- checks: this.config.checks,
150
- transforms: [...this.config.transforms, (v) => v.trim()],
151
- errorMessage: this.config.errorMessage
152
- });
153
- }
154
- /**
155
- * Create a new validator that converts to lowercase
156
- */
157
- toLowerCase() {
158
- return new VldString({
159
- checks: this.config.checks,
160
- transforms: [...this.config.transforms, (v) => v.toLowerCase()],
161
- errorMessage: this.config.errorMessage
162
- });
163
- }
164
- /**
165
- * Create a new validator that converts to uppercase
166
- */
167
- toUpperCase() {
168
- return new VldString({
169
- checks: this.config.checks,
170
- transforms: [...this.config.transforms, (v) => v.toUpperCase()],
171
- errorMessage: this.config.errorMessage
172
- });
173
- }
174
- /**
175
- * Create a new validator that checks if string starts with a substring
176
- */
177
- startsWith(str, message) {
178
- return new VldString({
179
- checks: [...this.config.checks, (v) => v.startsWith(str)],
180
- transforms: this.config.transforms,
181
- errorMessage: message || getMessages().stringStartsWith(str)
182
- });
183
- }
184
- /**
185
- * Create a new validator that checks if string ends with a substring
186
- */
187
- endsWith(str, message) {
188
- return new VldString({
189
- checks: [...this.config.checks, (v) => v.endsWith(str)],
190
- transforms: this.config.transforms,
191
- errorMessage: message || getMessages().stringEndsWith(str)
192
- });
193
- }
194
- /**
195
- * Create a new validator that checks if string includes a substring
196
- */
197
- includes(str, message) {
198
- return new VldString({
199
- checks: [...this.config.checks, (v) => v.includes(str)],
200
- transforms: this.config.transforms,
201
- errorMessage: message || getMessages().stringIncludes(str)
202
- });
203
- }
204
- /**
205
- * Create a new validator that checks for valid IP address (v4 or v6)
206
- */
207
- ip(message) {
208
- return new VldString({
209
- checks: [...this.config.checks, (v) => {
210
- // Prevent ReDoS: Check length before regex
211
- if (v.length > 100)
212
- return false;
213
- return REGEX_PATTERNS.ipv4.test(v) || isValidIPv6(v);
214
- }],
215
- transforms: this.config.transforms,
216
- errorMessage: message || getMessages().stringIp
217
- });
218
- }
219
- /**
220
- * Create a new validator that checks for valid IPv4 address
221
- */
222
- ipv4(message) {
223
- return new VldString({
224
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.ipv4.test(v)],
225
- transforms: this.config.transforms,
226
- errorMessage: message || getMessages().stringIpv4
227
- });
228
- }
229
- /**
230
- * Create a new validator that checks for valid IPv6 address
231
- */
232
- ipv6(message) {
233
- return new VldString({
234
- checks: [...this.config.checks, (v) => {
235
- // Use safe IPv6 validation to prevent ReDoS attacks
236
- return isValidIPv6(v);
237
- }],
238
- transforms: this.config.transforms,
239
- errorMessage: message || getMessages().stringIpv6
240
- });
241
- }
242
- /**
243
- * Create a new validator that ensures string is not empty
244
- */
245
- nonempty(message) {
246
- return new VldString({
247
- checks: [...this.config.checks, (v) => v.length > 0],
248
- transforms: this.config.transforms,
249
- errorMessage: message || getMessages().stringEmpty
250
- });
251
- }
252
- }
253
- //# sourceMappingURL=string.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/validators/string.ts"],"names":[],"mappings":"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","sourcesContent":["import { VldBase, ParseResult } from './base';\r\nimport { getMessages } from '../locales';\r\nimport { isValidIPv6 } from '../utils/ip-validation';\r\n\r\n/**\r\n * Ultra-fast email validation using simplified regex for maximum performance\r\n */\r\nconst FAST_EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n\r\n/**\r\n * Pre-compiled regex patterns for common validations\r\n * Optimized to prevent ReDoS attacks\r\n */\r\nconst REGEX_PATTERNS = {\r\n email: FAST_EMAIL_REGEX, // Use simplified fast regex\r\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\r\n url: /^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/, // Fixed unnecessary escapes\r\n ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\r\n // Simplified IPv6 regex to prevent ReDoS - splits into multiple checks for performance\r\n ipv6Basic: /^[0-9a-fA-F:]+$/,\r\n};\r\n\r\n// BUG-NEW-001 FIX: IPv6 validation moved to shared utility (src/utils/ip-validation.ts)\r\n// to eliminate code duplication between string.ts and coercion/string.ts\r\n\r\n/**\r\n * Type for string validation check functions\r\n */\r\ntype StringCheck = (value: string) => boolean;\r\n\r\n/**\r\n * Type for string transformation functions\r\n */\r\ntype StringTransform = (value: string) => string;\r\n\r\n/**\r\n * Configuration for string validator\r\n */\r\ninterface StringValidatorConfig {\r\n readonly checks: ReadonlyArray<StringCheck>;\r\n readonly transforms: ReadonlyArray<StringTransform>;\r\n readonly errorMessage?: string;\r\n}\r\n\r\n/**\r\n * Immutable string validator with chainable methods\r\n */\r\nexport class VldString extends VldBase<string, string> {\r\n protected readonly config: StringValidatorConfig;\r\n \r\n /**\r\n * Protected constructor to allow extension while maintaining immutability\r\n */\r\n protected constructor(config?: Partial<StringValidatorConfig>) {\r\n super();\r\n this.config = {\r\n checks: config?.checks || [],\r\n transforms: config?.transforms || [],\r\n errorMessage: config?.errorMessage\r\n };\r\n }\r\n \r\n /**\r\n * Create a new string validator\r\n */\r\n static create(): VldString {\r\n return new VldString();\r\n }\r\n \r\n /**\r\n * Parse and validate a string value - ultra-optimized\r\n */\r\n parse(value: unknown): string {\r\n if (typeof value !== 'string') {\r\n throw new Error(this.config.errorMessage || getMessages().invalidString);\r\n }\r\n \r\n let result = value;\r\n \r\n // Apply transformations with optimized loop\r\n const transformsLength = this.config.transforms.length;\r\n for (let i = 0; i < transformsLength; i++) {\r\n result = this.config.transforms[i](result);\r\n }\r\n \r\n // Apply checks with optimized loop and early termination\r\n const checksLength = this.config.checks.length;\r\n for (let i = 0; i < checksLength; i++) {\r\n if (!this.config.checks[i](result)) {\r\n throw new Error(this.config.errorMessage || getMessages().invalidString);\r\n }\r\n }\r\n \r\n return result;\r\n }\r\n \r\n /**\r\n * Safely parse and validate a string value\r\n */\r\n safeParse(value: unknown): ParseResult<string> {\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 length constraint\r\n */\r\n min(length: number, message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.length >= length],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringMin(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): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.length <= length],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringMax(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): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.length === length],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringLength(length)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid email format\r\n */\r\n email(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => REGEX_PATTERNS.email.test(v)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringEmail\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid URL format\r\n */\r\n url(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => REGEX_PATTERNS.url.test(v)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringUrl\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid UUID format\r\n */\r\n uuid(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => REGEX_PATTERNS.uuid.test(v)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringUuid\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator with regex pattern matching\r\n */\r\n regex(pattern: RegExp, message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => pattern.test(v)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringRegex\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that trims whitespace\r\n */\r\n trim(): VldString {\r\n return new VldString({\r\n checks: this.config.checks,\r\n transforms: [...this.config.transforms, (v: string) => v.trim()],\r\n errorMessage: this.config.errorMessage\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that converts to lowercase\r\n */\r\n toLowerCase(): VldString {\r\n return new VldString({\r\n checks: this.config.checks,\r\n transforms: [...this.config.transforms, (v: string) => v.toLowerCase()],\r\n errorMessage: this.config.errorMessage\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that converts to uppercase\r\n */\r\n toUpperCase(): VldString {\r\n return new VldString({\r\n checks: this.config.checks,\r\n transforms: [...this.config.transforms, (v: string) => v.toUpperCase()],\r\n errorMessage: this.config.errorMessage\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks if string starts with a substring\r\n */\r\n startsWith(str: string, message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.startsWith(str)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringStartsWith(str)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks if string ends with a substring\r\n */\r\n endsWith(str: string, message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.endsWith(str)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringEndsWith(str)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks if string includes a substring\r\n */\r\n includes(str: string, message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.includes(str)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringIncludes(str)\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid IP address (v4 or v6)\r\n */\r\n ip(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => {\r\n // Prevent ReDoS: Check length before regex\r\n if (v.length > 100) return false;\r\n return REGEX_PATTERNS.ipv4.test(v) || isValidIPv6(v);\r\n }],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringIp\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid IPv4 address\r\n */\r\n ipv4(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => REGEX_PATTERNS.ipv4.test(v)],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringIpv4\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that checks for valid IPv6 address\r\n */\r\n ipv6(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => {\r\n // Use safe IPv6 validation to prevent ReDoS attacks\r\n return isValidIPv6(v);\r\n }],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringIpv6\r\n });\r\n }\r\n \r\n /**\r\n * Create a new validator that ensures string is not empty\r\n */\r\n nonempty(message?: string): VldString {\r\n return new VldString({\r\n checks: [...this.config.checks, (v: string) => v.length > 0],\r\n transforms: this.config.transforms,\r\n errorMessage: message || getMessages().stringEmpty\r\n });\r\n }\r\n}"]}