Amplify-cli: Adding validation to fields in graphql api schema

Created on 4 Nov 2018  路  15Comments  路  Source: aws-amplify/amplify-cli

* Which Category is your question related to? *
Amplify GraphQL API

Is it possible to add validation to fields in the schema file? So min/max length, min/max value etc? If I had a field on a Person type and wanted to limit their name field to 250 characters, is that possible using the schema file only? Otherwise how can this be done?

feature-request graphql-transformer

Most helpful comment

What directives would you like access to? Over the long term, we can work on building a few transformers that tackle common issues but it would be helpful to hear more about the use cases you want to be solved.

For example, I would suspect these two would be useful:

@regex

directive @regex(expression: String!) on FIELD_DEFINITION

Usage

type Post {
  id: ID!
  title: String @regex(expression: ".*graphql.*")
}

@length

directive @length(min: Int, max: Int) on FIELD_DEFINITION

Usage

type Post {
  id: ID!
  title: String @length(min: 10, max: 255)
}

There are a lot of possibilities so let me know what you think and we will prioritize based on demand.

All 15 comments

We don't package any transformers that allow you to do this out of the box but have discussed use cases like this in the past. If you want to do this purely using the schema.graphql today, you can write your own transformer that will augment the generated resolver template code. To make this work you will also need to write your own light-weight CLI that loads and runs the transformer. There are docs on this here https://aws-amplify.github.io/docs/js/graphql#writing-custom-transformers.

The way to implement this in AppSync is to write resolver code that validates inputs during mutations. For example, if you wanted to validate that the "name" is a max of 250 characters then you would add a snippet like this to createPerson and updatePerson resolvers:

## mutation.create/updatePerson.request.vtl **
#if( $ctx.args.input.name.length() > 250 )
    $util.error("Value for input field `CreatePersonInput.name` cannot exceed 250 characters.")
#end

If you provided a name longer than 250 characters this would cause the mutation to fail before saving the object to DynamoDB. This is how your custom transformer would work too, but you would be generating the above snippet in your transformer instead of writing it by hand.

What directives would you like access to? Over the long term, we can work on building a few transformers that tackle common issues but it would be helpful to hear more about the use cases you want to be solved.

For example, I would suspect these two would be useful:

@regex

directive @regex(expression: String!) on FIELD_DEFINITION

Usage

type Post {
  id: ID!
  title: String @regex(expression: ".*graphql.*")
}

@length

directive @length(min: Int, max: Int) on FIELD_DEFINITION

Usage

type Post {
  id: ID!
  title: String @length(min: 10, max: 255)
}

There are a lot of possibilities so let me know what you think and we will prioritize based on demand.

@mikeparisstuff thanks for the code snippet. I'll take a look at this. As for the possible directives. I guess what you mentioned sounds reasonable with the addition of maybe:

  • @equals - equality check which would work for all/most types like int, ID, string etc
  • @notEqual - not equal to
  • @in - a set of values that it can be
  • @notIn - a set of values that it can never be (I wonder if this would actually be useful)
  • @lt - less than (should probably work with numbers/times etc)
  • @gt - greater than (similar to above)
  • @multipleOf - check if value is multiple of some input

there's also a few common simplified regex checks I guess. @startsWIth, @endsWith, @contains

also for the length implementation, should max be optional somehow? Maybe we want the value to be at least 10.

@rayhaanq Thanks for those suggestions. I will take a note of all of these and will try to write up a more formal design that covers a subset of useful directives and publish it so that we can get more feedback on these features.

This is also another good use case for supporting custom transformers that would allow you to define your own directives that could be run as part of the Amplify CLI. For example, you could write a transformer on your local machine and then import it such that it is loaded by the amplify CLI:

"transformers": [
  "path/to/local/transformer.js"
]

Would you be interested in such functionality? This would provide another safety hatch for advanced behavior that is not supported OOTB by the transform.

I would be interested for sure. I was looking for something like a @readonly directive which would cause the field to be excluded from the generated Inputs but available for "reading". I'd imagine a @writeonly field might be something we'd want as well. Maybe something like @toUpper @toLower, etc. It would be great to be able to create these on our own even if not available in core amplify-cli.

Do we have any update about those new directives? This is a very interesting matter if we want to build an complete application while writing the minimum of serveless code

This would be amazing! Hoping for news on availability soon... maybe re:Invent?!

This would be great and would really make writing complex models a breeze! Is there anything planned for above mentioned directives?

I would be interested for sure. I was looking for something like a @readonly directive which would cause the field to be excluded from the generated Inputs but available for "reading". I'd imagine a @writeonly field might be something we'd want as well. Maybe something like @toupper @tolower, etc. It would be great to be able to create these on our own even if not available in core amplify-cli.

I think the @readonly usage is covered by: https://www.npmjs.com/package/graphql-auto-transformer by @hirochachacha

And there's @tolower: https://www.npmjs.com/package/graphql-lowercase-transformer by @hisham

Hopefully someone can step in and create the directives mentioned by @mikeparisstuff above.

I've made https://github.com/hirochachacha/graphql-assert-transformer

type Post @model {
  id: ID!
  title: String @assert(condition: """.length() > 3 && .matches("t.*")""")
  text: String @assert(condition: ".length() > 10")
  episode: Int @assert(condition: ". % 2 == 0")
}

It would be great something like this to uniq validation or any other necessity:

@custom("lambda-${env}")

Any updates on the custom field validations?

Fro custom field level validations, I would highly recommend looking at writing custom transformer directive plugins based on our docs here - https://docs.amplify.aws/cli/plugins/authoring#custom-graphql-transformers

Found a similar 3rd party custom directive plugin here for field level validations/operations - https://www.npmjs.com/package/graphql-default-value-transformer and the code for which is here https://github.com/trek10inc/graphql-default-value-transformer

Also, as @andreialecu mentioned there are some more 3rd party custom directives which you could leverage:

@readonly usage is covered by: https://www.npmjs.com/package/graphql-auto-transformer by @hirochachacha
@tolower: https://www.npmjs.com/package/graphql-lowercase-transformer by @hisham

If you'd like something really specific which can't be built with a custom directive and which all our customers can leverage as a default, I would recommend opening up an RFC in our repo and we can discuss it for including it as a part of our code offering.

any updates on this??

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jeanpaulcozzatti picture jeanpaulcozzatti  路  3Comments

ReidWeb picture ReidWeb  路  3Comments

amlcodes picture amlcodes  路  3Comments

davo301 picture davo301  路  3Comments

gabriel-wilkes picture gabriel-wilkes  路  3Comments