@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,31 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { emoji } from './emoji';
|
|
3
|
+
|
|
4
|
+
describe('emoji', () => {
|
|
5
|
+
let validate = emoji();
|
|
6
|
+
|
|
7
|
+
test('should return no errors for valid emoji', () => {
|
|
8
|
+
let result = validate('😀');
|
|
9
|
+
expect(result).toEqual([]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('should return an error for invalid emoji', () => {
|
|
13
|
+
let result = validate('not an emoji');
|
|
14
|
+
expect(result).toEqual([
|
|
15
|
+
{
|
|
16
|
+
code: 'invalid_emoji',
|
|
17
|
+
message: 'Invalid emoji'
|
|
18
|
+
}
|
|
19
|
+
]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('should allow custom error messages', () => {
|
|
23
|
+
let result = emoji({ message: 'Custom error message' })('not an emoji');
|
|
24
|
+
expect(result).toEqual([
|
|
25
|
+
{
|
|
26
|
+
code: 'invalid_emoji',
|
|
27
|
+
message: 'Custom error message'
|
|
28
|
+
}
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
let emojiRegex = /^(\p{Extended_Pictographic}|\p{Emoji_Component})+$/u;
|
|
4
|
+
|
|
5
|
+
export let emoji =
|
|
6
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
7
|
+
value => {
|
|
8
|
+
if (!emojiRegex.test(value)) {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
code: 'invalid_emoji',
|
|
12
|
+
message: opts?.message ?? 'Invalid emoji'
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [];
|
|
18
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { endsWith } from './endsWith';
|
|
3
|
+
|
|
4
|
+
describe('endsWith', () => {
|
|
5
|
+
test('returns an empty array if the value ends with the suffix', () => {
|
|
6
|
+
let suffix = 'world';
|
|
7
|
+
let validate = endsWith(suffix);
|
|
8
|
+
|
|
9
|
+
expect(validate('hello world')).toEqual([]);
|
|
10
|
+
expect(validate('goodbye world')).toEqual([]);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('returns an error object if the value does not end with the suffix', () => {
|
|
14
|
+
let suffix = 'world';
|
|
15
|
+
let validate = endsWith(suffix);
|
|
16
|
+
|
|
17
|
+
expect(validate('hello')).toEqual([
|
|
18
|
+
{
|
|
19
|
+
code: 'invalid_suffix',
|
|
20
|
+
message: `Invalid suffix, expected ${suffix}`,
|
|
21
|
+
expected: suffix,
|
|
22
|
+
received: 'hello'
|
|
23
|
+
}
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
expect(validate('goodbye')).toEqual([
|
|
27
|
+
{
|
|
28
|
+
code: 'invalid_suffix',
|
|
29
|
+
message: `Invalid suffix, expected ${suffix}`,
|
|
30
|
+
expected: suffix,
|
|
31
|
+
received: 'goodbye'
|
|
32
|
+
}
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('uses the provided error message if one is given', () => {
|
|
37
|
+
let suffix = 'world';
|
|
38
|
+
let message = 'This value must end with "world"';
|
|
39
|
+
let validate = endsWith(suffix, { message });
|
|
40
|
+
|
|
41
|
+
expect(validate('hello')).toEqual([
|
|
42
|
+
{
|
|
43
|
+
code: 'invalid_suffix',
|
|
44
|
+
message,
|
|
45
|
+
expected: suffix,
|
|
46
|
+
received: 'hello'
|
|
47
|
+
}
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
export let endsWith =
|
|
4
|
+
(suffix: string, opts?: { message?: string }): ValidationModifier<string> =>
|
|
5
|
+
value => {
|
|
6
|
+
if (!value.endsWith(suffix)) {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
code: 'invalid_suffix',
|
|
10
|
+
message: opts?.message ?? `Invalid suffix, expected ${suffix}`,
|
|
11
|
+
expected: suffix,
|
|
12
|
+
received: value
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [];
|
|
18
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { equals, notEquals } from './equals';
|
|
3
|
+
|
|
4
|
+
describe('equals', () => {
|
|
5
|
+
test('returns an empty array if the value equals the expected value', () => {
|
|
6
|
+
let validator = equals('hello');
|
|
7
|
+
let result = validator('hello');
|
|
8
|
+
expect(result).toEqual([]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('returns an error object if the value does not equal the expected value', () => {
|
|
12
|
+
let validator = equals('hello');
|
|
13
|
+
let result = validator('world');
|
|
14
|
+
expect(result).toEqual([
|
|
15
|
+
{
|
|
16
|
+
code: 'invalid_equals',
|
|
17
|
+
message: 'Invalid value, expected hello',
|
|
18
|
+
expected: 'hello',
|
|
19
|
+
received: 'world'
|
|
20
|
+
}
|
|
21
|
+
]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('uses the custom error message if provided', () => {
|
|
25
|
+
let validator = equals('hello', { message: 'This is a custom error message' });
|
|
26
|
+
let result = validator('world');
|
|
27
|
+
expect(result).toEqual([
|
|
28
|
+
{
|
|
29
|
+
code: 'invalid_equals',
|
|
30
|
+
message: 'This is a custom error message',
|
|
31
|
+
expected: 'hello',
|
|
32
|
+
received: 'world'
|
|
33
|
+
}
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('notEquals', () => {
|
|
39
|
+
test('returns an empty array if the value does not equal the expected value', () => {
|
|
40
|
+
let validator = notEquals('hello');
|
|
41
|
+
let result = validator('world');
|
|
42
|
+
expect(result).toEqual([]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('returns an error object if the value equals the expected value', () => {
|
|
46
|
+
let validator = notEquals('hello');
|
|
47
|
+
let result = validator('hello');
|
|
48
|
+
expect(result).toEqual([
|
|
49
|
+
{
|
|
50
|
+
code: 'invalid_not_equals',
|
|
51
|
+
message: 'Invalid value, expected not hello',
|
|
52
|
+
expected: 'hello',
|
|
53
|
+
received: 'hello'
|
|
54
|
+
}
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('uses the custom error message if provided', () => {
|
|
59
|
+
let validator = notEquals('hello', { message: 'This is a custom error message' });
|
|
60
|
+
let result = validator('hello');
|
|
61
|
+
expect(result).toEqual([
|
|
62
|
+
{
|
|
63
|
+
code: 'invalid_not_equals',
|
|
64
|
+
message: 'This is a custom error message',
|
|
65
|
+
expected: 'hello',
|
|
66
|
+
received: 'hello'
|
|
67
|
+
}
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
export let equals =
|
|
4
|
+
(
|
|
5
|
+
expected: string | number | boolean,
|
|
6
|
+
opts?: { message?: string }
|
|
7
|
+
): ValidationModifier<string> =>
|
|
8
|
+
value => {
|
|
9
|
+
if (value !== expected) {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
code: 'invalid_equals',
|
|
13
|
+
message: opts?.message ?? `Invalid value, expected ${expected}`,
|
|
14
|
+
expected: expected,
|
|
15
|
+
received: value
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return [];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let notEquals =
|
|
24
|
+
(
|
|
25
|
+
expected: string | number | boolean,
|
|
26
|
+
opts?: { message?: string }
|
|
27
|
+
): ValidationModifier<string> =>
|
|
28
|
+
value => {
|
|
29
|
+
if (value === expected) {
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
code: 'invalid_not_equals',
|
|
33
|
+
message: opts?.message ?? `Invalid value, expected not ${expected}`,
|
|
34
|
+
expected: expected,
|
|
35
|
+
received: value
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [];
|
|
41
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { includes, notIncludes } from './includes';
|
|
3
|
+
|
|
4
|
+
describe('includes modifier', () => {
|
|
5
|
+
test('returns an empty array if the value includes the substring', () => {
|
|
6
|
+
let result = includes('foo')('foobar');
|
|
7
|
+
expect(result).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('returns an error object if the value does not include the substring', () => {
|
|
11
|
+
let result = includes('foo')('bar');
|
|
12
|
+
expect(result).toEqual([
|
|
13
|
+
{
|
|
14
|
+
code: 'invalid_includes',
|
|
15
|
+
message: 'Invalid substring, expected foo',
|
|
16
|
+
expected: 'foo',
|
|
17
|
+
received: 'bar'
|
|
18
|
+
}
|
|
19
|
+
]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('allows a custom error message to be provided', () => {
|
|
23
|
+
let result = includes('foo', { message: 'Custom error message' })('bar');
|
|
24
|
+
expect(result).toEqual([
|
|
25
|
+
{
|
|
26
|
+
code: 'invalid_includes',
|
|
27
|
+
message: 'Custom error message',
|
|
28
|
+
expected: 'foo',
|
|
29
|
+
received: 'bar'
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('notIncludes modifier', () => {
|
|
36
|
+
test('returns an empty array if the value does not include the substring', () => {
|
|
37
|
+
let result = notIncludes('foo')('bar');
|
|
38
|
+
expect(result).toEqual([]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('returns an error object if the value includes the substring', () => {
|
|
42
|
+
let result = notIncludes('foo')('foobar');
|
|
43
|
+
expect(result).toEqual([
|
|
44
|
+
{
|
|
45
|
+
code: 'invalid_not_includes',
|
|
46
|
+
message: 'Invalid substring, expected not foo',
|
|
47
|
+
expected: 'foo',
|
|
48
|
+
received: 'foobar'
|
|
49
|
+
}
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('allows a custom error message to be provided', () => {
|
|
54
|
+
let result = notIncludes('foo', { message: 'Custom error message' })('foobar');
|
|
55
|
+
expect(result).toEqual([
|
|
56
|
+
{
|
|
57
|
+
code: 'invalid_not_includes',
|
|
58
|
+
message: 'Custom error message',
|
|
59
|
+
expected: 'foo',
|
|
60
|
+
received: 'foobar'
|
|
61
|
+
}
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
export let includes =
|
|
4
|
+
(substring: string, opts?: { message?: string }): ValidationModifier<string> =>
|
|
5
|
+
value => {
|
|
6
|
+
if (!value.includes(substring)) {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
code: 'invalid_includes',
|
|
10
|
+
message: opts?.message ?? `Invalid substring, expected ${substring}`,
|
|
11
|
+
expected: substring,
|
|
12
|
+
received: value
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export let notIncludes =
|
|
21
|
+
(substring: string, opts?: { message?: string }): ValidationModifier<string> =>
|
|
22
|
+
value => {
|
|
23
|
+
if (value.includes(substring)) {
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
code: 'invalid_not_includes',
|
|
27
|
+
message: opts?.message ?? `Invalid substring, expected not ${substring}`,
|
|
28
|
+
expected: substring,
|
|
29
|
+
received: value
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return [];
|
|
35
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './color';
|
|
2
|
+
export * from './email';
|
|
3
|
+
export * from './emoji';
|
|
4
|
+
export * from './endsWith';
|
|
5
|
+
export * from './equals';
|
|
6
|
+
export * from './includes';
|
|
7
|
+
export * from './integer';
|
|
8
|
+
export * from './ip';
|
|
9
|
+
export * from './isoDate';
|
|
10
|
+
export * from './length';
|
|
11
|
+
export * from './multipleOf';
|
|
12
|
+
export * from './oneOf';
|
|
13
|
+
export * from './positive';
|
|
14
|
+
export * from './regex';
|
|
15
|
+
export * from './size';
|
|
16
|
+
export * from './startsWith';
|
|
17
|
+
export * from './url';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { integer } from './integer';
|
|
3
|
+
|
|
4
|
+
describe('integer', () => {
|
|
5
|
+
test('should return an empty array if the value is an integer', () => {
|
|
6
|
+
let result = integer()(42);
|
|
7
|
+
expect(result).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('should return an error object if the value is not an integer', () => {
|
|
11
|
+
let result = integer()(0.42);
|
|
12
|
+
expect(result).toEqual([
|
|
13
|
+
{
|
|
14
|
+
code: 'invalid_integer',
|
|
15
|
+
message: 'Invalid value, expected integer',
|
|
16
|
+
expected: 0.42,
|
|
17
|
+
received: 0.42
|
|
18
|
+
}
|
|
19
|
+
]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('should return an error object if the value is not an integer', () => {
|
|
23
|
+
let result = integer()('not an integer' as any);
|
|
24
|
+
expect(result).toEqual([
|
|
25
|
+
{
|
|
26
|
+
code: 'invalid_integer',
|
|
27
|
+
message: 'Invalid value, expected integer',
|
|
28
|
+
expected: 'not an integer',
|
|
29
|
+
received: 'not an integer'
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should use the provided error message if one is provided', () => {
|
|
35
|
+
let result = integer({ message: 'Custom error message' })('not an integer' as any);
|
|
36
|
+
expect(result).toEqual([
|
|
37
|
+
{
|
|
38
|
+
code: 'invalid_integer',
|
|
39
|
+
message: 'Custom error message',
|
|
40
|
+
expected: 'not an integer',
|
|
41
|
+
received: 'not an integer'
|
|
42
|
+
}
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
export let integer =
|
|
4
|
+
(opts?: { message?: string }): ValidationModifier<number> =>
|
|
5
|
+
value => {
|
|
6
|
+
if (!Number.isInteger(value)) {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
code: 'invalid_integer',
|
|
10
|
+
message: opts?.message ?? `Invalid value, expected integer`,
|
|
11
|
+
expected: value,
|
|
12
|
+
received: value
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [];
|
|
18
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { ip } from './ip';
|
|
3
|
+
|
|
4
|
+
describe('ip', () => {
|
|
5
|
+
test('should return an empty array for a valid IPv4 address', () => {
|
|
6
|
+
let result = ip()('192.168.0.1');
|
|
7
|
+
expect(result).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('should return an empty array for a valid IPv6 address', () => {
|
|
11
|
+
let result = ip()('2001:0db8:85a3:0000:0000:8a2e:0370:7334');
|
|
12
|
+
expect(result).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('should return an error object for an invalid IP address', () => {
|
|
16
|
+
let result = ip()('invalid-ip-address');
|
|
17
|
+
expect(result).toEqual([
|
|
18
|
+
{
|
|
19
|
+
code: 'invalid_ip',
|
|
20
|
+
message: 'Invalid ip address'
|
|
21
|
+
}
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('should return a custom error message for an invalid IP address', () => {
|
|
26
|
+
let result = ip({ message: 'Invalid IP address format' })('invalid-ip-address');
|
|
27
|
+
expect(result).toEqual([
|
|
28
|
+
{
|
|
29
|
+
code: 'invalid_ip',
|
|
30
|
+
message: 'Invalid IP address format'
|
|
31
|
+
}
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
let ipV4Regex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
4
|
+
let ipV6Regex =
|
|
5
|
+
/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
|
6
|
+
|
|
7
|
+
export let ip =
|
|
8
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
9
|
+
value => {
|
|
10
|
+
if (!ipV4Regex.test(value) && !ipV6Regex.test(value)) {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
code: 'invalid_ip',
|
|
14
|
+
message: opts?.message ?? 'Invalid ip address'
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return [];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export let ipV4 =
|
|
23
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
24
|
+
value => {
|
|
25
|
+
if (!ipV4Regex.test(value)) {
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
code: 'invalid_ip_v4',
|
|
29
|
+
message: opts?.message ?? 'Invalid ip v4 address'
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return [];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export let ipV6 =
|
|
38
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
39
|
+
value => {
|
|
40
|
+
if (!ipV6Regex.test(value)) {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
code: 'invalid_ip_v6',
|
|
44
|
+
message: opts?.message ?? 'Invalid ip v6 address'
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { isoDate, isoDateTime, isoTime } from './isoDate';
|
|
3
|
+
|
|
4
|
+
describe('isoDate', () => {
|
|
5
|
+
test('should return an empty array if the value is a valid ISO date', () => {
|
|
6
|
+
let result = isoDate()('2022-01-01');
|
|
7
|
+
expect(result).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('should return an error object if the value is not a valid ISO date', () => {
|
|
11
|
+
let result = isoDate()('2022-01-32');
|
|
12
|
+
expect(result).toEqual([
|
|
13
|
+
{
|
|
14
|
+
code: 'invalid_iso_date',
|
|
15
|
+
message: 'Invalid iso date'
|
|
16
|
+
}
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('should return a custom error message if provided', () => {
|
|
21
|
+
let result = isoDate({ message: 'Invalid date format' })('2022-01-32');
|
|
22
|
+
expect(result).toEqual([
|
|
23
|
+
{
|
|
24
|
+
code: 'invalid_iso_date',
|
|
25
|
+
message: 'Invalid date format'
|
|
26
|
+
}
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('isoDateTime', () => {
|
|
32
|
+
test('should return an empty array if the value is a valid ISO date time', () => {
|
|
33
|
+
let result = isoDateTime()('2022-01-01T12:30');
|
|
34
|
+
expect(result).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('should return an error object if the value is not a valid ISO date time', () => {
|
|
38
|
+
let result = isoDateTime()('2022-01-32T25:00');
|
|
39
|
+
expect(result).toEqual([
|
|
40
|
+
{
|
|
41
|
+
code: 'invalid_iso_date_time',
|
|
42
|
+
message: 'Invalid iso date time'
|
|
43
|
+
}
|
|
44
|
+
]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('should return a custom error message if provided', () => {
|
|
48
|
+
let result = isoDateTime({ message: 'Invalid date time format' })('2022-01-32T25:00');
|
|
49
|
+
expect(result).toEqual([
|
|
50
|
+
{
|
|
51
|
+
code: 'invalid_iso_date_time',
|
|
52
|
+
message: 'Invalid date time format'
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('isoTime', () => {
|
|
59
|
+
test('should return an empty array if the value is a valid ISO time', () => {
|
|
60
|
+
let result = isoTime()('12:30');
|
|
61
|
+
expect(result).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('should return an error object if the value is not a valid ISO time', () => {
|
|
65
|
+
let result = isoTime()('25:00');
|
|
66
|
+
expect(result).toEqual([
|
|
67
|
+
{
|
|
68
|
+
code: 'invalid_iso_time',
|
|
69
|
+
message: 'Invalid iso time'
|
|
70
|
+
}
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('should return a custom error message if provided', () => {
|
|
75
|
+
let result = isoTime({ message: 'Invalid time format' })('25:00');
|
|
76
|
+
expect(result).toEqual([
|
|
77
|
+
{
|
|
78
|
+
code: 'invalid_iso_time',
|
|
79
|
+
message: 'Invalid time format'
|
|
80
|
+
}
|
|
81
|
+
]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ValidationModifier } from '../lib/types';
|
|
2
|
+
|
|
3
|
+
let isoDateRegex = /^\d{4}-(0[1-9]|1[0-2])-([12]\d|0[1-9]|3[01])$/;
|
|
4
|
+
let isoDateTimeRegex =
|
|
5
|
+
/^\d{4}-(0[1-9]|1[0-2])-([12]\d|0[1-9]|3[01])T(0[0-9]|1\d|2[0-3]):[0-5]\d$/;
|
|
6
|
+
let isoTimeRegex = /^(0[0-9]|1\d|2[0-3]):[0-5]\d$/;
|
|
7
|
+
|
|
8
|
+
export let isoDate =
|
|
9
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
10
|
+
value => {
|
|
11
|
+
if (!isoDateRegex.test(value)) {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
code: 'invalid_iso_date',
|
|
15
|
+
message: opts?.message ?? 'Invalid iso date'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return [];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let isoDateTime =
|
|
24
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
25
|
+
value => {
|
|
26
|
+
if (!isoDateTimeRegex.test(value)) {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
code: 'invalid_iso_date_time',
|
|
30
|
+
message: opts?.message ?? 'Invalid iso date time'
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return [];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export let isoTime =
|
|
39
|
+
(opts?: { message?: string }): ValidationModifier<string> =>
|
|
40
|
+
value => {
|
|
41
|
+
if (!isoTimeRegex.test(value)) {
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
code: 'invalid_iso_time',
|
|
45
|
+
message: opts?.message ?? 'Invalid iso time'
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [];
|
|
51
|
+
};
|