@conform-to/yup 0.4.0-pre.2 → 0.4.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/README.md +60 -13
- package/index.js +14 -24
- package/module/index.js +14 -25
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
## API Reference
|
|
8
8
|
|
|
9
9
|
- [formatError](#formatError)
|
|
10
|
+
- [getFieldsetConstraint](#getfieldsetconstraint)
|
|
11
|
+
- [validate](#validate)
|
|
10
12
|
|
|
11
13
|
<!-- /aside -->
|
|
12
14
|
|
|
@@ -17,7 +19,7 @@ This formats Yup `ValidationError` to the **conform** error structure (i.e. A se
|
|
|
17
19
|
If the error received is not provided by Yup, it will be treated as a form level error with message set to **error.messages** or **Oops! Something went wrong.** if no fallback message is provided.
|
|
18
20
|
|
|
19
21
|
```tsx
|
|
20
|
-
import { useForm } from '@conform-to/react';
|
|
22
|
+
import { useForm, parse } from '@conform-to/react';
|
|
21
23
|
import { formatError } from '@conform-to/yup';
|
|
22
24
|
import * as yup from 'yup';
|
|
23
25
|
|
|
@@ -29,23 +31,25 @@ const schema = yup.object({
|
|
|
29
31
|
|
|
30
32
|
function ExampleForm() {
|
|
31
33
|
const formProps = useForm<yup.InferType<typeof schema>>({
|
|
32
|
-
onValidate({
|
|
34
|
+
onValidate({ formData }) {
|
|
35
|
+
const submission = parse(formData);
|
|
36
|
+
|
|
33
37
|
try {
|
|
34
38
|
// Only sync validation is allowed on the client side
|
|
35
39
|
schema.validateSync(submission.value, {
|
|
36
40
|
abortEarly: false,
|
|
37
41
|
});
|
|
38
42
|
} catch (error) {
|
|
39
|
-
submission.error
|
|
43
|
+
submission.error.push(
|
|
40
44
|
// The 2nd argument is an optional fallback message
|
|
41
|
-
formatError(
|
|
45
|
+
...formatError(
|
|
42
46
|
error,
|
|
43
47
|
'The application has encountered an unknown error.',
|
|
44
48
|
),
|
|
45
49
|
);
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
return submission;
|
|
49
53
|
},
|
|
50
54
|
});
|
|
51
55
|
|
|
@@ -74,17 +78,11 @@ export let action = async ({ request }) => {
|
|
|
74
78
|
abortEarly: false,
|
|
75
79
|
});
|
|
76
80
|
|
|
77
|
-
if (submission.
|
|
81
|
+
if (submission.type !== 'validate') {
|
|
78
82
|
return await handleFormData(data);
|
|
79
83
|
}
|
|
80
84
|
} catch (error) {
|
|
81
|
-
|
|
82
|
-
submission.error = submission.error.concat(formatError(error));
|
|
83
|
-
} else {
|
|
84
|
-
submission.error = submission.error.concat([
|
|
85
|
-
['', 'Sorry, something went wrong.'],
|
|
86
|
-
]);
|
|
87
|
-
}
|
|
85
|
+
submission.error.push(...formatError(error));
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
return submission;
|
|
@@ -100,3 +98,52 @@ export default function ExampleRoute() {
|
|
|
100
98
|
// ...
|
|
101
99
|
}
|
|
102
100
|
```
|
|
101
|
+
|
|
102
|
+
### getFieldsetConstraint
|
|
103
|
+
|
|
104
|
+
This tries to infer constraint of each field based on the yup schema. This is useful only for:
|
|
105
|
+
|
|
106
|
+
1. Make it easy to style input using CSS, e.g. `:required`
|
|
107
|
+
2. Have some basic validation working before/without JS. But the message is not customizable and it might be simpler and cleaner relying on server validation.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { getFieldsetConstraint } from '@conform-to/yup';
|
|
111
|
+
|
|
112
|
+
function LoginFieldset() {
|
|
113
|
+
const form = useForm();
|
|
114
|
+
const { email, password } = useFieldset(ref, {
|
|
115
|
+
...form.config,
|
|
116
|
+
constraint: getFieldsetConstraint(schema),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// ...
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### validate
|
|
124
|
+
|
|
125
|
+
It parses the formData and returns a [submission](/docs/submission.md) object with the validation error, which removes the boilerplate code shown on the [formatError](#formaterror) example.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import { useForm } from '@conform-to/react';
|
|
129
|
+
import { validate } from '@conform-to/yup';
|
|
130
|
+
import * as yup from 'yup';
|
|
131
|
+
|
|
132
|
+
const schema = yup.object({
|
|
133
|
+
email: yup.string().required(),
|
|
134
|
+
password: yup.string().required(),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
function ExampleForm() {
|
|
138
|
+
const formProps = useForm({
|
|
139
|
+
onValidate({ formData }) {
|
|
140
|
+
return validate(formData, schema, {
|
|
141
|
+
// Optional
|
|
142
|
+
fallbackMessage: 'The application has encountered an unknown error.',
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ...
|
|
148
|
+
}
|
|
149
|
+
```
|
package/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var dom = require('@conform-to/dom');
|
|
5
6
|
var yup = require('yup');
|
|
6
7
|
|
|
7
8
|
function _interopNamespace(e) {
|
|
@@ -28,10 +29,8 @@ function getFieldsetConstraint(source) {
|
|
|
28
29
|
var description = source.describe();
|
|
29
30
|
return Object.fromEntries(Object.entries(description.fields).map(_ref => {
|
|
30
31
|
var _test$params, _test$params3, _test$params5, _test$params6, _test$params8;
|
|
31
|
-
|
|
32
32
|
var [key, def] = _ref;
|
|
33
33
|
var constraint = {};
|
|
34
|
-
|
|
35
34
|
switch (def.type) {
|
|
36
35
|
case 'string':
|
|
37
36
|
{
|
|
@@ -40,88 +39,79 @@ function getFieldsetConstraint(source) {
|
|
|
40
39
|
case 'required':
|
|
41
40
|
constraint.required = true;
|
|
42
41
|
break;
|
|
43
|
-
|
|
44
42
|
case 'min':
|
|
45
43
|
if (!constraint.minLength || constraint.minLength < Number((_test$params = test.params) === null || _test$params === void 0 ? void 0 : _test$params.min)) {
|
|
46
44
|
var _test$params2;
|
|
47
|
-
|
|
48
45
|
constraint.minLength = Number((_test$params2 = test.params) === null || _test$params2 === void 0 ? void 0 : _test$params2.min);
|
|
49
46
|
}
|
|
50
|
-
|
|
51
47
|
break;
|
|
52
|
-
|
|
53
48
|
case 'max':
|
|
54
49
|
if (!constraint.maxLength || constraint.maxLength > Number((_test$params3 = test.params) === null || _test$params3 === void 0 ? void 0 : _test$params3.max)) {
|
|
55
50
|
var _test$params4;
|
|
56
|
-
|
|
57
51
|
constraint.maxLength = Number((_test$params4 = test.params) === null || _test$params4 === void 0 ? void 0 : _test$params4.max);
|
|
58
52
|
}
|
|
59
|
-
|
|
60
53
|
break;
|
|
61
|
-
|
|
62
54
|
case 'matches':
|
|
63
55
|
if (!constraint.pattern && ((_test$params5 = test.params) === null || _test$params5 === void 0 ? void 0 : _test$params5.regex) instanceof RegExp) {
|
|
64
56
|
constraint.pattern = test.params.regex.source;
|
|
65
57
|
}
|
|
66
|
-
|
|
67
58
|
break;
|
|
68
59
|
}
|
|
69
60
|
}
|
|
70
|
-
|
|
71
61
|
if (!constraint.pattern && def.oneOf.length > 0) {
|
|
72
62
|
constraint.pattern = def.oneOf.join('|');
|
|
73
63
|
}
|
|
74
|
-
|
|
75
64
|
break;
|
|
76
65
|
}
|
|
77
|
-
|
|
78
66
|
case 'number':
|
|
79
67
|
for (var _test of def.tests) {
|
|
80
68
|
switch (_test.name) {
|
|
81
69
|
case 'required':
|
|
82
70
|
constraint.required = true;
|
|
83
71
|
break;
|
|
84
|
-
|
|
85
72
|
case 'min':
|
|
86
73
|
if (!constraint.min || constraint.min < Number((_test$params6 = _test.params) === null || _test$params6 === void 0 ? void 0 : _test$params6.min)) {
|
|
87
74
|
var _test$params7;
|
|
88
|
-
|
|
89
75
|
constraint.min = Number((_test$params7 = _test.params) === null || _test$params7 === void 0 ? void 0 : _test$params7.min);
|
|
90
76
|
}
|
|
91
|
-
|
|
92
77
|
break;
|
|
93
|
-
|
|
94
78
|
case 'max':
|
|
95
79
|
if (!constraint.max || constraint.max > Number((_test$params8 = _test.params) === null || _test$params8 === void 0 ? void 0 : _test$params8.max)) {
|
|
96
80
|
var _test$params9;
|
|
97
|
-
|
|
98
81
|
constraint.max = Number((_test$params9 = _test.params) === null || _test$params9 === void 0 ? void 0 : _test$params9.max);
|
|
99
82
|
}
|
|
100
|
-
|
|
101
83
|
break;
|
|
102
84
|
}
|
|
103
85
|
}
|
|
104
|
-
|
|
105
86
|
break;
|
|
106
87
|
}
|
|
107
|
-
|
|
108
88
|
return [key, constraint];
|
|
109
89
|
}));
|
|
110
90
|
}
|
|
111
91
|
function formatError(error) {
|
|
112
92
|
var fallbackMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Oops! Something went wrong.';
|
|
113
|
-
|
|
114
93
|
if (error instanceof yup__namespace.ValidationError) {
|
|
115
94
|
return error.inner.reduce((result, e) => {
|
|
116
95
|
var _e$path;
|
|
117
|
-
|
|
118
96
|
result.push([(_e$path = e.path) !== null && _e$path !== void 0 ? _e$path : '', e.message]);
|
|
119
97
|
return result;
|
|
120
98
|
}, []);
|
|
121
99
|
}
|
|
122
|
-
|
|
123
100
|
return [['', error instanceof Error ? error.message : fallbackMessage]];
|
|
124
101
|
}
|
|
102
|
+
function validate(formData, schema) {
|
|
103
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
104
|
+
var submission = dom.parse(formData);
|
|
105
|
+
try {
|
|
106
|
+
schema.validateSync(submission.value, {
|
|
107
|
+
abortEarly: false
|
|
108
|
+
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
submission.error.push(...formatError(error, options.fallbackMessage));
|
|
111
|
+
}
|
|
112
|
+
return submission;
|
|
113
|
+
}
|
|
125
114
|
|
|
126
115
|
exports.formatError = formatError;
|
|
127
116
|
exports.getFieldsetConstraint = getFieldsetConstraint;
|
|
117
|
+
exports.validate = validate;
|
package/module/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { parse } from '@conform-to/dom';
|
|
1
2
|
import * as yup from 'yup';
|
|
2
3
|
|
|
3
4
|
function getFieldsetConstraint(source) {
|
|
4
5
|
var description = source.describe();
|
|
5
6
|
return Object.fromEntries(Object.entries(description.fields).map(_ref => {
|
|
6
7
|
var _test$params, _test$params3, _test$params5, _test$params6, _test$params8;
|
|
7
|
-
|
|
8
8
|
var [key, def] = _ref;
|
|
9
9
|
var constraint = {};
|
|
10
|
-
|
|
11
10
|
switch (def.type) {
|
|
12
11
|
case 'string':
|
|
13
12
|
{
|
|
@@ -16,87 +15,77 @@ function getFieldsetConstraint(source) {
|
|
|
16
15
|
case 'required':
|
|
17
16
|
constraint.required = true;
|
|
18
17
|
break;
|
|
19
|
-
|
|
20
18
|
case 'min':
|
|
21
19
|
if (!constraint.minLength || constraint.minLength < Number((_test$params = test.params) === null || _test$params === void 0 ? void 0 : _test$params.min)) {
|
|
22
20
|
var _test$params2;
|
|
23
|
-
|
|
24
21
|
constraint.minLength = Number((_test$params2 = test.params) === null || _test$params2 === void 0 ? void 0 : _test$params2.min);
|
|
25
22
|
}
|
|
26
|
-
|
|
27
23
|
break;
|
|
28
|
-
|
|
29
24
|
case 'max':
|
|
30
25
|
if (!constraint.maxLength || constraint.maxLength > Number((_test$params3 = test.params) === null || _test$params3 === void 0 ? void 0 : _test$params3.max)) {
|
|
31
26
|
var _test$params4;
|
|
32
|
-
|
|
33
27
|
constraint.maxLength = Number((_test$params4 = test.params) === null || _test$params4 === void 0 ? void 0 : _test$params4.max);
|
|
34
28
|
}
|
|
35
|
-
|
|
36
29
|
break;
|
|
37
|
-
|
|
38
30
|
case 'matches':
|
|
39
31
|
if (!constraint.pattern && ((_test$params5 = test.params) === null || _test$params5 === void 0 ? void 0 : _test$params5.regex) instanceof RegExp) {
|
|
40
32
|
constraint.pattern = test.params.regex.source;
|
|
41
33
|
}
|
|
42
|
-
|
|
43
34
|
break;
|
|
44
35
|
}
|
|
45
36
|
}
|
|
46
|
-
|
|
47
37
|
if (!constraint.pattern && def.oneOf.length > 0) {
|
|
48
38
|
constraint.pattern = def.oneOf.join('|');
|
|
49
39
|
}
|
|
50
|
-
|
|
51
40
|
break;
|
|
52
41
|
}
|
|
53
|
-
|
|
54
42
|
case 'number':
|
|
55
43
|
for (var _test of def.tests) {
|
|
56
44
|
switch (_test.name) {
|
|
57
45
|
case 'required':
|
|
58
46
|
constraint.required = true;
|
|
59
47
|
break;
|
|
60
|
-
|
|
61
48
|
case 'min':
|
|
62
49
|
if (!constraint.min || constraint.min < Number((_test$params6 = _test.params) === null || _test$params6 === void 0 ? void 0 : _test$params6.min)) {
|
|
63
50
|
var _test$params7;
|
|
64
|
-
|
|
65
51
|
constraint.min = Number((_test$params7 = _test.params) === null || _test$params7 === void 0 ? void 0 : _test$params7.min);
|
|
66
52
|
}
|
|
67
|
-
|
|
68
53
|
break;
|
|
69
|
-
|
|
70
54
|
case 'max':
|
|
71
55
|
if (!constraint.max || constraint.max > Number((_test$params8 = _test.params) === null || _test$params8 === void 0 ? void 0 : _test$params8.max)) {
|
|
72
56
|
var _test$params9;
|
|
73
|
-
|
|
74
57
|
constraint.max = Number((_test$params9 = _test.params) === null || _test$params9 === void 0 ? void 0 : _test$params9.max);
|
|
75
58
|
}
|
|
76
|
-
|
|
77
59
|
break;
|
|
78
60
|
}
|
|
79
61
|
}
|
|
80
|
-
|
|
81
62
|
break;
|
|
82
63
|
}
|
|
83
|
-
|
|
84
64
|
return [key, constraint];
|
|
85
65
|
}));
|
|
86
66
|
}
|
|
87
67
|
function formatError(error) {
|
|
88
68
|
var fallbackMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Oops! Something went wrong.';
|
|
89
|
-
|
|
90
69
|
if (error instanceof yup.ValidationError) {
|
|
91
70
|
return error.inner.reduce((result, e) => {
|
|
92
71
|
var _e$path;
|
|
93
|
-
|
|
94
72
|
result.push([(_e$path = e.path) !== null && _e$path !== void 0 ? _e$path : '', e.message]);
|
|
95
73
|
return result;
|
|
96
74
|
}, []);
|
|
97
75
|
}
|
|
98
|
-
|
|
99
76
|
return [['', error instanceof Error ? error.message : fallbackMessage]];
|
|
100
77
|
}
|
|
78
|
+
function validate(formData, schema) {
|
|
79
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
80
|
+
var submission = parse(formData);
|
|
81
|
+
try {
|
|
82
|
+
schema.validateSync(submission.value, {
|
|
83
|
+
abortEarly: false
|
|
84
|
+
});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
submission.error.push(...formatError(error, options.fallbackMessage));
|
|
87
|
+
}
|
|
88
|
+
return submission;
|
|
89
|
+
}
|
|
101
90
|
|
|
102
|
-
export { formatError, getFieldsetConstraint };
|
|
91
|
+
export { formatError, getFieldsetConstraint, validate };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@conform-to/yup",
|
|
3
3
|
"description": "Conform schema resolver for yup",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.4.0
|
|
5
|
+
"version": "0.4.0",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "module/index.js",
|
|
8
8
|
"repository": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@conform-to/dom": "0.4.0
|
|
17
|
+
"@conform-to/dom": "0.4.0",
|
|
18
18
|
"yup": ">=0.32.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|