@lowerdeck/validation 1.0.0

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 (250) hide show
  1. package/.turbo/turbo-build.log +11 -0
  2. package/.turbo/turbo-test.log +144 -0
  3. package/README.md +158 -0
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.ts +119 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.modern.js +2 -0
  9. package/dist/index.modern.js.map +1 -0
  10. package/dist/index.module.js +2 -0
  11. package/dist/index.module.js.map +1 -0
  12. package/dist/index.umd.js +2 -0
  13. package/dist/index.umd.js.map +1 -0
  14. package/dist/lib/introspect.d.ts +13 -0
  15. package/dist/lib/introspect.d.ts.map +1 -0
  16. package/dist/lib/result.d.ts +4 -0
  17. package/dist/lib/result.d.ts.map +1 -0
  18. package/dist/lib/result.test.d.ts +2 -0
  19. package/dist/lib/result.test.d.ts.map +1 -0
  20. package/dist/lib/types.d.ts +48 -0
  21. package/dist/lib/types.d.ts.map +1 -0
  22. package/dist/lib/validator.d.ts +3 -0
  23. package/dist/lib/validator.d.ts.map +1 -0
  24. package/dist/lib/validator.test.d.ts +2 -0
  25. package/dist/lib/validator.test.d.ts.map +1 -0
  26. package/dist/modifiers/color.d.ts +5 -0
  27. package/dist/modifiers/color.d.ts.map +1 -0
  28. package/dist/modifiers/color.test.d.ts +2 -0
  29. package/dist/modifiers/color.test.d.ts.map +1 -0
  30. package/dist/modifiers/email.d.ts +5 -0
  31. package/dist/modifiers/email.d.ts.map +1 -0
  32. package/dist/modifiers/email.test.d.ts +2 -0
  33. package/dist/modifiers/email.test.d.ts.map +1 -0
  34. package/dist/modifiers/emoji.d.ts +5 -0
  35. package/dist/modifiers/emoji.d.ts.map +1 -0
  36. package/dist/modifiers/emoji.test.d.ts +2 -0
  37. package/dist/modifiers/emoji.test.d.ts.map +1 -0
  38. package/dist/modifiers/endsWith.d.ts +5 -0
  39. package/dist/modifiers/endsWith.d.ts.map +1 -0
  40. package/dist/modifiers/endsWith.test.d.ts +2 -0
  41. package/dist/modifiers/endsWith.test.d.ts.map +1 -0
  42. package/dist/modifiers/equals.d.ts +8 -0
  43. package/dist/modifiers/equals.d.ts.map +1 -0
  44. package/dist/modifiers/equals.test.d.ts +2 -0
  45. package/dist/modifiers/equals.test.d.ts.map +1 -0
  46. package/dist/modifiers/includes.d.ts +8 -0
  47. package/dist/modifiers/includes.d.ts.map +1 -0
  48. package/dist/modifiers/includes.test.d.ts +2 -0
  49. package/dist/modifiers/includes.test.d.ts.map +1 -0
  50. package/dist/modifiers/index.d.ts +18 -0
  51. package/dist/modifiers/index.d.ts.map +1 -0
  52. package/dist/modifiers/integer.d.ts +5 -0
  53. package/dist/modifiers/integer.d.ts.map +1 -0
  54. package/dist/modifiers/integer.test.d.ts +2 -0
  55. package/dist/modifiers/integer.test.d.ts.map +1 -0
  56. package/dist/modifiers/ip.d.ts +11 -0
  57. package/dist/modifiers/ip.d.ts.map +1 -0
  58. package/dist/modifiers/ip.test.d.ts +2 -0
  59. package/dist/modifiers/ip.test.d.ts.map +1 -0
  60. package/dist/modifiers/isoDate.d.ts +11 -0
  61. package/dist/modifiers/isoDate.d.ts.map +1 -0
  62. package/dist/modifiers/isoDate.test.d.ts +2 -0
  63. package/dist/modifiers/isoDate.test.d.ts.map +1 -0
  64. package/dist/modifiers/length.d.ts +9 -0
  65. package/dist/modifiers/length.d.ts.map +1 -0
  66. package/dist/modifiers/length.test.d.ts +2 -0
  67. package/dist/modifiers/length.test.d.ts.map +1 -0
  68. package/dist/modifiers/multipleOf.d.ts +5 -0
  69. package/dist/modifiers/multipleOf.d.ts.map +1 -0
  70. package/dist/modifiers/multipleOf.test.d.ts +2 -0
  71. package/dist/modifiers/multipleOf.test.d.ts.map +1 -0
  72. package/dist/modifiers/oneOf.d.ts +5 -0
  73. package/dist/modifiers/oneOf.d.ts.map +1 -0
  74. package/dist/modifiers/oneOf.test.d.ts +2 -0
  75. package/dist/modifiers/oneOf.test.d.ts.map +1 -0
  76. package/dist/modifiers/positive.d.ts +8 -0
  77. package/dist/modifiers/positive.d.ts.map +1 -0
  78. package/dist/modifiers/positive.test.d.ts +2 -0
  79. package/dist/modifiers/positive.test.d.ts.map +1 -0
  80. package/dist/modifiers/regex.d.ts +5 -0
  81. package/dist/modifiers/regex.d.ts.map +1 -0
  82. package/dist/modifiers/regex.test.d.ts +2 -0
  83. package/dist/modifiers/regex.test.d.ts.map +1 -0
  84. package/dist/modifiers/size.d.ts +8 -0
  85. package/dist/modifiers/size.d.ts.map +1 -0
  86. package/dist/modifiers/size.test.d.ts +2 -0
  87. package/dist/modifiers/size.test.d.ts.map +1 -0
  88. package/dist/modifiers/startsWith.d.ts +5 -0
  89. package/dist/modifiers/startsWith.d.ts.map +1 -0
  90. package/dist/modifiers/startsWith.test.d.ts +2 -0
  91. package/dist/modifiers/startsWith.test.d.ts.map +1 -0
  92. package/dist/modifiers/url.d.ts +6 -0
  93. package/dist/modifiers/url.d.ts.map +1 -0
  94. package/dist/modifiers/url.test.d.ts +2 -0
  95. package/dist/modifiers/url.test.d.ts.map +1 -0
  96. package/dist/transformers/case.d.ts +4 -0
  97. package/dist/transformers/case.d.ts.map +1 -0
  98. package/dist/transformers/case.test.d.ts +2 -0
  99. package/dist/transformers/case.test.d.ts.map +1 -0
  100. package/dist/transformers/index.d.ts +3 -0
  101. package/dist/transformers/index.d.ts.map +1 -0
  102. package/dist/transformers/trim.d.ts +5 -0
  103. package/dist/transformers/trim.d.ts.map +1 -0
  104. package/dist/transformers/trim.test.d.ts +2 -0
  105. package/dist/transformers/trim.test.d.ts.map +1 -0
  106. package/dist/validators/any.d.ts +4 -0
  107. package/dist/validators/any.d.ts.map +1 -0
  108. package/dist/validators/any.test.d.ts +2 -0
  109. package/dist/validators/any.test.d.ts.map +1 -0
  110. package/dist/validators/array.d.ts +3 -0
  111. package/dist/validators/array.d.ts.map +1 -0
  112. package/dist/validators/array.test.d.ts +2 -0
  113. package/dist/validators/array.test.d.ts.map +1 -0
  114. package/dist/validators/boolean.d.ts +3 -0
  115. package/dist/validators/boolean.d.ts.map +1 -0
  116. package/dist/validators/boolean.test.d.ts +2 -0
  117. package/dist/validators/boolean.test.d.ts.map +1 -0
  118. package/dist/validators/date.d.ts +3 -0
  119. package/dist/validators/date.d.ts.map +1 -0
  120. package/dist/validators/date.test.d.ts +2 -0
  121. package/dist/validators/date.test.d.ts.map +1 -0
  122. package/dist/validators/enum.d.ts +6 -0
  123. package/dist/validators/enum.d.ts.map +1 -0
  124. package/dist/validators/enum.test.d.ts +2 -0
  125. package/dist/validators/enum.test.d.ts.map +1 -0
  126. package/dist/validators/index.d.ts +17 -0
  127. package/dist/validators/index.d.ts.map +1 -0
  128. package/dist/validators/intersection.d.ts +3 -0
  129. package/dist/validators/intersection.d.ts.map +1 -0
  130. package/dist/validators/intersection.test.d.ts +2 -0
  131. package/dist/validators/intersection.test.d.ts.map +1 -0
  132. package/dist/validators/literal.d.ts +3 -0
  133. package/dist/validators/literal.d.ts.map +1 -0
  134. package/dist/validators/literal.test.d.ts +2 -0
  135. package/dist/validators/literal.test.d.ts.map +1 -0
  136. package/dist/validators/null.d.ts +3 -0
  137. package/dist/validators/null.d.ts.map +1 -0
  138. package/dist/validators/null.test.d.ts +2 -0
  139. package/dist/validators/null.test.d.ts.map +1 -0
  140. package/dist/validators/nullable.d.ts +3 -0
  141. package/dist/validators/nullable.d.ts.map +1 -0
  142. package/dist/validators/nullable.test.d.ts +2 -0
  143. package/dist/validators/nullable.test.d.ts.map +1 -0
  144. package/dist/validators/number.d.ts +3 -0
  145. package/dist/validators/number.d.ts.map +1 -0
  146. package/dist/validators/number.test.d.ts +2 -0
  147. package/dist/validators/number.test.d.ts.map +1 -0
  148. package/dist/validators/object.d.ts +12 -0
  149. package/dist/validators/object.d.ts.map +1 -0
  150. package/dist/validators/object.test.d.ts +2 -0
  151. package/dist/validators/object.test.d.ts.map +1 -0
  152. package/dist/validators/optional.d.ts +3 -0
  153. package/dist/validators/optional.d.ts.map +1 -0
  154. package/dist/validators/optional.test.d.ts +2 -0
  155. package/dist/validators/optional.test.d.ts.map +1 -0
  156. package/dist/validators/record.d.ts +3 -0
  157. package/dist/validators/record.d.ts.map +1 -0
  158. package/dist/validators/record.test.d.ts +2 -0
  159. package/dist/validators/record.test.d.ts.map +1 -0
  160. package/dist/validators/string.d.ts +3 -0
  161. package/dist/validators/string.d.ts.map +1 -0
  162. package/dist/validators/string.test.d.ts +2 -0
  163. package/dist/validators/string.test.d.ts.map +1 -0
  164. package/dist/validators/union.d.ts +3 -0
  165. package/dist/validators/union.d.ts.map +1 -0
  166. package/dist/validators/union.test.d.ts +2 -0
  167. package/dist/validators/union.test.d.ts.map +1 -0
  168. package/dist/validators/void.d.ts +3 -0
  169. package/dist/validators/void.d.ts.map +1 -0
  170. package/package.json +31 -0
  171. package/src/index.ts +33 -0
  172. package/src/lib/introspect.ts +33 -0
  173. package/src/lib/result.test.ts +80 -0
  174. package/src/lib/result.ts +11 -0
  175. package/src/lib/types.ts +57 -0
  176. package/src/lib/validator.test.ts +82 -0
  177. package/src/lib/validator.ts +63 -0
  178. package/src/modifiers/color.test.ts +29 -0
  179. package/src/modifiers/color.ts +18 -0
  180. package/src/modifiers/email.test.ts +29 -0
  181. package/src/modifiers/email.ts +18 -0
  182. package/src/modifiers/emoji.test.ts +31 -0
  183. package/src/modifiers/emoji.ts +18 -0
  184. package/src/modifiers/endsWith.test.ts +50 -0
  185. package/src/modifiers/endsWith.ts +18 -0
  186. package/src/modifiers/equals.test.ts +70 -0
  187. package/src/modifiers/equals.ts +41 -0
  188. package/src/modifiers/includes.test.ts +64 -0
  189. package/src/modifiers/includes.ts +35 -0
  190. package/src/modifiers/index.ts +17 -0
  191. package/src/modifiers/integer.test.ts +45 -0
  192. package/src/modifiers/integer.ts +18 -0
  193. package/src/modifiers/ip.test.ts +34 -0
  194. package/src/modifiers/ip.ts +50 -0
  195. package/src/modifiers/isoDate.test.ts +83 -0
  196. package/src/modifiers/isoDate.ts +51 -0
  197. package/src/modifiers/length.test.ts +107 -0
  198. package/src/modifiers/length.ts +54 -0
  199. package/src/modifiers/multipleOf.test.ts +51 -0
  200. package/src/modifiers/multipleOf.ts +18 -0
  201. package/src/modifiers/oneOf.test.ts +27 -0
  202. package/src/modifiers/oneOf.ts +16 -0
  203. package/src/modifiers/positive.test.ts +64 -0
  204. package/src/modifiers/positive.ts +35 -0
  205. package/src/modifiers/regex.test.ts +40 -0
  206. package/src/modifiers/regex.ts +17 -0
  207. package/src/modifiers/size.test.ts +84 -0
  208. package/src/modifiers/size.ts +37 -0
  209. package/src/modifiers/startsWith.test.ts +40 -0
  210. package/src/modifiers/startsWith.ts +18 -0
  211. package/src/modifiers/url.test.ts +48 -0
  212. package/src/modifiers/url.ts +30 -0
  213. package/src/transformers/case.test.ts +36 -0
  214. package/src/transformers/case.ts +5 -0
  215. package/src/transformers/index.ts +2 -0
  216. package/src/transformers/trim.test.ts +32 -0
  217. package/src/transformers/trim.ts +7 -0
  218. package/src/validators/any.test.ts +11 -0
  219. package/src/validators/any.ts +11 -0
  220. package/src/validators/array.test.ts +46 -0
  221. package/src/validators/array.ts +43 -0
  222. package/src/validators/boolean.test.ts +39 -0
  223. package/src/validators/boolean.ts +34 -0
  224. package/src/validators/date.test.ts +39 -0
  225. package/src/validators/date.ts +26 -0
  226. package/src/validators/enum.test.ts +25 -0
  227. package/src/validators/enum.ts +56 -0
  228. package/src/validators/index.ts +16 -0
  229. package/src/validators/intersection.test.ts +35 -0
  230. package/src/validators/intersection.ts +24 -0
  231. package/src/validators/literal.test.ts +42 -0
  232. package/src/validators/literal.ts +26 -0
  233. package/src/validators/null.test.ts +39 -0
  234. package/src/validators/null.ts +18 -0
  235. package/src/validators/nullable.test.ts +34 -0
  236. package/src/validators/nullable.ts +16 -0
  237. package/src/validators/number.test.ts +39 -0
  238. package/src/validators/number.ts +23 -0
  239. package/src/validators/object.test.ts +66 -0
  240. package/src/validators/object.ts +66 -0
  241. package/src/validators/optional.test.ts +33 -0
  242. package/src/validators/optional.ts +16 -0
  243. package/src/validators/record.test.ts +56 -0
  244. package/src/validators/record.ts +56 -0
  245. package/src/validators/string.test.ts +39 -0
  246. package/src/validators/string.ts +30 -0
  247. package/src/validators/union.test.ts +73 -0
  248. package/src/validators/union.ts +38 -0
  249. package/src/validators/void.ts +6 -0
  250. package/tsconfig.json +9 -0
@@ -0,0 +1,107 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { length, maxLength, minLength } from './length';
3
+
4
+ describe('length', () => {
5
+ test('returns an empty array if the value has the expected length', () => {
6
+ let validator = length(5);
7
+ let result = validator('hello');
8
+ expect(result).toEqual([]);
9
+ });
10
+
11
+ test('returns an error object if the value does not have the expected length', () => {
12
+ let validator = length(5);
13
+ let result = validator('longer');
14
+ expect(result).toEqual([
15
+ {
16
+ code: 'invalid_length',
17
+ message: 'Invalid length, expected 5',
18
+ expected: 5,
19
+ received: 6
20
+ }
21
+ ]);
22
+ });
23
+ });
24
+
25
+ describe('minLength', () => {
26
+ test('returns an empty array if the value has the minimum length', () => {
27
+ let validator = minLength(5);
28
+ let result = validator('hello');
29
+ expect(result).toEqual([]);
30
+ });
31
+
32
+ test('returns an empty array if the value is longer than the minimum length', () => {
33
+ let validator = minLength(5);
34
+ let result = validator('world');
35
+ expect(result).toEqual([]);
36
+ });
37
+
38
+ test('returns an error object if the value is shorter than the minimum length', () => {
39
+ let validator = minLength(5);
40
+ let result = validator('hi');
41
+ expect(result).toEqual([
42
+ {
43
+ code: 'invalid_min_length',
44
+ message: 'Invalid min length, expected 5',
45
+ expected: 5,
46
+ received: 2,
47
+ min: 5
48
+ }
49
+ ]);
50
+ });
51
+
52
+ test('uses the custom error message if provided', () => {
53
+ let validator = minLength(5, { message: 'Too short!' });
54
+ let result = validator('hi');
55
+ expect(result).toEqual([
56
+ {
57
+ code: 'invalid_min_length',
58
+ message: 'Too short!',
59
+ expected: 5,
60
+ received: 2,
61
+ min: 5
62
+ }
63
+ ]);
64
+ });
65
+ });
66
+
67
+ describe('maxLength', () => {
68
+ test('returns an empty array if the value has the maximum length', () => {
69
+ let validator = maxLength(5);
70
+ let result = validator('hello');
71
+ expect(result).toEqual([]);
72
+ });
73
+
74
+ test('returns an empty array if the value is shorter than the maximum length', () => {
75
+ let validator = maxLength(5);
76
+ let result = validator('hi');
77
+ expect(result).toEqual([]);
78
+ });
79
+
80
+ test('returns an error object if the value is longer than the maximum length', () => {
81
+ let validator = maxLength(5);
82
+ let result = validator('longer');
83
+ expect(result).toEqual([
84
+ {
85
+ code: 'invalid_max_length',
86
+ message: 'Invalid max length, expected 5',
87
+ expected: 5,
88
+ received: 6,
89
+ max: 5
90
+ }
91
+ ]);
92
+ });
93
+
94
+ test('uses the custom error message if provided', () => {
95
+ let validator = maxLength(5, { message: 'Too long!' });
96
+ let result = validator('longer');
97
+ expect(result).toEqual([
98
+ {
99
+ code: 'invalid_max_length',
100
+ message: 'Too long!',
101
+ expected: 5,
102
+ received: 6,
103
+ max: 5
104
+ }
105
+ ]);
106
+ });
107
+ });
@@ -0,0 +1,54 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let length =
4
+ (length: number): ValidationModifier<string> =>
5
+ value => {
6
+ if (value.length !== length) {
7
+ return [
8
+ {
9
+ code: 'invalid_length',
10
+ message: `Invalid length, expected ${length}`,
11
+ expected: length,
12
+ received: value.length
13
+ }
14
+ ];
15
+ }
16
+
17
+ return [];
18
+ };
19
+
20
+ export let minLength =
21
+ (length: number, opts?: { message?: string }): ValidationModifier<string | any[]> =>
22
+ value => {
23
+ if (value.length < length) {
24
+ return [
25
+ {
26
+ code: 'invalid_min_length',
27
+ message: opts?.message ?? `Invalid min length, expected ${length}`,
28
+ expected: length,
29
+ received: value.length,
30
+ min: length
31
+ }
32
+ ];
33
+ }
34
+
35
+ return [];
36
+ };
37
+
38
+ export let maxLength =
39
+ (length: number, opts?: { message?: string }): ValidationModifier<string | any[]> =>
40
+ value => {
41
+ if (value.length > length) {
42
+ return [
43
+ {
44
+ code: 'invalid_max_length',
45
+ message: opts?.message ?? `Invalid max length, expected ${length}`,
46
+ expected: length,
47
+ received: value.length,
48
+ max: length
49
+ }
50
+ ];
51
+ }
52
+
53
+ return [];
54
+ };
@@ -0,0 +1,51 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { multipleOf } from './multipleOf';
3
+
4
+ describe('multipleOf', () => {
5
+ test('should return an empty array if the value is a multiple of the given number', () => {
6
+ const modifier = multipleOf(3);
7
+ expect(modifier(9)).toEqual([]);
8
+ expect(modifier(12)).toEqual([]);
9
+ expect(modifier(0)).toEqual([]);
10
+ });
11
+
12
+ test('should return an error object if the value is not a multiple of the given number', () => {
13
+ const modifier = multipleOf(5);
14
+ expect(modifier(7)).toEqual([
15
+ {
16
+ code: 'invalid_multiple_of',
17
+ message: 'Invalid multiple of 5, expected 7',
18
+ received: 7,
19
+ multipleOf: 5
20
+ }
21
+ ]);
22
+ expect(modifier(11)).toEqual([
23
+ {
24
+ code: 'invalid_multiple_of',
25
+ message: 'Invalid multiple of 5, expected 11',
26
+ received: 11,
27
+ multipleOf: 5
28
+ }
29
+ ]);
30
+ });
31
+
32
+ test('should allow custom error message', () => {
33
+ const modifier = multipleOf(2, { message: 'Value must be an even number' });
34
+ expect(modifier(3)).toEqual([
35
+ {
36
+ code: 'invalid_multiple_of',
37
+ message: 'Value must be an even number',
38
+ received: 3,
39
+ multipleOf: 2
40
+ }
41
+ ]);
42
+ expect(modifier(5)).toEqual([
43
+ {
44
+ code: 'invalid_multiple_of',
45
+ message: 'Value must be an even number',
46
+ received: 5,
47
+ multipleOf: 2
48
+ }
49
+ ]);
50
+ });
51
+ });
@@ -0,0 +1,18 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let multipleOf =
4
+ (multi: number, opts?: { message?: string }): ValidationModifier<number> =>
5
+ value => {
6
+ if (value % multi !== 0) {
7
+ return [
8
+ {
9
+ code: 'invalid_multiple_of',
10
+ message: opts?.message ?? `Invalid multiple of ${multi}, expected ${value}`,
11
+ received: value,
12
+ multipleOf: multi
13
+ }
14
+ ];
15
+ }
16
+
17
+ return [];
18
+ };
@@ -0,0 +1,27 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { oneOf } from './oneOf';
3
+
4
+ describe('oneOf', () => {
5
+ test('should return an empty array if the value is one of the allowed values', () => {
6
+ let allowed = ['apple', 'banana', 'orange'];
7
+ let modifier = oneOf(allowed);
8
+ let value = 'banana';
9
+ let result = modifier(value);
10
+ expect(result).toEqual([]);
11
+ });
12
+
13
+ test('should return an error object if the value is not one of the allowed values', () => {
14
+ let allowed = ['apple', 'banana', 'orange'];
15
+ let modifier = oneOf(allowed);
16
+ let value = 'grape';
17
+ let result = modifier(value);
18
+ expect(result).toEqual([
19
+ {
20
+ code: 'invalid_value',
21
+ message: 'Value must be one of: apple, banana, orange'
22
+ }
23
+ ]);
24
+ });
25
+
26
+ // Add more test cases if needed
27
+ });
@@ -0,0 +1,16 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let oneOf =
4
+ (allowed: string[], opts?: { message?: string }): ValidationModifier<string> =>
5
+ value => {
6
+ if (!allowed.includes(value)) {
7
+ return [
8
+ {
9
+ code: 'invalid_value',
10
+ message: opts?.message ?? `Value must be one of: ${allowed.join(', ')}`
11
+ }
12
+ ];
13
+ }
14
+
15
+ return [];
16
+ };
@@ -0,0 +1,64 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { negative, positive } from './positive';
3
+
4
+ describe('positive', () => {
5
+ test('should return an empty array for positive numbers', () => {
6
+ let result = positive()(1);
7
+ expect(result).toEqual([]);
8
+ });
9
+
10
+ test('should return an error object for non-positive numbers', () => {
11
+ let result = positive()(-1);
12
+ expect(result).toEqual([
13
+ {
14
+ code: 'invalid_positive',
15
+ message: 'Invalid positive, expected -1',
16
+ received: -1,
17
+ positive: true
18
+ }
19
+ ]);
20
+ });
21
+
22
+ test('should use the custom error message if provided', () => {
23
+ let result = positive({ message: 'Value must be positive' })(-1);
24
+ expect(result).toEqual([
25
+ {
26
+ code: 'invalid_positive',
27
+ message: 'Value must be positive',
28
+ received: -1,
29
+ positive: true
30
+ }
31
+ ]);
32
+ });
33
+ });
34
+
35
+ describe('negative', () => {
36
+ test('should return an empty array for negative numbers', () => {
37
+ let result = negative()(-1);
38
+ expect(result).toEqual([]);
39
+ });
40
+
41
+ test('should return an error object for non-negative numbers', () => {
42
+ let result = negative()(1);
43
+ expect(result).toEqual([
44
+ {
45
+ code: 'invalid_negative',
46
+ message: 'Invalid negative, expected 1',
47
+ received: 1,
48
+ negative: true
49
+ }
50
+ ]);
51
+ });
52
+
53
+ test('should use the custom error message if provided', () => {
54
+ let result = negative({ message: 'Value must be negative' })(1);
55
+ expect(result).toEqual([
56
+ {
57
+ code: 'invalid_negative',
58
+ message: 'Value must be negative',
59
+ received: 1,
60
+ negative: true
61
+ }
62
+ ]);
63
+ });
64
+ });
@@ -0,0 +1,35 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let positive =
4
+ (opts?: { message?: string }): ValidationModifier<number> =>
5
+ value => {
6
+ if (value <= 0) {
7
+ return [
8
+ {
9
+ code: 'invalid_positive',
10
+ message: opts?.message ?? `Invalid positive, expected ${value}`,
11
+ received: value,
12
+ positive: true
13
+ }
14
+ ];
15
+ }
16
+
17
+ return [];
18
+ };
19
+
20
+ export let negative =
21
+ (opts?: { message?: string }): ValidationModifier<number> =>
22
+ value => {
23
+ if (value >= 0) {
24
+ return [
25
+ {
26
+ code: 'invalid_negative',
27
+ message: opts?.message ?? `Invalid negative, expected ${value}`,
28
+ received: value,
29
+ negative: true
30
+ }
31
+ ];
32
+ }
33
+
34
+ return [];
35
+ };
@@ -0,0 +1,40 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { regex } from './regex';
3
+
4
+ describe('regex', () => {
5
+ test('returns an empty array if the value matches the pattern', () => {
6
+ let pattern = /^[a-z]+$/;
7
+ let validate = regex(pattern);
8
+ let result = validate('hello');
9
+
10
+ expect(result).toEqual([]);
11
+ });
12
+
13
+ test('returns an error object if the value does not match the pattern', () => {
14
+ let pattern = /^[a-z]+$/;
15
+ let validate = regex(pattern);
16
+ let result = validate('123');
17
+
18
+ expect(result).toEqual([
19
+ {
20
+ code: 'invalid_regex',
21
+ message: 'Invalid regex, expected /^[a-z]+$/',
22
+ received: '123'
23
+ }
24
+ ]);
25
+ });
26
+
27
+ test('uses the custom error message if provided', () => {
28
+ let pattern = /^[a-z]+$/;
29
+ let validate = regex(pattern, { message: 'Must be all lowercase letters' });
30
+ let result = validate('123');
31
+
32
+ expect(result).toEqual([
33
+ {
34
+ code: 'invalid_regex',
35
+ message: 'Must be all lowercase letters',
36
+ received: '123'
37
+ }
38
+ ]);
39
+ });
40
+ });
@@ -0,0 +1,17 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let regex =
4
+ (pattern: RegExp, opts?: { message?: string }): ValidationModifier<string> =>
5
+ value => {
6
+ if (!pattern.test(value)) {
7
+ return [
8
+ {
9
+ code: 'invalid_regex',
10
+ message: opts?.message ?? `Invalid regex, expected ${pattern}`,
11
+ received: value
12
+ }
13
+ ];
14
+ }
15
+
16
+ return [];
17
+ };
@@ -0,0 +1,84 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { maxValue, minValue } from './size';
3
+
4
+ describe('minValue', () => {
5
+ test('returns an empty array if the value is greater than or equal to the minimum', () => {
6
+ let min = 5;
7
+ let validate = minValue(min);
8
+
9
+ expect(validate(5)).toEqual([]);
10
+ expect(validate(10)).toEqual([]);
11
+ });
12
+
13
+ test('returns an array with an error object if the value is less than the minimum', () => {
14
+ let min = 5;
15
+ let validate = minValue(min);
16
+
17
+ expect(validate(4)).toEqual([
18
+ {
19
+ code: 'invalid_min',
20
+ message: `Invalid min, expected ${min}`,
21
+ expected: min,
22
+ received: 4,
23
+ min
24
+ }
25
+ ]);
26
+ });
27
+
28
+ test('uses the custom error message if provided', () => {
29
+ let min = 5;
30
+ let message = 'Value must be at least 5';
31
+ let validate = minValue(min, { message });
32
+
33
+ expect(validate(4)).toEqual([
34
+ {
35
+ code: 'invalid_min',
36
+ message,
37
+ expected: min,
38
+ received: 4,
39
+ min
40
+ }
41
+ ]);
42
+ });
43
+ });
44
+
45
+ describe('maxValue', () => {
46
+ test('returns an empty array if the value is less than or equal to the maximum', () => {
47
+ let max = 10;
48
+ let validate = maxValue(max);
49
+
50
+ expect(validate(10)).toEqual([]);
51
+ expect(validate(5)).toEqual([]);
52
+ });
53
+
54
+ test('returns an array with an error object if the value is greater than the maximum', () => {
55
+ let max = 10;
56
+ let validate = maxValue(max);
57
+
58
+ expect(validate(11)).toEqual([
59
+ {
60
+ code: 'invalid_max',
61
+ message: `Invalid max, expected ${max}`,
62
+ expected: max,
63
+ received: 11,
64
+ max
65
+ }
66
+ ]);
67
+ });
68
+
69
+ test('uses the custom error message if provided', () => {
70
+ let max = 10;
71
+ let message = 'Value must be at most 10';
72
+ let validate = maxValue(max, { message });
73
+
74
+ expect(validate(11)).toEqual([
75
+ {
76
+ code: 'invalid_max',
77
+ message,
78
+ expected: max,
79
+ received: 11,
80
+ max
81
+ }
82
+ ]);
83
+ });
84
+ });
@@ -0,0 +1,37 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let minValue =
4
+ (min: number, opts?: { message?: string }): ValidationModifier<number> =>
5
+ value => {
6
+ if (value < min) {
7
+ return [
8
+ {
9
+ code: 'invalid_min',
10
+ message: opts?.message ?? `Invalid min, expected ${min}`,
11
+ expected: min,
12
+ received: value,
13
+ min
14
+ }
15
+ ];
16
+ }
17
+
18
+ return [];
19
+ };
20
+
21
+ export let maxValue =
22
+ (max: number, opts?: { message?: string }): ValidationModifier<number> =>
23
+ value => {
24
+ if (value > max) {
25
+ return [
26
+ {
27
+ code: 'invalid_max',
28
+ message: opts?.message ?? `Invalid max, expected ${max}`,
29
+ expected: max,
30
+ received: value,
31
+ max
32
+ }
33
+ ];
34
+ }
35
+
36
+ return [];
37
+ };
@@ -0,0 +1,40 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { startsWith } from './startsWith';
3
+
4
+ describe('startsWith', () => {
5
+ test('returns an empty array if the value starts with the prefix', () => {
6
+ let prefix = 'hello';
7
+ let value = 'hello world';
8
+ let result = startsWith(prefix)(value);
9
+ expect(result).toEqual([]);
10
+ });
11
+
12
+ test('returns an error object if the value does not start with the prefix', () => {
13
+ let prefix = 'hello';
14
+ let value = 'world';
15
+ let result = startsWith(prefix)(value);
16
+ expect(result).toEqual([
17
+ {
18
+ code: 'invalid_prefix',
19
+ message: `Invalid prefix, expected ${prefix}`,
20
+ expected: prefix,
21
+ received: value
22
+ }
23
+ ]);
24
+ });
25
+
26
+ test('returns a custom error message if provided', () => {
27
+ let prefix = 'hello';
28
+ let value = 'world';
29
+ let message = 'Value must start with hello';
30
+ let result = startsWith(prefix, { message })(value);
31
+ expect(result).toEqual([
32
+ {
33
+ code: 'invalid_prefix',
34
+ message,
35
+ expected: prefix,
36
+ received: value
37
+ }
38
+ ]);
39
+ });
40
+ });
@@ -0,0 +1,18 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let startsWith =
4
+ (prefix: string, opts?: { message?: string }): ValidationModifier<string> =>
5
+ value => {
6
+ if (!value.startsWith(prefix)) {
7
+ return [
8
+ {
9
+ code: 'invalid_prefix',
10
+ message: opts?.message ?? `Invalid prefix, expected ${prefix}`,
11
+ expected: prefix,
12
+ received: value
13
+ }
14
+ ];
15
+ }
16
+
17
+ return [];
18
+ };
@@ -0,0 +1,48 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { url } from './url';
3
+
4
+ describe('url', () => {
5
+ test('should return an empty array for a valid URL', () => {
6
+ let result = url()('https://example.com');
7
+ expect(result).toEqual([]);
8
+ });
9
+
10
+ test('should return an error for an invalid URL', () => {
11
+ let result = url()('not a url');
12
+ expect(result).toEqual([
13
+ {
14
+ code: 'invalid_url',
15
+ message: 'Invalid URL',
16
+ received: 'not a url'
17
+ }
18
+ ]);
19
+ });
20
+
21
+ test('should return an error for a URL with an invalid hostname', () => {
22
+ let result = url({ hostnames: ['example.com'] })('https://google.com');
23
+ expect(result).toEqual([
24
+ {
25
+ code: 'invalid_hostname',
26
+ message: 'Invalid hostname',
27
+ expected: ['example.com'],
28
+ received: 'google.com'
29
+ }
30
+ ]);
31
+ });
32
+
33
+ test('should return an empty array for a URL with a valid hostname', () => {
34
+ let result = url({ hostnames: ['example.com'] })('https://example.com');
35
+ expect(result).toEqual([]);
36
+ });
37
+
38
+ test('should use the provided error message', () => {
39
+ let result = url({ message: 'Custom error message' })('not a url');
40
+ expect(result).toEqual([
41
+ {
42
+ code: 'invalid_url',
43
+ message: 'Custom error message',
44
+ received: 'not a url'
45
+ }
46
+ ]);
47
+ });
48
+ });
@@ -0,0 +1,30 @@
1
+ import { ValidationModifier } from '../lib/types';
2
+
3
+ export let url =
4
+ (opts?: { message?: string; hostnames?: string[] }): ValidationModifier<string> =>
5
+ value => {
6
+ try {
7
+ let url = new URL(value);
8
+
9
+ if (opts?.hostnames && !opts.hostnames.includes(url.hostname)) {
10
+ return [
11
+ {
12
+ code: 'invalid_hostname',
13
+ message: opts?.message ?? `Invalid hostname`,
14
+ expected: opts?.hostnames,
15
+ received: url.hostname
16
+ }
17
+ ];
18
+ }
19
+
20
+ return [];
21
+ } catch (err) {
22
+ return [
23
+ {
24
+ code: 'invalid_url',
25
+ message: opts?.message ?? `Invalid URL`,
26
+ received: value
27
+ }
28
+ ];
29
+ }
30
+ };