Skip to content
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

Amplify Codegen without @model directive does not create Java/Kotlin code for Queries #2807

Closed
1 task done
olliestringfield-accedo opened this issue May 7, 2024 · 7 comments
Labels
api question General question

Comments

@olliestringfield-accedo
Copy link

Before opening, please confirm:

Language and Async Model

Kotlin - Coroutines

Amplify Categories

Authentication, GraphQL API

Gradle script dependencies

// Put output below this line
    implementation("com.amplifyframework:core-kotlin:2.16.0")
    implementation("com.amplifyframework:aws-auth-cognito:2.16.0")
    implementation("com.amplifyframework:aws-api:2.16.0")

Environment information

# Put output below this line
------------------------------------------------------------
Gradle 8.4
------------------------------------------------------------

Build time:   2023-10-04 20:52:13 UTC
Revision:     e9251e572c9bd1d01e503a0dfdf43aedaeecdc3f

Kotlin:       1.9.10
Groovy:       3.0.17
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          17.0.9 (JetBrains s.r.o. 17.0.9+0-17.0.9b1087.7-11185874)
OS:           Mac OS X 14.4.1 aarch64

Please include any relevant guides or documentation you're referencing

https://docs.amplify.aws/gen1/android/build-a-backend/graphqlapi/client-code-generation/

Describe the bug

We are implementing the Android Amplify SDK into a Kotlin Android app with no Amplify instance.
Instead we are using a Cognito User Pool and AppSync.
When putting the schema.graphql from AppSync into the root folder and running the codegen command:

amplify codegen add
>>> Choose the type of app that you're building **android**
>>> Enter the file name pattern of graphql queries, mutations and subscriptions **app/src/main/graphql/**/*.graphql**
>>> Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions **Yes**
>>> Enter maximum statement depth [increase from default if your schema is deeply nested] 2
✔ Generated GraphQL operations successfully and saved at app/src/main/graphql/com/amazonaws/amplify/generated/graphql

Only .graphql files are generated i.e app/src/main/graphql/com/amazonaws/amplify/generated/graphql/queries.graphql
There is no generated Java or Kotlin code to use with Amplify SDK and use our queries defined in the schema file.
Note the schema is not using the @model directive since we are not using Dynamo DB

Reproduction steps (if applicable)

No response

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


amplifyconfiguration.json

No response

GraphQL Schema

// Put your schema below this line
schema {
  query: Query
  mutation: Mutation
}

type ModelProductConnection @aws_cognito_user_pools {
  items: [Product]!
  nextToken: String
}

type Mutation {
  createProduct(condition: ModelProductConditionInput, input: CreateProductInput!): Product @aws_cognito_user_pools
  deleteProduct(condition: ModelProductConditionInput, input: DeleteProductInput!): Product @aws_cognito_user_pools
  updateProduct(condition: ModelProductConditionInput, input: UpdateProductInput!): Product @aws_cognito_user_pools
}

type Product @aws_cognito_user_pools {
  createdAt: AWSDateTime!
  description: String
  id: ID!
  image: String
  name: String!
  owner: String
  price: Float
  updatedAt: AWSDateTime!
  userId: String
  userName: String
}

type Query {
  getProduct(id: ID!): Product @aws_cognito_user_pools
  listProducts(filter: ModelProductFilterInput, limit: Int, nextToken: String): ModelProductConnection @aws_cognito_user_pools
}

enum ModelAttributeTypes {
  _null
  binary
  binarySet
  bool
  list
  map
  number
  numberSet
  string
  stringSet
}

enum ModelSortDirection {
  ASC
  DESC
}

input CreateProductInput {
  description: String
  id: ID
  image: String
  name: String!
  price: Float
  userId: String
  userName: String
}

input DeleteProductInput {
  id: ID!
}

input ModelBooleanInput {
  attributeExists: Boolean
  attributeType: ModelAttributeTypes
  eq: Boolean
  ne: Boolean
}

input ModelFloatInput {
  attributeExists: Boolean
  attributeType: ModelAttributeTypes
  between: [Float]
  eq: Float
  ge: Float
  gt: Float
  le: Float
  lt: Float
  ne: Float
}

input ModelIDInput {
  attributeExists: Boolean
  attributeType: ModelAttributeTypes
  beginsWith: ID
  between: [ID]
  contains: ID
  eq: ID
  ge: ID
  gt: ID
  le: ID
  lt: ID
  ne: ID
  notContains: ID
  size: ModelSizeInput
}

input ModelIntInput {
  attributeExists: Boolean
  attributeType: ModelAttributeTypes
  between: [Int]
  eq: Int
  ge: Int
  gt: Int
  le: Int
  lt: Int
  ne: Int
}

input ModelProductConditionInput {
  and: [ModelProductConditionInput]
  description: ModelStringInput
  image: ModelStringInput
  name: ModelStringInput
  not: ModelProductConditionInput
  or: [ModelProductConditionInput]
  price: ModelFloatInput
  userId: ModelStringInput
  userName: ModelStringInput
}

input ModelProductFilterInput {
  and: [ModelProductFilterInput]
  description: ModelStringInput
  id: ModelIDInput
  image: ModelStringInput
  name: ModelStringInput
  not: ModelProductFilterInput
  or: [ModelProductFilterInput]
  price: ModelFloatInput
  userId: ModelStringInput
  userName: ModelStringInput
}

input ModelSizeInput {
  between: [Int]
  eq: Int
  ge: Int
  gt: Int
  le: Int
  lt: Int
  ne: Int
}

input ModelStringInput {
  attributeExists: Boolean
  attributeType: ModelAttributeTypes
  beginsWith: String
  between: [String]
  contains: String
  eq: String
  ge: String
  gt: String
  le: String
  lt: String
  ne: String
  notContains: String
  size: ModelSizeInput
}

input UpdateProductInput {
  description: String
  id: ID!
  image: String
  name: String
  price: Float
  userId: String
  userName: String
}

Additional information and screenshots

Output queries.graphql

# this is an auto generated file. This will be overwritten

query GetProduct($id: ID!) {
  getProduct(id: $id) {
    createdAt
    description
    id
    image
    name
    owner
    price
    updatedAt
    userId
    userName
    __typename
  }
}

query ListProducts(
  $filter: ModelProductFilterInput
  $limit: Int
  $nextToken: String
) {
  listProducts(filter: $filter, limit: $limit, nextToken: $nextToken) {
    items {
      createdAt
      description
      id
      image
      name
      owner
      price
      updatedAt
      userId
      userName
      __typename
    }
    nextToken
    __typename
  }
}

@github-actions github-actions bot added the pending-triage Issue is pending triage label May 7, 2024
@tylerjroach
Copy link
Contributor

tylerjroach commented May 7, 2024

@olliestringfield-accedo This is expected. The Amplify Android client library is built to use Amplify models and it does not use the .graphql files generated. To use non amplify models, the Android AppSync SDK is still available (https://github.com/awslabs/aws-mobile-appsync-sdk-android)

@tylerjroach tylerjroach added question General question and removed pending-triage Issue is pending triage labels May 7, 2024
@joon-won joon-won added the auth Related to the Auth category/plugins label May 7, 2024
@yuhengshs yuhengshs added api and removed auth Related to the Auth category/plugins labels May 7, 2024
@olliestringfield-accedo
Copy link
Author

@tylerjroach Thanks for the recommendation.
This is odd because the iOS Amplify SDK allows querying for non-Amplify models and the codegen generates queries to use with the SDK without the @model directive.
Is this a known feature discrepancy between Android and iOS that will not be aligned?

@tylerjroach
Copy link
Contributor

@olliestringfield-accedo Can you show me a code example for Swift of what you are doing? I want to make sure I'm not misunderstanding anything.

One difference between Swift and Android is that the AWS AppSync SDK for iOS has entered maintenance mode, and the Amplify API category was updated to support a few of the AppSync SDK use cases.

@olliestringfield-accedo
Copy link
Author

So given the attached schema.graphql file.
When I run amplify add codegen, the generated queries are output to the API.swift file.

We can see the generated GetProductQuery class

public final class GetProductQuery: GraphQLQuery {
  public static let operationString =
    "query GetProduct($id: ID!) {\n  getProduct(id: $id) {\n    __typename\n    createdAt\n    description\n    id\n    image\n    name\n    owner\n    price\n    updatedAt\n    userId\n    userName\n  }\n}"
    
  public var id: GraphQLID

  public init(id: GraphQLID) {
    self.id = id
  }
  
  public var variables: GraphQLMap? {
    return ["id": id]
  }
  ...
}

Then we can use this to create a GraphQLRequest<R: Decodable> object to pass through to the Amplify API category as shown below

    func getProduct(id: String) async throws -> GetProductQuery.Data {
        do {
            let query = GetProductQuery(id: id)
            let operation = GetProductQuery.operationString
            let responseType = GetProductQuery.Data.self
            let request = GraphQLRequest(document: operation, variables: query.variables, responseType: responseType)
            let result = try await Amplify.API.query(request: request)
            switch result {
            case .success(let data):
                return data
            case .failure(let error):
                debugPrint(error.errorDescription)
                throw error
            }
        } catch let error {
            debugPrint("Failed to get product id=\(id)")
            throw error
        }
    }

I've added the full generated API.swift for reference
API.swift.zip

@tylerjroach
Copy link
Contributor

Hi @olliestringfield-accedo, the use case you are using on the Swift side is the one found in the upgrade guide to use the AppSync SDK API.swift file that was previously used with AppSync iOS SDK. When the SDK was placed into maintenance mode, support was added on Amplify Swift side to allow this file to be used.

Since the Android AppSync SDK is still supported, this migration path has not been enabled. The expectation is still to use the AppSync Android SDK.

@olliestringfield-accedo
Copy link
Author

Thanks for the clarification @tylerjroach. I'll use the Android AppSync SDK for our use case

Copy link
Contributor

This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api question General question
Projects
None yet
Development

No branches or pull requests

4 participants