-
-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example: how to create dedicated email and URL types #109
base: main
Are you sure you want to change the base?
Conversation
); | ||
|
||
return GraphQLEmailType; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@singingwolfboy It seems to me that this plugin adds the Email
type, with a comment, and performs validation on it. However we already perform validation on the type using the domain constraint you added; so I'm not sure if these 149 lines of code add much additional value? If this plugin were removed, would the following be sufficient?
create domain app_public.email as citext check(VALUE ~ '[^@]+@[^@]+\.[^@]+');
comment on domain app_public.email is
'An address in the electronic mail system. Email addresses such as `John.Smith@example.com` are made up of a local-part, followed by an `@` symbol, followed by a domain.';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned in the description of the pull request, the benefit of making an Email
GraphQL scalar is that anyone introspecting the schema knows that the corresponding field won't accept just any string: it must be a valid email address. You're correct that this was already enforced at the database level, but because it wasn't exposed at the schema level, it could cause surprises. Using an Email
scalar is a fairly trivial example, but consider that this repo is also meant to be an example of how to do things with PostGraphile: I think that learning how to create your own GraphQL scalar with PostGraphile is very useful!
For a more concrete example of how this could be useful, consider a front-end application that you can point at an arbitrary GraphQL schema, and it can generate a pretty HTML form for doing queries and mutations on that schema. Because it needs to work with arbitrary schemas, it can't have much knowledge about the structure of the schema that it's going to see: as a result, it makes sense to have this application look at the scalars in the schema, and generate form fields based on that. If we expose the User.email
field as type String
, this application could only generate a standard text field; but if we expose it as type Email
, it could style the field differently and provide dynamic validation based on how emails are formatted.
There's a section in the Shopify GraphQL Design Tutorial about naming and scalars, which I think is relevant here. Semantic value can be really useful for GraphQL clients, so I think it makes sense to expose that semantic value as clearly as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m cool with the custom scalar and totally understand the reasoning; for some reason I was expecting creating a custom domain to result in a custom scalar being created. Seems maybe I never implemented that https://github.com/graphile/graphile-engine/blob/v4/packages/graphile-build-pg/src/plugins/PgTypesPlugin.js#L844
I think I'd like to see this as a separate plugin, potentially a built-in option to PostGraphile, rather than adding a significant amount of code to starter to handle it. Ideally just issuing create domain app_public.email as citext check(VALUE ~ '[^@]+@[^@]+\.[^@]+');
comment on domain app_public.email is
'An address in the electronic mail system. Email addresses such as `John.Smith@example.com` are made up of a local-part, followed by an `@` symbol, followed by a domain.'; should result in the GraphQL schema containing """
An address in the electronic mail system. Email addresses such as
`John.Smith@example.com` are made up of a local-part, followed by
an `@` symbol, followed by a domain.
"""
scalar Email |
That makes sense to me. Are you OK with leaving this pull request open until that feature exists in PostGraphile? That way, other people using PostGraphile are more likely to find this code and use it if they need it. |
Absolutely; I plan to leave it open 👍 |
This pull request uses PostgreSQL's domain types feature to define two new types directly in the database: email and URL. It also modifies the existing tables to use these types where appropriate, and creates two new
graphile-engine
plugins to expose these data types in the GraphQL schema.The benefit of this change is that GraphQL clients are informed that these values in the schema won't accept just any string -- it must be properly formatted, whether it's an email or a URL. This was already enforced in the database, but because it wasn't exposed in the GraphQL type system, clients may not recognize this requirement until they run into a validation error.
If this pull request is accepted, then we can also use the URL type in #108.