Giter VIP home page Giter VIP logo

graphql-auto-transformer's Introduction

graphql-auto-transformer

A custom transformer of the amplify-cli. It can control accessibility of auto generated fields.

directive @auto(creatable: Boolean = false, updatable: Boolean = false) on FIELD_DEFINITION

Motivation

If you are familiar with amplify-cli, you know several fields of object are generated by some directives. For example, @model generates createdAt and updatedAt, @versioned generates version, @auth generates owner and so on. Currently, the official way to access these fields from GraphQL API is to define these types as nullable types.

type Post @model {
  id: ID!
  text: String
  createdAt: AWSDateTime
}

However above solution isn't ideal because users can modify createdAt at any time.

input CreatePostInput {
  id: ID
  text: String
  createdAt: AWSDateTime
}

input UpdatePostInput {
  id: ID!
  text: String
  createdAt: AWSDateTime
}

We want to strip createdAt field from CreatePostInput and UpdatePostInput.

What is worse, we cannot use nullable type as a part of a database index. So, we should write:

type Post
  @model
  @key(name: "byUser", fields: ["userId", "createdAt"]) {
    id: ID!
    userId: ID!
    text: String
    createdAt: AWSDateTime!
}

Predictabley, the result is bad. aws-amplify/amplify-cli#1657

Usage

1. Install package

npm install graphql-auto-transformer -D

or

yarn add graphql-auto-transformer -D

2. Setup custom transformer

Edit amplify/backend/api/<YOUR_API>/transform.conf.json and append "./graphql-auto-transformer" to transformers field.

    "transformers": [
      "graphql-auto-transformer"
    ]

3. Use @auto directive

Append @auto to target fields.

type Post @model {
  id: ID!
  text: String
  createdAt: AWSDateTime! @auto
}

generates:

input CreatePostInput {
  id: ID
  text: String
}

input UpdatePostInput {
  id: ID!
  text: String
}

If you want to allow optional creation/update like id field, use creatable and updatable parameter.

type Post @model {
  id: ID!
  text: String
  createdAt: AWSDateTime! @auto(creatable: true)
}

generates:

input CreatePostInput {
  id: ID
  text: String
  createdAt: AWSDateTime
}

input UpdatePostInput {
  id: ID!
  text: String
}

License

Fork of graphql-versioned-transformer

Apache-2.0

Copyright 2017 - 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.

Copyright 2020 - 2020 Hiroshi Ioka. All Rights Reserved.

graphql-auto-transformer's People

Contributors

dependabot[bot] avatar hirochachacha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

graphql-auto-transformer's Issues

Errors on amplify push: CloudFormation cannot update a stack when a custom-named resource requires replacing

I tried using this package for the first time. After following the guide in Usage part I got the following errors:

    UPDATE_FAILED      FeedbackTable          AWS::DynamoDB::Table   Fri May 21 2021 11:19:38 GMT+0300 (GMT+03:00) CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename Feedback-qcgiorvlhrc2veihhxc75wm4py-dev and update the stack again.

    UPDATE_FAILED      CreateFeedbackResolver AWS::AppSync::Resolver Fri May 21 2021 11:19:38 GMT+0300 (GMT+03:00) Resource update cancelled

And similar errors for other APIs. Here is my schema:

    type Feedback @model @key(fields: ["id", "createdAt"]) {
        id: ID!
        createdAt: AWSDateTime! @auth
        score: Int!
        content: String
    }

After removing the packages, transformers array, and @auto directive and doing amplify push again, I'm still getting these errors.

It might be a totally random error on the server side, but I'm guessing installing this package caused it, because I didn't do anything else.

I'm using amplify-cli version 4.50.2

Typing issues on DataStore.save

Consider this example:

// schema.graphql
type UserInfo @model @auth(rules: [{allow: owner}]) {
  id: ID!
  name: string!
  createdAt: AWSDateTime! @auto
}

// another file
await DataStore.save(new UserInfo({...name: "Bob"}));

It results in the following typing issue: "TS2345: ...Property 'createdAt' is missing in type..."
I am able to fix this by changing the createdAt field to readonly createdAt?: string; in the generated models file, but I am escalating this here in case it can be fixed from within this package.

Thanks!

Cannot find module 'graphql-auto-transformer'

After following the installation instructions (step1) with npm install and (step 2) adding graphql-auto-transformer to the transform.conf.json file of my Amplify API:

{
    "Version": 5,
    "transformers": [
        "graphql-auto-transformer"
    ]
}

When attempting to use @auto directive in my model

type Post @model {
[...]
    createdAt: AWSDateTime! @auto
}

I get the following error

$ amplify push -y
- Fetching updates to backend environment: dev from the cloud.
√ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name                       | Operation | Provider plugin   |
| -------- | ----------------------------------- | --------- | ----------------- |
| Api      | pocapi                                  | Update    | awscloudformation |
| Auth     | userPoolGroups                      | No Change | awscloudformation |
| Auth     | pocapixxxxxxxxx                    | No Change | awscloudformation |
| Hosting  | S3AndCloudFront                     | No Change | awscloudformation |
× An error occurred when pushing the resources to the cloud

Unknown directive "auto".
An error occurred during the push operation: Unknown directive "auto".

When removing the @auto directory from my schema and running amplify push -y I get the error that graphql-auto-transformer module could not be found, while the module is present in .\node_modules\graphql-auto-transformer (after being installed through npm as mentioned in the readme.MD).

$ amplify push -y
- Fetching updates to backend environment: dev from the cloud.
√ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name                       | Operation | Provider plugin   |
| -------- | ----------------------------------- | --------- | ----------------- |
| Api      | pocapi                                  | Update    | awscloudformation |
| Auth     | userPoolGroups                      | No Change | awscloudformation |
| Auth     | pocapixxxxxxxxx                    | No Change | awscloudformation |
| Hosting  | S3AndCloudFront                     | No Change | awscloudformation |
Unable to import custom transformer module(graphql-auto-transformer).
You may fix this error by editing transformers at ~\poc\amplify\backend\api\pocapi\transform.conf.json
× An error occurred when pushing the resources to the cloud

Cannot find module 'graphql-auto-transformer'
Require stack:
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\transform-graphql-schema.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\push-resources.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\amplify-service-migrate.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\initializer.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\index.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\lib\commands\push.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\lib\index.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\bin\amplify
An error occured during the push operation: Cannot find module 'graphql-auto-transformer'
Require stack:
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\transform-graphql-schema.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\push-resources.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\amplify-service-migrate.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\lib\initializer.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\node_modules\amplify-provider-awscloudformation\index.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\lib\commands\push.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\lib\index.js
- C:\Users\PC\AppData\Roaming\npm\node_modules\@aws-amplify\cli\bin\amplify

This was only resolved through installing the package globally: npm install graphql-auto-transformer -g.

Note: I am not certain as if this issue is related to this package, or to the Amplify CLI perhaps containing a bug in combination with Windows, with finding the correct relative path to ./node_nodules/graphql-auto-transformer

Auto generate 'owner' value for update operations if primary key contain `owner` field

Hi, I'm really appreciate your work on this, without this plugin, I would have had to quit using Amplify...!!

I found an issue with a usecase that the primary key contain owner field.

For instance:

type Review
  @model
  @key(fields: ["owner", "serviceId"])
  @auth(rules: [ { allow: owner } ]) 
{
  id: ID!
  serviceId: ID!
  owner: String! @auto
  service: Service @connection(fields: ["serviceId"])
  rating: Int
  title: String
}

Now, updateReview wouldn't allow user to specify the owner field, which is fine, but, because the owner is the partition key of the Review table, DynamoDB requires the the owner field to update the item. So to make this work, we have to generate the value of 'owner'.

sure I can use @auto(updatable: true), so I can manually input the owner field, but it really should be generated automatically in this case.

I saw you have already auto generated the createdAt field, why not for the owner as well?

so the logic would be

  1. set ownerField default value to "owner".
  2. check if @auth directive contains ownerField argument, if it is, set ownerField to that value.
  3. check if fields argument of @key contains the value of ownerField.
  4. if step 3 is true, set $context.args.input.${ownerField} to the incoming request's identity.

Using createdAt with @key doesn't work for updates

When the @key directive is added and uses createdAt (or I assume updatedAt) as one of the fields it results in errors.

type Example
  @model
  @auth(rules: [{ allow: owner, operations: [create, read, update, delete] }])
  @key(name: "byOwner", fields: ["owner", "createdAt"], queryField: "examplesByOwner") {
  id: ID!
  owner: ID!
  createdAt: AWSDateTime! @auto
}

An attempt to do an update

When updating any part of the composite sort key for @key 'byOwner', you must provide all fields for the key. Missing key: 'createdAt'.

I figure it could be resolved with a custom resolver? But would I then have to handle setting the composite keys and would I lose the auth directive behaviour?

Thanks

Recommended approach for nullable 'lastUpdated'

Consider this schema:

type Page @model {
    id: ID!
    title: String!
    paragraphs: [String!]!
    lastUpdated: AWSDateTime! @auto
    createdAt: AWSDateTime! @auto
}

Currently lastUpdated is only set after update
commands (not on create) so queries for things
that may or may not have been updated cause
errors. In this case is the recommended approach
to make it nullable? Seemingly the transformer
prevents that from happening.

The workaround seems to be to run an update
command immediately after creating which is
non-ideal.

Otherwise this lib has been very simple to use :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.