Open ericwooley opened 3 years ago
I have a branch started https://github.com/ericwooley/graphql-code-generator/tree/react-formik
However, I am running into a strange issue when using yarn build && yarn generate:examples
. If anyone knows why I'm getting this issue, that would be very helpful!
Found 1 error
✖ ./dev-test/test-schema/formik.tsx
Error: Cannot use GraphQLScalarType "Int" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
Having played around with the concept a bit more. It may be sufficient to only support primitives and provide most of the value. Since you could build your mutations from primitives pretty easily. If Object types are never supported though, it could lead to a lot of long argument lists in mutations. Lists would also probably be requested rather quickly as well.
I decided to remove formik, because it can be done easily enough without formik.
Additionally, I could not get past the above issue about modules or realms. I think it has something to do with esm builds :shrug:
I moved development here: https://github.com/ericwooley/graphql-code-generator-react-form
I published the examples as a website, and re-used some of your iamges etc... Hopefully thats ok. Ideally, I would love the plugin to be merged into this repo, but not being able to use the graphql
package was a blocker.
@ericwooley imho, what would be cool is creating a yup or zod schema from the GraphQL schema (for inputs)
@mmahalwy :+1: I was thinking about yup for validation. But I didn't want to impose a library on the user. I have a near working version inspired by yup, that I think would be compatible. Then there could be another plugin for generating yup validations.
The API I have nearly working is a validate function, where you return an object. The object has keys that match your variable names. EG
mutation myMutation ($text1: String! $text2: String) {
# ...
}
function validateMyMutation (values: {text1: string, text2?: string}): {text1: string, text2?: string} {
// IIRC there is a way to get errors out of yup in an object format.
return {
text1: values.text1? '' : 'Error, text1 is required',
// text 2 is not required, so don't validate.
}
}
The validation is WIP right now. Hopefully, I'll make more progress this weekend. Enough progress to share and get feedback on.
@ericwooley i created this. Still very raw: https://github.com/mmahalwy/codegen-graphql-zod
Nice, I'll take I'll take a look at that.
Graphql Schemas provide everything we need to generate the form.
I have to disagree here. There is a great deal of validation information not described by GraphQL schema. At some point, you will need to extend the validation schema by adding constraints on minimum length, string URL format, default values (transformers), etc.
It might be possible using zod
’s .extend
but I think this can get pretty unreadable. Moreover, there can be cases where the form doesn’t match the mutation input completely. I tend to create form schemas per form (not per mutation) and let typescript check that both are compatible.
That being said, surely there are use-cases where the 1:1 mutation form schema is appropriate.
@brabeji You are right about validation. Part of the API is to allow validation on a per input basis. Which is what I'm currently working on.
You can also customize input components by scalar, per form, or globally through context.
For the more verbose update: https://twitter.com/ericwooley/status/1399191213501153289
as far as the validation API, here is what validation will look like for now: https://github.com/ericwooley/graphql-code-generator-react-form/blob/main/examples/components/addUser.tsx#L14 @mmahalwy @brabeji LMK what you think.
And here is a customized input that shows the errors: https://github.com/ericwooley/graphql-code-generator-react-form/blob/main/examples/components/addUser.tsx#L43
You can see it in action on the first form here: https://graphql-code-generator-react-form.thewooleyway.com/
It's not complete yet, so validation does not yet block form submission, and there is no validation setup on the complex forms yet, but it should work, according to typescript.
Validation took FOR EV ER. Lots of edge cases and small things to deal with. But I think it's basically done, there might be some small edge cases that I missed, but the api feels good, and handles all the cases I can think of.
If you can think of any other cases, please LMK.
Forms are the majority of the front end work in a lot of applications. Graphql Schemas provide everything we need to generate the form.
Some tooling exists for doing similar things. EG: uniform.tools and a few other dead packages that attempt to do this at runtime.
IMO generating the forms would be a much better approach.
Formik is a very popular react form library with support for typescript, validation, and nested objects.
A form generation plugin is tricky because it needs to be customizable enough to suit peoples needs, with regards to styles and implementations of inputs, as well as validation, and hidden elements. The way formik is built provides an easy (ish) path to code generation, because it uses context for values, change handlers, metadata, etc...
The plugin should generate a "base" input for each built in scalar. Then Input Object types, and lists can be recursively composed from the base inputs.
Lists should be their own component as well, with an delete for each button in the list, and an add button at the end.
Circular references for Input Types can be handled by an
Add <InputTypeName>
.Customization could be handled by generating a context Provider, which allows over rides for scalar types.
EG of a simple output
example usage
Additionally, default types, and basic yup validations could also be generated.