graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Integrate with graphql-code-generator and validation libraries

Open corysimmons opened this issue 2 years ago • 2 comments

Is your feature request related to a problem? Please describe. I would love to use my Neo4j GraphQL schemas as the single source of truth for all my frontend forms as well as anything that can go into the db.

Currently I have to:

  • create constraints in the db manually using Cypher
  • basically clone my neo4j .graphql model to something like Zod to use on the frontend

Describe the solution you'd like It would be amazing if Neo4j's GraphQL offering just tightly integrated with a modern validation lib like Zod so I could write my schema files in one place like so:

input ExampleInput {
  email: String! @required(msg: "Hello, World!") @constraint(minLength: 50, format: "email")
  message: String! @constraint(startsWith: "Hello")
}

And these constraints would be valid in the db, and I could use the generated type in my frontend forms.

Describe alternatives you've considered

I've tried to use a few libraries to do something similar to this:

  • https://github.com/withshepherd/graphql-codegen-zod (buggy, unmaintained, and doesn't work with graphql@16)
  • https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema (a great project that tries to work with everything, but I still can't get its custom directives to work with my introspected graphql api)

Additional context

It seems like there is a big lack of modern validation going on with Neo4j (it's really something that has me worried about diving in). I think you can do it with Cypher and creating constraints, but even then you have to be on an "Enterprise" plan to get relationship constraints?

Is there any way for the little startup to get relationship constraints?

Is there any hope of a clean (something like Zod) way to add validation/constraints to our graphql schemas that are honored by the database?

corysimmons avatar Jun 09 '22 04:06 corysimmons

We love this idea and it's been on our minds for a long time!

If we were to implement this in the library, I think constraints applied at the GraphQL make the most sense - essentially input validation on Mutations which would modify the database, and throwing an error if the input violates the constraints.

It might not make it's way into our planned work for a little while due to competing demands, however, we always welcome community collaboration if a contributor wants to pick this up!

darrellwarde avatar Jun 15 '22 10:06 darrellwarde

Maybe. I'm on the fence about where validation should live.

I think it'd be better as Zod models that simply worked with Neo4j GraphQL. There are already tons of integrations with these validation libraries and other stuff. For instance check out this library where you can make a Zod model and then just pass it into react-hook-form to easily create clientside errors https://github.com/react-hook-form/resolvers and this library to get backend Express validation from the same Zod model https://www.npmjs.com/package/zod-express-middleware

If there was a way to do something like

import {SomeZodModel} from '~/YourZodModels'

export default gql`
input SomeNeo4jType {
  email: String! @validationModel(SomeZodModel)
}
`

And use that same validation model in other places:

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

import {SomeZodModel} from '~/YourZodModels'

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(SomeZodModel),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      {errors.name?.message && <p>{errors.name?.message}</p>}
      <input type="submit" />
    </form>
  );
};

That would be amazing.

Maybe Neo4j GraphQL could just straight-up copy some open-source and package it up as part of core Neo4j GraphQL to offer the same functionality (and make some integrations with things like react-hook-form, Express, etc), but built into the GraphQL type? I'm not sure how that'd look and it seems like more work than simply

email: String! @validationModel(SomeZodModel)`

What are your thoughts? If we can figure this out and I can get some guidance I might be up for working on this.

corysimmons avatar Jun 15 '22 14:06 corysimmons

There's some good ideas here for an eventual solution, but going to close this in favour of #138 which has been around for (a lot) longer and really the principal is the same. Thanks!

darrellwarde avatar Aug 25 '22 16:08 darrellwarde