@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.
- package/.turbo/turbo-build.log +11 -0
- package/.turbo/turbo-test.log +144 -0
- package/README.md +158 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.modern.js +2 -0
- package/dist/index.modern.js.map +1 -0
- package/dist/index.module.js +2 -0
- package/dist/index.module.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/lib/introspect.d.ts +13 -0
- package/dist/lib/introspect.d.ts.map +1 -0
- package/dist/lib/result.d.ts +4 -0
- package/dist/lib/result.d.ts.map +1 -0
- package/dist/lib/result.test.d.ts +2 -0
- package/dist/lib/result.test.d.ts.map +1 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/validator.d.ts +3 -0
- package/dist/lib/validator.d.ts.map +1 -0
- package/dist/lib/validator.test.d.ts +2 -0
- package/dist/lib/validator.test.d.ts.map +1 -0
- package/dist/modifiers/color.d.ts +5 -0
- package/dist/modifiers/color.d.ts.map +1 -0
- package/dist/modifiers/color.test.d.ts +2 -0
- package/dist/modifiers/color.test.d.ts.map +1 -0
- package/dist/modifiers/email.d.ts +5 -0
- package/dist/modifiers/email.d.ts.map +1 -0
- package/dist/modifiers/email.test.d.ts +2 -0
- package/dist/modifiers/email.test.d.ts.map +1 -0
- package/dist/modifiers/emoji.d.ts +5 -0
- package/dist/modifiers/emoji.d.ts.map +1 -0
- package/dist/modifiers/emoji.test.d.ts +2 -0
- package/dist/modifiers/emoji.test.d.ts.map +1 -0
- package/dist/modifiers/endsWith.d.ts +5 -0
- package/dist/modifiers/endsWith.d.ts.map +1 -0
- package/dist/modifiers/endsWith.test.d.ts +2 -0
- package/dist/modifiers/endsWith.test.d.ts.map +1 -0
- package/dist/modifiers/equals.d.ts +8 -0
- package/dist/modifiers/equals.d.ts.map +1 -0
- package/dist/modifiers/equals.test.d.ts +2 -0
- package/dist/modifiers/equals.test.d.ts.map +1 -0
- package/dist/modifiers/includes.d.ts +8 -0
- package/dist/modifiers/includes.d.ts.map +1 -0
- package/dist/modifiers/includes.test.d.ts +2 -0
- package/dist/modifiers/includes.test.d.ts.map +1 -0
- package/dist/modifiers/index.d.ts +18 -0
- package/dist/modifiers/index.d.ts.map +1 -0
- package/dist/modifiers/integer.d.ts +5 -0
- package/dist/modifiers/integer.d.ts.map +1 -0
- package/dist/modifiers/integer.test.d.ts +2 -0
- package/dist/modifiers/integer.test.d.ts.map +1 -0
- package/dist/modifiers/ip.d.ts +11 -0
- package/dist/modifiers/ip.d.ts.map +1 -0
- package/dist/modifiers/ip.test.d.ts +2 -0
- package/dist/modifiers/ip.test.d.ts.map +1 -0
- package/dist/modifiers/isoDate.d.ts +11 -0
- package/dist/modifiers/isoDate.d.ts.map +1 -0
- package/dist/modifiers/isoDate.test.d.ts +2 -0
- package/dist/modifiers/isoDate.test.d.ts.map +1 -0
- package/dist/modifiers/length.d.ts +9 -0
- package/dist/modifiers/length.d.ts.map +1 -0
- package/dist/modifiers/length.test.d.ts +2 -0
- package/dist/modifiers/length.test.d.ts.map +1 -0
- package/dist/modifiers/multipleOf.d.ts +5 -0
- package/dist/modifiers/multipleOf.d.ts.map +1 -0
- package/dist/modifiers/multipleOf.test.d.ts +2 -0
- package/dist/modifiers/multipleOf.test.d.ts.map +1 -0
- package/dist/modifiers/oneOf.d.ts +5 -0
- package/dist/modifiers/oneOf.d.ts.map +1 -0
- package/dist/modifiers/oneOf.test.d.ts +2 -0
- package/dist/modifiers/oneOf.test.d.ts.map +1 -0
- package/dist/modifiers/positive.d.ts +8 -0
- package/dist/modifiers/positive.d.ts.map +1 -0
- package/dist/modifiers/positive.test.d.ts +2 -0
- package/dist/modifiers/positive.test.d.ts.map +1 -0
- package/dist/modifiers/regex.d.ts +5 -0
- package/dist/modifiers/regex.d.ts.map +1 -0
- package/dist/modifiers/regex.test.d.ts +2 -0
- package/dist/modifiers/regex.test.d.ts.map +1 -0
- package/dist/modifiers/size.d.ts +8 -0
- package/dist/modifiers/size.d.ts.map +1 -0
- package/dist/modifiers/size.test.d.ts +2 -0
- package/dist/modifiers/size.test.d.ts.map +1 -0
- package/dist/modifiers/startsWith.d.ts +5 -0
- package/dist/modifiers/startsWith.d.ts.map +1 -0
- package/dist/modifiers/startsWith.test.d.ts +2 -0
- package/dist/modifiers/startsWith.test.d.ts.map +1 -0
- package/dist/modifiers/url.d.ts +6 -0
- package/dist/modifiers/url.d.ts.map +1 -0
- package/dist/modifiers/url.test.d.ts +2 -0
- package/dist/modifiers/url.test.d.ts.map +1 -0
- package/dist/transformers/case.d.ts +4 -0
- package/dist/transformers/case.d.ts.map +1 -0
- package/dist/transformers/case.test.d.ts +2 -0
- package/dist/transformers/case.test.d.ts.map +1 -0
- package/dist/transformers/index.d.ts +3 -0
- package/dist/transformers/index.d.ts.map +1 -0
- package/dist/transformers/trim.d.ts +5 -0
- package/dist/transformers/trim.d.ts.map +1 -0
- package/dist/transformers/trim.test.d.ts +2 -0
- package/dist/transformers/trim.test.d.ts.map +1 -0
- package/dist/validators/any.d.ts +4 -0
- package/dist/validators/any.d.ts.map +1 -0
- package/dist/validators/any.test.d.ts +2 -0
- package/dist/validators/any.test.d.ts.map +1 -0
- package/dist/validators/array.d.ts +3 -0
- package/dist/validators/array.d.ts.map +1 -0
- package/dist/validators/array.test.d.ts +2 -0
- package/dist/validators/array.test.d.ts.map +1 -0
- package/dist/validators/boolean.d.ts +3 -0
- package/dist/validators/boolean.d.ts.map +1 -0
- package/dist/validators/boolean.test.d.ts +2 -0
- package/dist/validators/boolean.test.d.ts.map +1 -0
- package/dist/validators/date.d.ts +3 -0
- package/dist/validators/date.d.ts.map +1 -0
- package/dist/validators/date.test.d.ts +2 -0
- package/dist/validators/date.test.d.ts.map +1 -0
- package/dist/validators/enum.d.ts +6 -0
- package/dist/validators/enum.d.ts.map +1 -0
- package/dist/validators/enum.test.d.ts +2 -0
- package/dist/validators/enum.test.d.ts.map +1 -0
- package/dist/validators/index.d.ts +17 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/intersection.d.ts +3 -0
- package/dist/validators/intersection.d.ts.map +1 -0
- package/dist/validators/intersection.test.d.ts +2 -0
- package/dist/validators/intersection.test.d.ts.map +1 -0
- package/dist/validators/literal.d.ts +3 -0
- package/dist/validators/literal.d.ts.map +1 -0
- package/dist/validators/literal.test.d.ts +2 -0
- package/dist/validators/literal.test.d.ts.map +1 -0
- package/dist/validators/null.d.ts +3 -0
- package/dist/validators/null.d.ts.map +1 -0
- package/dist/validators/null.test.d.ts +2 -0
- package/dist/validators/null.test.d.ts.map +1 -0
- package/dist/validators/nullable.d.ts +3 -0
- package/dist/validators/nullable.d.ts.map +1 -0
- package/dist/validators/nullable.test.d.ts +2 -0
- package/dist/validators/nullable.test.d.ts.map +1 -0
- package/dist/validators/number.d.ts +3 -0
- package/dist/validators/number.d.ts.map +1 -0
- package/dist/validators/number.test.d.ts +2 -0
- package/dist/validators/number.test.d.ts.map +1 -0
- package/dist/validators/object.d.ts +12 -0
- package/dist/validators/object.d.ts.map +1 -0
- package/dist/validators/object.test.d.ts +2 -0
- package/dist/validators/object.test.d.ts.map +1 -0
- package/dist/validators/optional.d.ts +3 -0
- package/dist/validators/optional.d.ts.map +1 -0
- package/dist/validators/optional.test.d.ts +2 -0
- package/dist/validators/optional.test.d.ts.map +1 -0
- package/dist/validators/record.d.ts +3 -0
- package/dist/validators/record.d.ts.map +1 -0
- package/dist/validators/record.test.d.ts +2 -0
- package/dist/validators/record.test.d.ts.map +1 -0
- package/dist/validators/string.d.ts +3 -0
- package/dist/validators/string.d.ts.map +1 -0
- package/dist/validators/string.test.d.ts +2 -0
- package/dist/validators/string.test.d.ts.map +1 -0
- package/dist/validators/union.d.ts +3 -0
- package/dist/validators/union.d.ts.map +1 -0
- package/dist/validators/union.test.d.ts +2 -0
- package/dist/validators/union.test.d.ts.map +1 -0
- package/dist/validators/void.d.ts +3 -0
- package/dist/validators/void.d.ts.map +1 -0
- package/package.json +31 -0
- package/src/index.ts +33 -0
- package/src/lib/introspect.ts +33 -0
- package/src/lib/result.test.ts +80 -0
- package/src/lib/result.ts +11 -0
- package/src/lib/types.ts +57 -0
- package/src/lib/validator.test.ts +82 -0
- package/src/lib/validator.ts +63 -0
- package/src/modifiers/color.test.ts +29 -0
- package/src/modifiers/color.ts +18 -0
- package/src/modifiers/email.test.ts +29 -0
- package/src/modifiers/email.ts +18 -0
- package/src/modifiers/emoji.test.ts +31 -0
- package/src/modifiers/emoji.ts +18 -0
- package/src/modifiers/endsWith.test.ts +50 -0
- package/src/modifiers/endsWith.ts +18 -0
- package/src/modifiers/equals.test.ts +70 -0
- package/src/modifiers/equals.ts +41 -0
- package/src/modifiers/includes.test.ts +64 -0
- package/src/modifiers/includes.ts +35 -0
- package/src/modifiers/index.ts +17 -0
- package/src/modifiers/integer.test.ts +45 -0
- package/src/modifiers/integer.ts +18 -0
- package/src/modifiers/ip.test.ts +34 -0
- package/src/modifiers/ip.ts +50 -0
- package/src/modifiers/isoDate.test.ts +83 -0
- package/src/modifiers/isoDate.ts +51 -0
- package/src/modifiers/length.test.ts +107 -0
- package/src/modifiers/length.ts +54 -0
- package/src/modifiers/multipleOf.test.ts +51 -0
- package/src/modifiers/multipleOf.ts +18 -0
- package/src/modifiers/oneOf.test.ts +27 -0
- package/src/modifiers/oneOf.ts +16 -0
- package/src/modifiers/positive.test.ts +64 -0
- package/src/modifiers/positive.ts +35 -0
- package/src/modifiers/regex.test.ts +40 -0
- package/src/modifiers/regex.ts +17 -0
- package/src/modifiers/size.test.ts +84 -0
- package/src/modifiers/size.ts +37 -0
- package/src/modifiers/startsWith.test.ts +40 -0
- package/src/modifiers/startsWith.ts +18 -0
- package/src/modifiers/url.test.ts +48 -0
- package/src/modifiers/url.ts +30 -0
- package/src/transformers/case.test.ts +36 -0
- package/src/transformers/case.ts +5 -0
- package/src/transformers/index.ts +2 -0
- package/src/transformers/trim.test.ts +32 -0
- package/src/transformers/trim.ts +7 -0
- package/src/validators/any.test.ts +11 -0
- package/src/validators/any.ts +11 -0
- package/src/validators/array.test.ts +46 -0
- package/src/validators/array.ts +43 -0
- package/src/validators/boolean.test.ts +39 -0
- package/src/validators/boolean.ts +34 -0
- package/src/validators/date.test.ts +39 -0
- package/src/validators/date.ts +26 -0
- package/src/validators/enum.test.ts +25 -0
- package/src/validators/enum.ts +56 -0
- package/src/validators/index.ts +16 -0
- package/src/validators/intersection.test.ts +35 -0
- package/src/validators/intersection.ts +24 -0
- package/src/validators/literal.test.ts +42 -0
- package/src/validators/literal.ts +26 -0
- package/src/validators/null.test.ts +39 -0
- package/src/validators/null.ts +18 -0
- package/src/validators/nullable.test.ts +34 -0
- package/src/validators/nullable.ts +16 -0
- package/src/validators/number.test.ts +39 -0
- package/src/validators/number.ts +23 -0
- package/src/validators/object.test.ts +66 -0
- package/src/validators/object.ts +66 -0
- package/src/validators/optional.test.ts +33 -0
- package/src/validators/optional.ts +16 -0
- package/src/validators/record.test.ts +56 -0
- package/src/validators/record.ts +56 -0
- package/src/validators/string.test.ts +39 -0
- package/src/validators/string.ts +30 -0
- package/src/validators/union.test.ts +73 -0
- package/src/validators/union.ts +38 -0
- package/src/validators/void.ts +6 -0
- 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
|
+
};
|