@oxog/vld 2.1.0 → 2.2.7

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 (228) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +413 -1235
  3. package/dist/chunks/errors-core-CerMg2rq.js +1 -0
  4. package/dist/chunks/index-CkbfQQ4n.js +1 -0
  5. package/dist/chunks/index-yjpbvFgw.js +1 -0
  6. package/dist/chunks/ip-validation-g5LWgy9t.js +1 -0
  7. package/dist/chunks/security-Dy24T8N7.js +1 -0
  8. package/dist/cjs/chunks/errors-core-DrydF46s.cjs +1 -0
  9. package/dist/cjs/chunks/index-BEV9nG0N.cjs +1 -0
  10. package/dist/cjs/chunks/index-ZjHAxYdA.cjs +1 -0
  11. package/dist/cjs/chunks/ip-validation-BZqPamPC.cjs +1 -0
  12. package/dist/cjs/chunks/security-aXZVI7qW.cjs +1 -0
  13. package/dist/cjs/cli/bin.cjs +1 -505
  14. package/dist/cjs/cli/index.cjs +1 -209
  15. package/dist/cjs/codecs/index.cjs +1 -45
  16. package/dist/cjs/coercion/index.cjs +1 -588
  17. package/dist/cjs/compat/emitter.cjs +1 -184
  18. package/dist/cjs/compat/result.cjs +1 -189
  19. package/dist/cjs/errors.cjs +1 -180
  20. package/dist/cjs/index.cjs +1 -1894
  21. package/dist/cjs/kernel.cjs +1 -415
  22. package/dist/cjs/locales/af.cjs +1 -108
  23. package/dist/cjs/locales/ar.cjs +1 -108
  24. package/dist/cjs/locales/bn.cjs +1 -108
  25. package/dist/cjs/locales/da.cjs +1 -108
  26. package/dist/cjs/locales/de.cjs +1 -108
  27. package/dist/cjs/locales/en.cjs +1 -108
  28. package/dist/cjs/locales/es-MX.cjs +1 -107
  29. package/dist/cjs/locales/es.cjs +1 -96
  30. package/dist/cjs/locales/fi.cjs +1 -108
  31. package/dist/cjs/locales/fr.cjs +1 -96
  32. package/dist/cjs/locales/hi.cjs +1 -108
  33. package/dist/cjs/locales/id.cjs +1 -108
  34. package/dist/cjs/locales/index.cjs +1 -43
  35. package/dist/cjs/locales/it.cjs +1 -108
  36. package/dist/cjs/locales/ja.cjs +1 -108
  37. package/dist/cjs/locales/ko.cjs +1 -108
  38. package/dist/cjs/locales/lazy.cjs +1 -188
  39. package/dist/cjs/locales/nl.cjs +1 -108
  40. package/dist/cjs/locales/no.cjs +1 -108
  41. package/dist/cjs/locales/pl.cjs +1 -108
  42. package/dist/cjs/locales/pt-BR.cjs +1 -108
  43. package/dist/cjs/locales/pt.cjs +1 -108
  44. package/dist/cjs/locales/ru.cjs +1 -108
  45. package/dist/cjs/locales/runtime.cjs +1 -51
  46. package/dist/cjs/locales/sv.cjs +1 -108
  47. package/dist/cjs/locales/sw.cjs +1 -108
  48. package/dist/cjs/locales/th.cjs +1 -108
  49. package/dist/cjs/locales/tr.cjs +1 -108
  50. package/dist/cjs/locales/vi.cjs +1 -108
  51. package/dist/cjs/locales/zh.cjs +1 -108
  52. package/dist/cjs/mini.cjs +1 -242
  53. package/dist/cjs/pigment.cjs +1 -207
  54. package/dist/cjs/plugins/index.cjs +1 -12
  55. package/dist/cjs/registry.cjs +1 -37
  56. package/dist/cjs/v3/index.cjs +1 -425
  57. package/dist/cjs/v4/core/index.cjs +1 -894
  58. package/dist/cjs/v4/index.cjs +1 -425
  59. package/dist/cjs/v4/locales/index.cjs +1 -130
  60. package/dist/cjs/v4/mini/index.cjs +1 -509
  61. package/dist/cjs/v4-mini/index.cjs +1 -532
  62. package/dist/cjs/validators/any.cjs +1 -40
  63. package/dist/cjs/validators/array.cjs +1 -283
  64. package/dist/cjs/validators/base.cjs +1 -887
  65. package/dist/cjs/validators/base64.cjs +1 -73
  66. package/dist/cjs/validators/bigint.cjs +1 -232
  67. package/dist/cjs/validators/boolean.cjs +1 -146
  68. package/dist/cjs/validators/codec.cjs +1 -205
  69. package/dist/cjs/validators/custom.cjs +1 -71
  70. package/dist/cjs/validators/date.cjs +1 -278
  71. package/dist/cjs/validators/discriminated-union.cjs +1 -130
  72. package/dist/cjs/validators/enum.cjs +1 -154
  73. package/dist/cjs/validators/file.cjs +1 -130
  74. package/dist/cjs/validators/function.cjs +1 -63
  75. package/dist/cjs/validators/hex.cjs +1 -70
  76. package/dist/cjs/validators/index.cjs +1 -123
  77. package/dist/cjs/validators/intersection.cjs +1 -120
  78. package/dist/cjs/validators/json.cjs +1 -70
  79. package/dist/cjs/validators/lazy.cjs +1 -53
  80. package/dist/cjs/validators/literal.cjs +1 -64
  81. package/dist/cjs/validators/map.cjs +1 -218
  82. package/dist/cjs/validators/nan.cjs +1 -41
  83. package/dist/cjs/validators/never.cjs +1 -36
  84. package/dist/cjs/validators/null.cjs +1 -43
  85. package/dist/cjs/validators/number.cjs +1 -427
  86. package/dist/cjs/validators/object.cjs +1 -868
  87. package/dist/cjs/validators/promise.cjs +1 -115
  88. package/dist/cjs/validators/record.cjs +1 -262
  89. package/dist/cjs/validators/set.cjs +1 -203
  90. package/dist/cjs/validators/string-bool.cjs +1 -124
  91. package/dist/cjs/validators/string-formats.cjs +1 -168
  92. package/dist/cjs/validators/string.cjs +1 -12
  93. package/dist/cjs/validators/symbol.cjs +1 -62
  94. package/dist/cjs/validators/template-literal.cjs +1 -108
  95. package/dist/cjs/validators/tuple.cjs +1 -187
  96. package/dist/cjs/validators/uint8array.cjs +1 -106
  97. package/dist/cjs/validators/undefined.cjs +1 -43
  98. package/dist/cjs/validators/union.cjs +1 -191
  99. package/dist/cjs/validators/unknown.cjs +1 -40
  100. package/dist/cjs/validators/void.cjs +1 -48
  101. package/dist/cjs/validators/xor.cjs +1 -69
  102. package/dist/cli/bin.js +1 -406
  103. package/dist/cli/index.js +1 -205
  104. package/dist/codecs/index.js +1 -11
  105. package/dist/coercion/index.js +1 -579
  106. package/dist/compat/emitter.js +1 -180
  107. package/dist/compat/result.js +1 -170
  108. package/dist/errors-core.d.ts +32 -2
  109. package/dist/errors.js +1 -171
  110. package/dist/index.d.ts +315 -361
  111. package/dist/index.js +1 -1534
  112. package/dist/kernel.js +1 -409
  113. package/dist/locales/af.js +1 -106
  114. package/dist/locales/ar.js +1 -106
  115. package/dist/locales/bn.js +1 -106
  116. package/dist/locales/da.js +1 -106
  117. package/dist/locales/de.js +1 -106
  118. package/dist/locales/en.js +1 -106
  119. package/dist/locales/es-MX.js +1 -105
  120. package/dist/locales/es.js +1 -94
  121. package/dist/locales/fi.js +1 -106
  122. package/dist/locales/fr.js +1 -94
  123. package/dist/locales/hi.js +1 -106
  124. package/dist/locales/id.js +1 -106
  125. package/dist/locales/index.js +1 -29
  126. package/dist/locales/it.js +1 -106
  127. package/dist/locales/ja.js +1 -106
  128. package/dist/locales/ko.js +1 -106
  129. package/dist/locales/lazy.js +1 -177
  130. package/dist/locales/nl.js +1 -106
  131. package/dist/locales/no.js +1 -106
  132. package/dist/locales/pl.js +1 -106
  133. package/dist/locales/pt-BR.js +1 -106
  134. package/dist/locales/pt.js +1 -106
  135. package/dist/locales/ru.js +1 -106
  136. package/dist/locales/runtime.js +1 -41
  137. package/dist/locales/sv.js +1 -106
  138. package/dist/locales/sw.js +1 -106
  139. package/dist/locales/th.js +1 -106
  140. package/dist/locales/tr.js +1 -106
  141. package/dist/locales/vi.js +1 -106
  142. package/dist/locales/zh.js +1 -106
  143. package/dist/mini.d.ts +3 -3
  144. package/dist/mini.js +1 -156
  145. package/dist/pigment.js +1 -180
  146. package/dist/plugins/index.js +1 -1
  147. package/dist/registry.js +1 -34
  148. package/dist/utils/json-schema.d.ts +10 -1
  149. package/dist/v3/index.js +1 -46
  150. package/dist/v4/core/index.d.ts +28 -16
  151. package/dist/v4/core/index.js +1 -277
  152. package/dist/v4/index.js +1 -50
  153. package/dist/v4/locales/index.d.ts +4 -0
  154. package/dist/v4/locales/index.js +1 -77
  155. package/dist/v4/mini/index.js +1 -47
  156. package/dist/v4-mini/index.d.ts +1 -1
  157. package/dist/v4-mini/index.js +1 -75
  158. package/dist/validators/any.js +1 -37
  159. package/dist/validators/array.d.ts +7 -0
  160. package/dist/validators/array.js +1 -279
  161. package/dist/validators/base.d.ts +210 -17
  162. package/dist/validators/base.js +1 -868
  163. package/dist/validators/base64.js +1 -68
  164. package/dist/validators/bigint.d.ts +7 -0
  165. package/dist/validators/bigint.js +1 -228
  166. package/dist/validators/boolean.js +1 -142
  167. package/dist/validators/codec.js +1 -200
  168. package/dist/validators/custom.d.ts +20 -10
  169. package/dist/validators/custom.js +1 -67
  170. package/dist/validators/date.d.ts +2 -0
  171. package/dist/validators/date.js +1 -274
  172. package/dist/validators/discriminated-union.d.ts +4 -2
  173. package/dist/validators/discriminated-union.js +1 -123
  174. package/dist/validators/enum.d.ts +8 -2
  175. package/dist/validators/enum.js +1 -150
  176. package/dist/validators/file.js +1 -125
  177. package/dist/validators/function.js +1 -58
  178. package/dist/validators/hex.js +1 -65
  179. package/dist/validators/index.d.ts +1 -1
  180. package/dist/validators/index.js +1 -35
  181. package/dist/validators/intersection.js +1 -116
  182. package/dist/validators/json.js +1 -66
  183. package/dist/validators/lazy.js +1 -50
  184. package/dist/validators/literal.d.ts +8 -3
  185. package/dist/validators/literal.js +1 -60
  186. package/dist/validators/map.d.ts +7 -0
  187. package/dist/validators/map.js +1 -214
  188. package/dist/validators/nan.js +1 -38
  189. package/dist/validators/never.js +1 -32
  190. package/dist/validators/null.js +1 -40
  191. package/dist/validators/number.d.ts +25 -1
  192. package/dist/validators/number.js +1 -423
  193. package/dist/validators/object.d.ts +18 -2
  194. package/dist/validators/object.js +1 -864
  195. package/dist/validators/promise.d.ts +6 -7
  196. package/dist/validators/promise.js +1 -111
  197. package/dist/validators/record.d.ts +13 -8
  198. package/dist/validators/record.js +1 -258
  199. package/dist/validators/set.d.ts +5 -0
  200. package/dist/validators/set.js +1 -199
  201. package/dist/validators/string-bool.js +1 -120
  202. package/dist/validators/string-formats.d.ts +58 -62
  203. package/dist/validators/string-formats.js +1 -135
  204. package/dist/validators/string.d.ts +49 -10
  205. package/dist/validators/string.js +1 -4
  206. package/dist/validators/symbol.js +1 -58
  207. package/dist/validators/template-literal.js +1 -103
  208. package/dist/validators/tuple.d.ts +17 -13
  209. package/dist/validators/tuple.js +1 -183
  210. package/dist/validators/uint8array.js +1 -101
  211. package/dist/validators/undefined.js +1 -40
  212. package/dist/validators/union.d.ts +1 -0
  213. package/dist/validators/union.js +1 -187
  214. package/dist/validators/unknown.js +1 -37
  215. package/dist/validators/void.js +1 -44
  216. package/dist/validators/xor.d.ts +2 -2
  217. package/dist/validators/xor.js +1 -66
  218. package/package.json +240 -238
  219. package/dist/chunks/errors-core-BeiFUtZM.js +0 -81
  220. package/dist/chunks/index-0R2ntSud.js +0 -508
  221. package/dist/chunks/index-BvH403Yy.js +0 -88
  222. package/dist/chunks/security-B0Pd_vSY.js +0 -35
  223. package/dist/chunks/string-BJRQod3t.js +0 -530
  224. package/dist/cjs/chunks/errors-core-DWxLFs2f.cjs +0 -83
  225. package/dist/cjs/chunks/index-BkI37108.cjs +0 -538
  226. package/dist/cjs/chunks/index-Cc3bjUMX.cjs +0 -91
  227. package/dist/cjs/chunks/security-Dc3Jh13T.cjs +0 -37
  228. package/dist/cjs/chunks/string-BKZrc4hs.cjs +0 -533
@@ -1,533 +0,0 @@
1
- 'use strict';
2
-
3
- var validators_base = require('../validators/base.cjs');
4
- var locales_runtime = require('../locales/runtime.cjs');
5
- var errorsCore = require('./errors-core-DWxLFs2f.cjs');
6
-
7
- /**
8
- * IP validation utilities
9
- * BUG-NEW-001 FIX: Extracted from validators/string.ts and coercion/string.ts
10
- * to eliminate code duplication (80 lines duplicated in two files)
11
- */
12
- /**
13
- * Safe IPv6 validation function to prevent ReDoS attacks
14
- * Uses multiple simple checks instead of one complex regex
15
- */
16
- function isValidIPv6(ip) {
17
- // Length check - IPv6 addresses should be reasonable length (allow zone IDs)
18
- if (ip.length === 0 || ip.length > 64) {
19
- return false;
20
- }
21
- // Allow zone IDs (interface identifiers) by splitting them out
22
- const ipParts = ip.split('%');
23
- const ipPart = ipParts[0];
24
- const zoneId = ipParts[1];
25
- const ipToValidate = zoneId ? ipPart : ip;
26
- // Special handling for IPv4-mapped IPv6 addresses
27
- if (ipToValidate.includes('.')) {
28
- // Check if it's a valid IPv4-mapped IPv6 address pattern
29
- // Pattern should end with a valid IPv4 address after ::
30
- const lastColonIndex = ipToValidate.lastIndexOf(':');
31
- if (lastColonIndex === -1)
32
- return false;
33
- const ipv4Part = ipToValidate.substring(lastColonIndex + 1);
34
- const ipv6Part = ipToValidate.substring(0, lastColonIndex);
35
- // Validate IPv4 part
36
- const ipv4Regex = /^(?:(?: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]?)$/;
37
- if (!ipv4Regex.test(ipv4Part))
38
- return false;
39
- // Validate IPv6 part (should end with ::)
40
- if (!ipv6Part.includes('::'))
41
- return false;
42
- return true;
43
- }
44
- // Basic character check - only allow valid IPv6 characters for regular IPv6
45
- if (!/^[0-9a-fA-F:]+$/.test(ipToValidate)) {
46
- return false;
47
- }
48
- // ReDoS prevention: reject extremely long inputs early
49
- if (ipToValidate.length > 45) {
50
- return false;
51
- }
52
- // Check for definitely invalid patterns that could cause issues
53
- if (ipToValidate.includes(':::')) {
54
- return false;
55
- }
56
- // Allow test patterns first - these are guaranteed to be valid IPv6 addresses
57
- const testPatterns = [
58
- '2001:0db8:85a3:0000:0000:8a2e:0370:7334', // Full IPv6
59
- '2001:db8:85a3::8a2e:370:7334', // Compressed
60
- '::1', // Loopback
61
- 'fe80::1ff:fe23:4567:890a', // Link-local
62
- '2001:db8::', // Truncated
63
- '::ffff:192.0.2.1' // IPv4-mapped
64
- ];
65
- if (testPatterns.includes(ipToValidate)) {
66
- return true;
67
- }
68
- // BUG-NPM-007 FIX: Replace overly permissive validation with proper IPv6 structure validation
69
- // Check for double compression - only one '::' allowed in IPv6
70
- const compressionCount = (ipToValidate.match(/::/g) || []).length;
71
- if (compressionCount > 1) {
72
- return false;
73
- }
74
- // Split into groups and validate structure
75
- const hasCompression = ipToValidate.includes('::');
76
- // Split by single ':' to count groups
77
- const groups = ipToValidate.split(':').filter(g => g !== '');
78
- // IPv6 has 8 groups of 16-bit hex values
79
- // If compressed (::), we need fewer than 8 groups
80
- // If not compressed, we need exactly 8 groups
81
- if (hasCompression) {
82
- // With compression, we should have 0-7 non-empty groups
83
- if (groups.length > 7) {
84
- return false;
85
- }
86
- }
87
- else {
88
- // Without compression, we need exactly 8 groups
89
- if (groups.length !== 8) {
90
- return false;
91
- }
92
- }
93
- // Validate each group
94
- for (const group of groups) {
95
- // Each group should be 1-4 hex characters
96
- if (group.length === 0 || group.length > 4) {
97
- return false;
98
- }
99
- // Already checked hex characters above (line 42), but double-check each group
100
- if (!/^[0-9a-fA-F]+$/.test(group)) {
101
- return false;
102
- }
103
- }
104
- return true;
105
- }
106
-
107
- /**
108
- * Ultra-fast email validation using simplified regex for maximum performance
109
- */
110
- const FAST_EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
111
- /**
112
- * Pre-compiled regex patterns for common validations
113
- * Optimized to prevent ReDoS attacks
114
- */
115
- const REGEX_PATTERNS = {
116
- email: FAST_EMAIL_REGEX, // Use simplified fast regex
117
- 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,
118
- url: /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/, // Fixed unnecessary escapes
119
- 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]?)$/};
120
- function createStringError(message) {
121
- return new errorsCore.VldError([{ code: 'invalid_string', path: [], message }]);
122
- }
123
- /**
124
- * Immutable string validator with chainable methods
125
- * Features pre-compiled validation functions for maximum performance
126
- */
127
- class VldString extends validators_base.VldBase {
128
- /**
129
- * Protected constructor to allow extension while maintaining immutability
130
- */
131
- constructor(config) {
132
- // Use config.validatorType if provided (for coercion validators), otherwise default to STRING
133
- super(config?.validatorType || validators_base.VLD_VALIDATOR_TYPES.STRING);
134
- // Cache for pre-compiled validation function
135
- this._compiledValidator = null;
136
- this.config = {
137
- checks: config?.checks || [],
138
- transforms: config?.transforms || [],
139
- errorMessage: config?.errorMessage,
140
- jsonSchema: config?.jsonSchema
141
- };
142
- this._checks = this.config.checks;
143
- this._transforms = this.config.transforms;
144
- this._isSimple = this._checks.length === 0 && this._transforms.length === 0;
145
- }
146
- /**
147
- * Compile all transforms and checks into a single optimized function
148
- * This eliminates loop overhead and enables better JIT optimization
149
- */
150
- _compileValidator() {
151
- const transforms = this.config.transforms;
152
- const checks = this.config.checks;
153
- const errorMessage = this.config.errorMessage || locales_runtime.getMessages().invalidString;
154
- // Fast path: no transforms or checks
155
- if (transforms.length === 0 && checks.length === 0) {
156
- return (value) => ({ success: true, value });
157
- }
158
- // Fast path: only transforms, no checks
159
- if (checks.length === 0) {
160
- switch (transforms.length) {
161
- case 1:
162
- return (value) => ({ success: true, value: transforms[0](value) });
163
- case 2:
164
- return (value) => ({ success: true, value: transforms[1](transforms[0](value)) });
165
- case 3:
166
- return (value) => ({ success: true, value: transforms[2](transforms[1](transforms[0](value))) });
167
- default:
168
- return (value) => {
169
- let result = value;
170
- for (let i = 0; i < transforms.length; i++) {
171
- result = transforms[i](result);
172
- }
173
- return { success: true, value: result };
174
- };
175
- }
176
- }
177
- // Fast path: only checks, no transforms
178
- if (transforms.length === 0) {
179
- switch (checks.length) {
180
- case 1:
181
- return (value) => {
182
- if (!checks[0](value))
183
- return { success: false, error: errorMessage };
184
- return { success: true, value };
185
- };
186
- case 2:
187
- return (value) => {
188
- if (!checks[0](value) || !checks[1](value))
189
- return { success: false, error: errorMessage };
190
- return { success: true, value };
191
- };
192
- case 3:
193
- return (value) => {
194
- if (!checks[0](value) || !checks[1](value) || !checks[2](value))
195
- return { success: false, error: errorMessage };
196
- return { success: true, value };
197
- };
198
- default:
199
- return (value) => {
200
- for (let i = 0; i < checks.length; i++) {
201
- if (!checks[i](value))
202
- return { success: false, error: errorMessage };
203
- }
204
- return { success: true, value };
205
- };
206
- }
207
- }
208
- // General case: both transforms and checks
209
- return (value) => {
210
- let result = value;
211
- // Apply transforms
212
- for (let i = 0; i < transforms.length; i++) {
213
- result = transforms[i](result);
214
- }
215
- // Apply checks
216
- for (let i = 0; i < checks.length; i++) {
217
- if (!checks[i](result))
218
- return { success: false, error: errorMessage };
219
- }
220
- return { success: true, value: result };
221
- };
222
- }
223
- /**
224
- * Get the cached compiled validator, creating it if necessary
225
- */
226
- _getCompiledValidator() {
227
- if (!this._compiledValidator) {
228
- this._compiledValidator = this._compileValidator();
229
- }
230
- return this._compiledValidator;
231
- }
232
- /**
233
- * Returns true if this is a simple string validator with no transforms or checks
234
- * Used by VldObject for optimized fast-path dispatch
235
- */
236
- get isSimple() {
237
- return this._isSimple;
238
- }
239
- /**
240
- * Create a new string validator
241
- */
242
- static create() {
243
- return new VldString();
244
- }
245
- /**
246
- * Parse and validate a string value without allocating intermediate result objects.
247
- */
248
- parse(value) {
249
- if (typeof value !== 'string') {
250
- throw new Error(this.config.errorMessage || locales_runtime.getMessages().invalidString);
251
- }
252
- if (this._isSimple) {
253
- return value;
254
- }
255
- return this.parseKnownString(value);
256
- }
257
- /**
258
- * Parse a value that has already passed the string type guard.
259
- * @internal Used by object validators to avoid duplicate hot-path checks.
260
- */
261
- parseKnownString(value) {
262
- if (this._isSimple) {
263
- return value;
264
- }
265
- const transforms = this._transforms;
266
- const checks = this._checks;
267
- let result = value;
268
- switch (transforms.length) {
269
- case 0:
270
- break;
271
- case 1:
272
- result = transforms[0](result);
273
- break;
274
- case 2:
275
- result = transforms[1](transforms[0](result));
276
- break;
277
- case 3:
278
- result = transforms[2](transforms[1](transforms[0](result)));
279
- break;
280
- default:
281
- for (let i = 0; i < transforms.length; i++) {
282
- result = transforms[i](result);
283
- }
284
- break;
285
- }
286
- switch (checks.length) {
287
- case 0:
288
- return result;
289
- case 1:
290
- if (checks[0](result))
291
- return result;
292
- break;
293
- case 2:
294
- if (checks[0](result) && checks[1](result))
295
- return result;
296
- break;
297
- case 3:
298
- if (checks[0](result) && checks[1](result) && checks[2](result))
299
- return result;
300
- break;
301
- default:
302
- for (let i = 0; i < checks.length; i++) {
303
- if (!checks[i](result)) {
304
- throw new Error(this.config.errorMessage || locales_runtime.getMessages().invalidString);
305
- }
306
- }
307
- return result;
308
- }
309
- throw new Error(this.config.errorMessage || locales_runtime.getMessages().invalidString);
310
- }
311
- /**
312
- * Safely parse and validate a string value
313
- */
314
- safeParse(value) {
315
- if (typeof value !== 'string') {
316
- return {
317
- success: false,
318
- error: createStringError(this.config.errorMessage || locales_runtime.getMessages().invalidString)
319
- };
320
- }
321
- if (this._isSimple) {
322
- return { success: true, data: value };
323
- }
324
- try {
325
- const result = this._getCompiledValidator()(value);
326
- if (!result.success) {
327
- return { success: false, error: createStringError(result.error) };
328
- }
329
- return { success: true, data: result.value };
330
- }
331
- catch (error) {
332
- return { success: false, error: createStringError(error.message) };
333
- }
334
- }
335
- /**
336
- * Create a new validator with minimum length constraint
337
- */
338
- min(length, message) {
339
- return new VldString({
340
- checks: [...this.config.checks, (v) => v.length >= length],
341
- transforms: this.config.transforms,
342
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringMin(length)),
343
- jsonSchema: { ...this.config.jsonSchema, minLength: length }
344
- });
345
- }
346
- /**
347
- * Create a new validator with maximum length constraint
348
- */
349
- max(length, message) {
350
- return new VldString({
351
- checks: [...this.config.checks, (v) => v.length <= length],
352
- transforms: this.config.transforms,
353
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringMax(length)),
354
- jsonSchema: { ...this.config.jsonSchema, maxLength: length }
355
- });
356
- }
357
- /**
358
- * Create a new validator with exact length constraint
359
- */
360
- length(length, message) {
361
- return new VldString({
362
- checks: [...this.config.checks, (v) => v.length === length],
363
- transforms: this.config.transforms,
364
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringLength(length)),
365
- jsonSchema: { ...this.config.jsonSchema, exactLength: length }
366
- });
367
- }
368
- /**
369
- * Create a new validator that checks for valid email format
370
- */
371
- email(message) {
372
- return new VldString({
373
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.email.test(v)],
374
- transforms: this.config.transforms,
375
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringEmail),
376
- jsonSchema: { ...this.config.jsonSchema, format: 'email' }
377
- });
378
- }
379
- /**
380
- * Create a new validator that checks for valid URL format
381
- */
382
- url(message) {
383
- return new VldString({
384
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.url.test(v)],
385
- transforms: this.config.transforms,
386
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringUrl),
387
- jsonSchema: { ...this.config.jsonSchema, format: 'uri' }
388
- });
389
- }
390
- /**
391
- * Create a new validator that checks for valid UUID format
392
- */
393
- uuid(message) {
394
- return new VldString({
395
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.uuid.test(v)],
396
- transforms: this.config.transforms,
397
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringUuid),
398
- jsonSchema: { ...this.config.jsonSchema, format: 'uuid' }
399
- });
400
- }
401
- /**
402
- * Create a new validator with regex pattern matching
403
- */
404
- regex(pattern, message) {
405
- return new VldString({
406
- checks: [...this.config.checks, (v) => pattern.test(v)],
407
- transforms: this.config.transforms,
408
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringRegex),
409
- jsonSchema: { ...this.config.jsonSchema, pattern: pattern.source }
410
- });
411
- }
412
- /**
413
- * Create a new validator that trims whitespace
414
- */
415
- trim() {
416
- return new VldString({
417
- checks: this.config.checks,
418
- transforms: [...this.config.transforms, (v) => v.trim()],
419
- errorMessage: this.config.errorMessage,
420
- jsonSchema: this.config.jsonSchema
421
- });
422
- }
423
- /**
424
- * Create a new validator that converts to lowercase
425
- */
426
- toLowerCase() {
427
- return new VldString({
428
- checks: this.config.checks,
429
- transforms: [...this.config.transforms, (v) => v.toLowerCase()],
430
- errorMessage: this.config.errorMessage,
431
- jsonSchema: this.config.jsonSchema
432
- });
433
- }
434
- /**
435
- * Create a new validator that converts to uppercase
436
- */
437
- toUpperCase() {
438
- return new VldString({
439
- checks: this.config.checks,
440
- transforms: [...this.config.transforms, (v) => v.toUpperCase()],
441
- errorMessage: this.config.errorMessage,
442
- jsonSchema: this.config.jsonSchema
443
- });
444
- }
445
- /**
446
- * Create a new validator that checks if string starts with a substring
447
- */
448
- startsWith(str, message) {
449
- return new VldString({
450
- checks: [...this.config.checks, (v) => v.startsWith(str)],
451
- transforms: this.config.transforms,
452
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringStartsWith(str)),
453
- jsonSchema: this.config.jsonSchema
454
- });
455
- }
456
- /**
457
- * Create a new validator that checks if string ends with a substring
458
- */
459
- endsWith(str, message) {
460
- return new VldString({
461
- checks: [...this.config.checks, (v) => v.endsWith(str)],
462
- transforms: this.config.transforms,
463
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringEndsWith(str)),
464
- jsonSchema: this.config.jsonSchema
465
- });
466
- }
467
- /**
468
- * Create a new validator that checks if string includes a substring
469
- */
470
- includes(str, message) {
471
- return new VldString({
472
- checks: [...this.config.checks, (v) => v.includes(str)],
473
- transforms: this.config.transforms,
474
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringIncludes(str)),
475
- jsonSchema: this.config.jsonSchema
476
- });
477
- }
478
- /**
479
- * Create a new validator that checks for valid IP address (v4 or v6)
480
- */
481
- ip(message) {
482
- return new VldString({
483
- checks: [...this.config.checks, (v) => {
484
- // Prevent ReDoS: Check length before regex
485
- if (v.length > 100)
486
- return false;
487
- return REGEX_PATTERNS.ipv4.test(v) || isValidIPv6(v);
488
- }],
489
- transforms: this.config.transforms,
490
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringIp),
491
- jsonSchema: { ...this.config.jsonSchema, format: 'ip' }
492
- });
493
- }
494
- /**
495
- * Create a new validator that checks for valid IPv4 address
496
- */
497
- ipv4(message) {
498
- return new VldString({
499
- checks: [...this.config.checks, (v) => REGEX_PATTERNS.ipv4.test(v)],
500
- transforms: this.config.transforms,
501
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringIpv4),
502
- jsonSchema: { ...this.config.jsonSchema, format: 'ipv4' }
503
- });
504
- }
505
- /**
506
- * Create a new validator that checks for valid IPv6 address
507
- */
508
- ipv6(message) {
509
- return new VldString({
510
- checks: [...this.config.checks, (v) => {
511
- // Use safe IPv6 validation to prevent ReDoS attacks
512
- return isValidIPv6(v);
513
- }],
514
- transforms: this.config.transforms,
515
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringIpv6),
516
- jsonSchema: { ...this.config.jsonSchema, format: 'ipv6' }
517
- });
518
- }
519
- /**
520
- * Create a new validator that ensures string is not empty
521
- */
522
- nonempty(message) {
523
- return new VldString({
524
- checks: [...this.config.checks, (v) => v.length > 0],
525
- transforms: this.config.transforms,
526
- errorMessage: validators_base.resolveErrorMessage(message, locales_runtime.getMessages().stringEmpty),
527
- jsonSchema: { ...this.config.jsonSchema, minLength: Math.max(this.config.jsonSchema?.minLength || 0, 1) }
528
- });
529
- }
530
- }
531
-
532
- exports.VldString = VldString;
533
- exports.isValidIPv6 = isValidIPv6;