#✅ - How to auto-generate attributes in GraphQL mutations resolvers

15 messages · Page 1 of 1 (latest)

analog snow
#

Hey, y'all! I am trying to update the mutations resolver to auto-generate IDs and timestamps for a posts feature we are adding to our app, but am struggling to find the appropriate places to make these changes within the Amplify-generated resolvers. Any advice would be welcome!

analog snow
#

As a secondary issue, I am having trouble when mocking some queries for this API. I want to query with PK "owner" and SK "timestamp" but in my mock functions, they are returning empty lists while my other query (PK "type" SK "timestep") works.

Here is my schema:

type Post
  @model (
    mutations: {create: "createPost", delete: "deletePost", update: null}
    timestamps: null
    subscriptions: { level: public}
  )
  @auth(rules: [
    {allow: owner, ownerField:"owner", provider: userPools, operations:[read, create, delete]}
    {allow: private, provider: userPools, operations:[read]}
  ])
{
  type: String! @index(name: "listPostsSortedByTimestamp", sortKeyFields: ["timestamp"])
  id: ID! @primaryKey
  content: String!
  owner: String @index(name: "listPostsBySpecificOwner", sortKeyFields: ["timestamp"])
  timestamp: Int!
}
jagged compass
# analog snow Hey, y'all! I am trying to update the mutations resolver to auto-generate IDs an...

Hi @analog snow . Let's say you have the following schema:


type Todo 
  @model(
    timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" } ## <<-- for the timestamps
  )
{
  todoId: ID! @primaryKey ## <<-- for the autogenerated ID
  content: String
}

The timestamps: {...} annotates your Model to tell Amplify which fields represent your timestamps. Amplify will then set this value on create and update operations for you.

You can find more about this here: https://docs.amplify.aws/cli/graphql/data-modeling/#customize-creation-and-update-timestamps

The todoId field will be assigned an autogenerated UUID since it is annotated with @primaryKey by default.

To achieve this, Amplify creates the following resolvers:

`MyApi/build/resolvers/Post.createPost.init.1.req.vtl` 
`MyApi/build/resolvers/Post.updatePost.init.1.req.vtl`

The createPost.init.1.req.vtl would look like this:


## [Start] Initialization default values. **
$util.qr($ctx.stash.put("defaultValues", $util.defaultIfNull($ctx.stash.defaultValues, {})))
#set( $createdAt = $util.time.nowISO8601() )
$util.qr($ctx.stash.defaultValues.put("id", $util.autoId()))
$util.qr($ctx.stash.defaultValues.put("createdAt", $createdAt))
$util.qr($ctx.stash.defaultValues.put("updatedAt", $createdAt))
$util.toJson({
  "version": "2018-05-29",
  "payload": {}
})
## [End] Initialization default values. **

#

If you want to override these values you can set them yourself in a similar way. You would create an resolver for the init slot. For example,

Let's say your model is called Post, you would create a file resolvers/Mutation.createPost.init.X.req.vtl. If you want to replace the existing code, you would use the the same index (i.e. '1'). However, if you want to maintain the default behavior and add additional logic then you would replace X with 2 or any other index that wasn't already in use.

You can find out more about the slots here:
https://docs.amplify.aws/cli/graphql/custom-business-logic/#extend-amplify-generated-resolvers

NOTE
Preference is given to the input values over default values. So if these values are important to you then you can ensure that your value holds. You can:

  1. Clobber the input value with the generated value. For example, set the value for $args.input.createdAt so that it replaces any user input.
  2. Modify your schema so that you remove the values that you don't want the user to set as shown below. This will prevent the user from sending any values for the removed fields. Just don't forget to modify this to keep it in sync with your model as it evolves.

input TodoInput {
  id: ID! ## <<-- remove this
  name: String!
  description: String
  createdOn: AWSDateTime! ## <<-- remove this
  updatedOn: AWSDateTime! ## <<-- remove this
}

analog snow
#

Wow @jagged compass. Thank you for providing such a deep explanation and clearing a lot of this up, this was immensely helpful.

#

Here is my updated schema:

type Post
  @model (
    mutations: {create: "createPost", delete: "deletePost", update: null}
    timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" }
    subscriptions: { level: public }
  )
  @auth(rules: [
    {allow: owner, ownerField:"owner", provider: userPools, operations:[read, create, delete]}
    {allow: private, provider: userPools, operations:[read]}
  ])
{
  type: String! @index(name: "listPostsSortedByTimestamp", sortKeyFields: ["createdOn"])
  id: ID! @primaryKey
  content: String!
  owner: String @index(name: "listPostsBySpecificOwner", sortKeyFields: ["createdOn"])
  createdOn: AWSDateTime!
  updatedOn: AWSDateTime!
}
#

I am now having issues with the indexes I have set up. I am returning no data for both after performing some createPost operations.

jagged compass
jagged compass
analog snow
#

I am currently mocking the information through amplify CLI. I haven't been able to see the data in the console that i have been messing around with

frozen wagon
#

FYI, for those who have relationships which are sorted on the built-in field 'createdAt'. ( to do this one has to add a createdAt field to the referenced model ) Some recent change to DataStore has made it so that one must pass a non-null dummy value for the 'createdAt' field when creating a new record. Prior to a week or two ago, the createdAt field could be left out of the DataStore.save(new MyModel, ...) call as one would expect and DataStore would update the record with the built-in fields.

mossy orioleBOT
#

✅ - How to auto-generate attributes in GraphQL mutations resolvers