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