Giter VIP home page Giter VIP logo

amplify-codegen's Introduction

AWS Amplify

Discord Chat build:started

Reporting Bugs/Feature Requests

Open Bugs Feature Requests Enhancements Closed Issues

Amplify Codegen

Amplify Codegen is a JavaScript toolkit library for frontend and mobile developers building amplify applications. Packages are mainly used for frontend code generation including:

Package Description
amplify-codegen Amplify plugin for code generation
appsync-modelgen-plugin Model generator for Amplify Datastore
graphql-docs-generator Generates statements from GraphQL schema
graphql-types-generator Generates type annotations from GraphQL schema and statements

Developing

This section should get you running with Amplify Codegen. You will need to set nodejs to a version less than v16 on your system. Developing locally also requires yarn.

Start by Forking the main branch of amplify-codegen.

$ git clone [email protected]:[username]/amplify-codegen.git
$ cd amplify-codegen

$ yarn setup-dev

To generate model files in an Amplify app using the local version of codegen, run amplify-dev codegen models in an Amplify app.

Before pushing code or sending a pull request, do the following:

  • At the command line, run npm run lint at the top-level directory. This invokes lerna to check for lint errors in all of our packages.
  • You can use eslint to fix some of the lint errors. To use it, go to the package that has errors and run lint-fix
  • If there are any remaining lint errors, resolve them manually. Linting your code is a best practice that ensures good code quality so it's important that you don't skip this step.

Troubleshooting

Errors sometimes occur when a different version of amplify-cli-core is installed, typically during the time the CLI is updated. To resolve the error, execute the following command from the top-level directory:

rm -rf yarn.lock && yarn clean && yarn setup-dev

Contributing

See the contribution guideline. https://github.com/aws-amplify/amplify-codegen/blob/main/CONTRIBUTING.md

amplify-codegen's People

Contributors

aaronzylee avatar akshbhu avatar alharris-at avatar ammarkarachi avatar amplify-data-ci avatar attilah avatar dependabot[bot] avatar diegocstn avatar dpilch avatar edwardfoyle avatar equartey avatar evcodes avatar frimfram avatar hirochachacha avatar huisf avatar jordan-nelson avatar kaustavghosh06 avatar lawmicha avatar lazpavel avatar marcvberg avatar mikepschneider avatar nikhname avatar palpatim avatar phani-srikar avatar seang96 avatar sundersc avatar swaysway avatar tylerjroach avatar unleashedmind avatar yuth 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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

amplify-codegen's Issues

Support generation of batch actions by Codegen

Is your feature request related to a problem? Please describe.
When using the CLI I often find myself having to create, update or delete in bulk. I used to make a list of mutations and await them in a Promise.all which is far from ideal. I made an issue about this and @manueliglesias recommended to make a feature request (along with providing some helpful DIY instructions).

Describe the solution you'd like
It would be great if Codegen could generate queries and resolvers for batch mutations. You could maybe make this optional by providing a flag.

Describe alternatives you've considered
The only alternative is to write all the resolvers manually (which is not in the spirit of having your project 'amplified'), or to do it the suboptimal Promise.all way.

Additional context
This feature request might tie nicely into adding Codegen for the input types, which is also an issue that I stumbled upon in multiple projects.

This issue is similar to this.

Allow disabling complex object support in `amplify codegen`

Is your feature request related to a problem? Please describe.

We use amplify to generate a GraphQL client on iOS. Our project has a GraphQL input defined as:

input S3ObjectInput {
	bucket: String!
	key: String!
	metadata: String!
	name: String!
	region: String!
	localUri: String
	etag: String
	mimeType: String
}

We based this off some official documentation. Note that localUri and mimeType are nullable.

Recently, after an upgrade to some part of our toolchain, amplify codegen began producing code that didn't compile. We traced the problem to this generated code:

extension S3ObjectInput: AWSS3ObjectProtocol, AWSS3InputObjectProtocol {
  public func getLocalSourceFileURL() -> URL? {
      return URL(string: self.localUri)
  }

  public func getMimeType() -> String {
      return self.mimeType
  }

  public func getBucketName() -> String {
      return self.bucket
  }

  public func getKeyName() -> String {
      return self.key
  }

  public func getRegion() -> String {
      return self.region
  }

}

There are two errors here, but the obvious one is getMimeType() returns a non-nullable String (by contract of the protocol), but mimeType is nullable, as per the GraphQL schema. After doing some digging, we found this comment that explains why this happened, in AWSObjectProtocol.swift:

/// In order for the AWSAppSyncClient to automatically upload a GraphQL type as an S3Object, the type must contain
/// all of these field names, of type `String!`, in addition to the fields specified in `AWSS3ObjectFields`
public struct AWSS3InputObjectFields {
    public static let localUri = "localUri"
    public static let mimeType = "mimeType"
}

So localUri and mimeType are required to be non-nullable in the schema.

But, stepping back a little, I must note we do not use this auto-generated extension and did not even know about it until this incident. In our view, the root problem is amplify opts us into a code generation feature we do not need and which is incompatible with our schema.

Describe the solution you'd like
Add a new CLI option to amplify codegen, with signature --complexObjectSupport <yes|no|auto>. This option mirrors the option in amplify-graphql-types-generator, a tool invoked within amplify codegen, that allows the user to control whether S3 wrapper objects are generated, including the problematic extension.

Currently, amplify codegen always passes the value auto for this option, which turns on the generation of the extension if any of the GraphQL input objects have S3-looking fields in them, which is the case for our S3ObjectInput.

With this feature, we could invoke amplify with amplify codegen --complexObjectSupport no to opt out of generating the extension.

Describe alternatives you've considered

  • Change our schema to avoid triggering autogeneration of the extension
    This is not desirable because it would break much of our code.

  • Make mimeType and localUri non-nullable in the schema
    We have considered this option, but have so far turned it down because it doesn't reflect the actual nullability of these properties. We currently consider this option a workaround rather than a solution, because again, we don't use the code that requires non-nullability on these fields.

  • Don't use amplify--instead use the lower level tools directly to have access to more options
    This would require a good deal of effort to get tooling back to parity, and we'd lose the benefits of amplify codegen, such as schema downloading.

`listXXX` query lacks the connection `items` field

Describe the bug
A clear and concise description of what the bug is.

Amplify CLI Version
4.37.1

To Reproduce

type UserMeta @model @key(fields: ["owner"]) @auth(rules: [
    { allow: public, operations: [read] },
    { allow: owner },
    {
        allow: groups,
        groups: ["Admins"],
        operations: [read, update, delete]
    }
]) {
    familyName: String
    givenName: String
    careers: [Career] @connection(keyName: "byOwner", fields: ["owner"])
    owner: String!
}

type Career @model @key(name: "byOwner", fields: ["owner"]) @auth(rules: [
    { allow: public, operations: [read] },
    { allow: owner },
    {
        allow: groups,
        groups: ["Admins"],
        operations: [read, update, delete]
    }
]) {
    id: ID!
    company: String
    companyUrl: AWSURL
    industry: String
    owner: String!
}

with the above schema, this query was generated:

export const listUserMetas = /* GraphQL */ `
  query ListUserMetas(
    $owner: String
    $filter: ModelUserMetaFilterInput
    $limit: Int
    $nextToken: String
    $sortDirection: ModelSortDirection
  ) {
    listUserMetas(
      owner: $owner
      filter: $filter
      limit: $limit
      nextToken: $nextToken
      sortDirection: $sortDirection
    ) {
      items {
        familyName
        givenName
        owner
        createdAt
        updatedAt
        careers {
          nextToken
        }
      }
      nextToken
    }
  }
`;

as you can see the careers has only a nextToken field, where it should be:

export const listUserMetas = /* GraphQL */ `
  query ListUserMetas(
    $owner: String
    $filter: ModelUserMetaFilterInput
    $limit: Int
    $nextToken: String
    $sortDirection: ModelSortDirection
  ) {
    listUserMetas(
      owner: $owner
      filter: $filter
      limit: $limit
      nextToken: $nextToken
      sortDirection: $sortDirection
    ) {
      items {
        familyName
        givenName
        owner
        createdAt
        updatedAt
        careers {
            items {
              id
              company
              companyUrl
              owner
              createdAt
              updatedAt
            }
            nextToken
        }
      }
      nextToken
    }
  }
`;

Codegen Model Types

Is your feature request related to a problem? Please describe.

It's frustrating that codegen doesn't generate typescript model types. If I define a @model in my schema consisting of:

type Room
  @model 
{
  id: ID!
  name: String!
  primaryColor: String
  iconName: String
}

Codegen will generate literally thousands of lines of code. For example:

export type GetRoomQuery = {
  getRoom:  {
    __typename: "Room",
    id: string,
    name: string,
    primaryColor: string | null,
    iconName: string | null,
};

export type ListRoomsQuery = {
  listRooms:  {
    __typename: "ModelRoomConnection",
    items:  Array< {
      __typename: "Room",
      id: string,
      name: string,
      primaryColor: string | null,
      iconName: string | null,
};

export type CreateRoomInput... etc etc

But it never generates a simple Room model interface. We have to create and maintain this manually. Why? Is there a reason for this?

Describe the solution you'd like

For this specific example, somewhere in the thousands of lines of code in API.ts I would expect to find:

export interface Room {
  id: string;
  name: string;
  primaryColor?: string;
  iconName?: string;
}

Describe alternatives you've considered

Manual creation and maintenance of model types.

Thanks for your time,
Chris

Headless support for amplify add codegen

Is your feature request related to a problem? Please describe.
I am trying to add multi env support for externally linked APIs but this is currently not possible.

Describe the solution you'd like
Headless support for amplify add codegen that lets you pass the codegen config as an argument.

CONFIG="{\
\"generateCode\":true,\
\"codeLanguage\":\"typescript\",\
\"fileNamePattern\":\"src/graphql/**/*.ts\",\
\"generatedFileName\":\"src/API.ts\",\
\"generateDocs\":true\
}"

amplify add codegen --apiId xxxxxxxxxxxxxxxxx --config $CONFIG

Describe alternatives you've considered
Add multi env support for externally linked APIs that allows you to link each environment to a specific AppSync ID.

Additional context

Ability to extend or shape the graphql queries generated by codegen without writing completely new queries/mutations

Is your feature request related to a problem? Please describe.
Codgen is great for getting started, but there's often cases where we need to customize the queries and create new custom queries. Cases where certain fields would be too expensive to resolve, or more nesting depth is required, or including optional variables in nested fields (codegen I believe defaults to only retrieving required variables for nested objects). If there are field resolvers that are slow, or highly relational data, then the default queries codegen generates could degrade performance unnecessarily. One can argue Apollo has a great caching layer so what's wrong with asking for as much info as possible in a query since it's a one time hit but I think you can still run into cases like mutations where the query that is run after a mutation could be more than what you want.

As background, this came out from this discussion here: aws-amplify/amplify-cli#745

Describe the solution you'd like
The current solution is to write your own custom queries, disregarding what codgen produces from the GraphQL schema. I think a better solution at minimum is for the codgen code to use fragments when generating queries (see https://www.apollographql.com/docs/react/advanced/fragments.html). And maybe then during runtime, in different parts of the code if a query needs to be customized, we can just pass in a different fragment instead completely writing the new query.

Another possible solution is some kind of dynamic query generator that works off of a base query codegen generates but then you pass it fields to include or omit (kind of like lodash's pick or omit functionality (https://lodash.com/docs/4.17.11#omit)) and it gives you the customized query back as requested.

Describe alternatives you've considered
The current solution is to write your own custom queries and include them in the dir that codgen scans to generate types and APIs. This works fine but these custom queries have to then be manually updated when the GraphQL schema changes. Also you can run into cases where codgen generates multiple variations of types that all refer to the same object but the compiler or transpiler doesn't recognize them as so and so then you have to re-cast to unknown and then back to the type you want.

Additional context
I am new to graphql and still learning. Above are my suggestions based on what I know and ran into developing a graphql client but the community may have an already established way to to do this. There might be things to learn from the sql world as well since this is very similar, codegen is essentially generating "select *" sql scripts for us when all I need is something similar to Rails' Active Record "select" method to pass in the variables I need (https://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields).

Customizable $input per GraphQL operation on new API/Datastore plugins

iOS, Android, JS, API plugin, DataStore plugin, code-gen, feature-request

Is your feature request related to a problem? Please describe.
With previous API (iOS-sdk) you could go custom with GraphQL mutation/query input attributes schema definition, and front end code would get generated accordingly.

i.e. Your GraphQL input attributes could be a subgroup of model's available attributes.

Now with new plugins it is not possible anymore as frontend modules (at least iOS) have 'hardcoded' (on delete) or all fields included (on update or create). So GraphQL query input schema would always need to include all model attributes, plus doesn't allows to go custom because of 'hardcoded' on deletion.

Describe the solution you'd like
My proposal is to do an optional inclusion on model schema definition at front-end code level, where you (and codegen) can define which concrete fields would be included as $input on each GraphQL query type.

i.e. (iOS):
https://github.com/aws-amplify/amplify-ios/blob/f4b0423ee3a4af09af85c8e32d78a180003db6af/Amplify/Categories/DataStore/Model/ModelSchema.swift#L62-L67

public struct ModelSchema {


    public let name: String
    public let pluralName: String?
    public let fields: ModelFields
    public let attributes: [ModelAttribute]

Add:

    public let operationInputFields: [String:ModelFields]

Where String is GraphQL operation's name, and ModelFields includes the definition for that operation input.

So every time an operation is executed only those fields are added, by implementing a check+cribe here on the corresponding operation type file: https://github.com/aws-amplify/amplify-ios/tree/389cb6e5d708553287265314d294af0b15af6c96/AmplifyPlugins/Core/AWSPluginsCore/Model/GraphQLDocument

iOS/codegen: "generated" models folder and definitions go out of sync after updating schema.graphql

Describe the bug
Changing a model's name or removing a model from schema.graphql is not reflected in amplify/generated/models/.

Amplify CLI Version
4.35.0

To Reproduce

  • Follow iOS getting started guide to setup a new iOS project
  • run amplify codegen models
  • run amplify-app
  • rename or delete one of the entity in the schema.graphql schema
  • run amplify codegen models and amplify-app
  • observe that the generated models don't reflect the current schema status, removed/renamed model is still present

Expected behavior
The renamed/removed model gets also renamed/removed from both the amplify/generated/models folder Xcode project

Screenshots
N/A

Desktop (please complete the following information):

  • Mac
  • v12.12.0

Additional context
N/A

[request?] `amplify codegen` does not reflect updated schema from local copy

Is your feature request related to a problem? Please describe.

Problem 1: codegen doesnt codegen from local copy

when i update my local schema in /amplify/backend/api/MYAPI/schema.graphql and run amplify codegen, the generated code in src/graphql doesn't update at all.

we are not sure if this is a bug or working as intended. but it's clear that in order to update the generated code i have to amplify push.

Problem 2: CLI gives the impression that codegen is done before push

I have to amplify push before i can codegen the new model:

image

this causes a LONG wait time and completely breaks my flow, for information i already have on my machine.

I ran amplify push 40 minutes 1 hour ago and am still waiting for my updated graphql schema so i can continue working. this is not a sustainable workflow when i'm just changing one little field on my schema.

Repro steps

  1. amplify add api
  2. amplify codegen
  3. change one field in the graphql schema
  4. amplify codegen again
  5. observe that nothing has changed in src/graphql

Describe the solution you'd like

i understand you do this in order to always codegen the right thing. but perhaps offer to codegen based off my local model first, if i accept the risks of mismatch between the model i have on my machine and the model i have in the cloud.

Describe alternatives you've considered

do nothing

Can I use the generated GraphQL queries in my Lambda functions?

I want to keep everything DRY as I can so would like my Lambda functions to be able to reuse my GraphQL queries. Trouble is I'm not sure how to do that!

I think that my functions when I add them are just uploaded separately in isolation of the rest of my code when I do a amplify push, by that I mean if I change my schema and regenerate everything I don't expect that to get pushed up to my functions but I could be wrong.

I'm currently using a Lambda Layer for shared code so I thought I would be the right place to put my queries but how to get them in there? Copy them to the \amplify\backend\function\myAmazingLayer\opt\ folder of my Layer? Could hook up a build step for that I guess?

It could be I've got work to do and I'm just missing the right imports or even to know which imports to use and their path. Or none of this is automagically available and I have to manually include it in my Layer somehow?

Again gaps in knowledge are telling here as I can't seem to find any information on how to do this. There is stuff out there on how to talk to DynamoDB direct (https://dev.to/dabit3/lambda-function-graphql-resolvers-11cd) in a Lambda but I'd rather go through my GraphQL API I think as I've been bitten before when I've pushed strings of data in to Dynamo directly for it to then blow up one of my AWS GraphQL types when I try to pull it back out via the GraphQL API. As a result I'd like everything to go through the "front door" of my GraphQL API. This doc (https://docs.amplify.aws/lib/graphqlapi/query-data/q/platform/js) covers how to talk to GraphQL in my front-end client code but I'd like to use this in my Lambda too...ideas?

Please can someone enlighten me.

Wrong variable name is generated by the code generator.

Describe the bug
Wrong code is generated by the generator.

I have a model like this:

type CTA
  @model
  @key(name: "ByOwner", fields: ["owner"], queryField: "ctasByOwner") {
  id: ID!
  owner: String!
  createdAt: String
  updatedAt: String
}

Which only consists of uppercase letters, a variable like this will still be created:

export const deleteCta = `mutation DeleteCta($input: DeleteCTAInput!) {
  deleteCTA(input: $input) {
    id
    owner
    created
    updated
  }
}
`;

we can already see that something does not fit.
const deleteCta and the object returned by GraphQL is then deleteCTA. (Pay attention to upper and lower case).

So it is no longer possible to dynamically build something like this:

export const mutation = async (resource, data) => {
  try {
    const answer = await API.graphql(
      graphqlOperation(mutations[resource], {
        input: data
      })
    );
    return answer.data[**resource**];
  } catch (e) {
    return { error: e };
  }
};

Because the resource is not found then.

Expected behavior
if the name of the Model is Uppercase than the variable name should be delteXXX instead of deleteXxx

Amplify

  • Version 3.2.0

Take codegen depth as an input to @model

Is your feature request related to a problem? Please describe.
There are lots of cases where a model is self-referential and the entities have a bi-directional relationship. Eg. posts with comments where each comment has a reference back to the post. When queries and mutations are generated for these models, the return objects can be unnecessarily nested.

Describe the solution you'd like
Be able to define optional codegen depth on a per-operation basis that will override the global default. The following is an example @model SDL where this behavior would be specified

directive @model(
  queries: ModelQueryMap,
  mutations: ModelMutationMap,
  subscriptions: ModelSubscriptionMap
) on OBJECT
input ModelMutationMap { create: String, update: String, delete: String, createDepth: Int, updateDepth: Int, deleteDepth: Int }
input ModelQueryMap { get: String, list: String, getDepth: Int, listDepth: Int }
input ModelSubscriptionMap {
  onCreate: [String]
  onUpdate: [String]
  onDelete: [String]
  level: ModelSubscriptionLevel
}
enum ModelSubscriptionLevel { off public on }

And then it could be used in the following way:

type Comment @model(queries: {getDepth: 4, listDepth: 5}) {
  id: ID
}

to generate get queries with a depth of 4 and list queries with a depth of 5.

Describe alternatives you've considered
Specify a reasonable codegen depth for the current project and create custom queries / mutations for any operations where this default doesn't work. This creates unnecessary work making sure these custom queries stay in sync with the rest of the project.

Another option that seems like it may solve most use cases is to ignore the "items" field in the depth count when generating queries for one-to-many relationships. Based on discussion in aws-amplify/amplify-cli#1013 this would generate code that is closer to developer expectations. However I would not say this is the same feature because there still may be cases where you have some models that are deeply nested and others that aren't.

Additional context
There have been some other related requests made aws-amplify/amplify-cli#1013, but they all seem to target trying to come up with more sensible defaults whereas this gives the developer total control to adjust depth for each operation. Another related issue is aws-amplify/amplify-cli#2977.

"amplify codegen models" does not recognize "external" AppSync api

Note: If your issue/bug is regarding the AWS Amplify Console service, please log it in the
Amplify Console GitHub Issue Tracker

Describe the bug
"amplify codegen models" does not recognize an AppSync api which was added using "amplify add codegen --apiId ..." The command outputs: "No AppSync API configured. Please add an API"

Amplify CLI Version
You can use amplify -v to check the amplify cli version on your system
4.13.4

To Reproduce

  1. Setup AWS AppSync api (via CFN or AWS Management Console) including a sample schema
  2. Generate project via create-react-app and amplify init
  3. Add api to project via "amplify add codegen --apiId ..."
  4. Run "amplify codegen" -> works as expected
  5. Run "amplify codegen models" -> console output: No AppSync API configured. Please add an API
  6. "amplify add api"
    ? Please select from one of the below mentioned services: GraphQL
    You already have an AppSync API in your project. Use the "amplify update api" command to update your existing AppSync API.
  7. amplify update api
    ? Please select from one of the below mentioned services: GraphQL
    The selected resource is not managed using AWS Cloudformation. Please use the AWS AppSync Console to make updates to your API

Expected behavior
Either the model generation (required for Amplify DataStore) is supported or a clear error message states that the model generation only works for APIs added using "amplify add api".

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: Ubuntu
  • Node Version. v12.14.1

Additional context
Add any other context about the problem here.

How do I generate API from my .graphql files without generating entire api?

** Which Category is your question related to? **
amplify codegen for iOS

** What AWS Services are you utilizing? **
Appsync

** Provide additional details e.g. code snippets **
I don't want api for the entire schema polluting my namespace. I want API just for the .graphql file that I generate. How do I do this?

I was able to get this to work by moving the schema out of my ../graphql directory, putting my .graphql files in the directory, and then using:

amplify codegen --max-depth graphql/*.graphql

It generates the API.swift (which works!), but then errors out with:

uncaughtException: GraphQL schema file should contain a valid GraphQL introspection query result date=Fri Aug 23 2019 12:30:41 GMT+0200 (Central European Summer Time), pid=96247, uid=501, gid=20, cwd=/Users/jason/Documents/projects/tensil/bettercam-ios/Bettercam/Server/GraphQLAPI, execPath=/usr/local/bin/node, version=v10.16.3, argv=[/usr/local/bin/node, /usr/local/bin/amplify, codegen, --max-depth, graphql/GroupsTableViewControllerViewModel.graphql], rss=307851264, heapTotal=239886336, heapUsed=204516848, external=50348145, loadavg=[1.81005859375, 1.89892578125, 1.77294921875], uptime=676048, trace=[column=11, file=/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-graphql-docs-generator/lib/generator/src/generator/generate.ts, function=Object.generate [as default], line=20, method=generate [as default], native=false, column=57, file=/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-graphql-docs-generator/lib/src/index.ts, function=generate, line=40, method=null, native=false, column=11, file=/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-codegen/src/commands/statements.js, function=projects.forEach, line=32, method=forEach, native=false, column=7, file=internal/process/next_tick.js, function=process._tickCallback, line=68, method=_tickCallback, native=false], stack=[Error: GraphQL schema file should contain a valid GraphQL introspection query result, at Object.generate [as default] (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-graphql-docs-generator/lib/generator/src/generator/generate.ts:20:11), at generate (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-graphql-docs-generator/lib/src/index.ts:40:57), at projects.forEach (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-codegen/src/commands/statements.js:32:11), at process._tickCallback (internal/process/next_tick.js:68:7)]

Amplify Codegen does not generate output in a consistent/deterministic order

First of all, I'm surprised I couldn't find an existing bug, so if I've missed it, apologies. But as I couldn't find one I'm creating this ticket as as surely I'm not the only one this drives nuts over time...

Describe the bug
Running amplify push and regenerating GraphQL code bindings, or simply running amplify codegen on a GraphQL schema that hasn't changed results in unnecessary changes to files such as graphql/schema.json simply due to reordering of the same output due to apparent non-deterministic ordering in the generated code.

Amplify CLI Version
4.35.0

To Reproduce
Run the commands listed above a few times and see unnecessary and noisy changes made to files such as graphql/schema.json.

Expected behavior
All code generated should be generated in a consistent deterministic, possibly sorted, order so that:

  1. It is clear that a change in the generated file is caused by a change to the GraphQL schema that has just been pushed up, rather than changes in generated files unrelated to the schema change.
    1. Currently I have to either spend a lot of time eyeballing the diffs to and reverting hunks if I'm absolutely sure something didn't change, or otherwise include it in file history just to be safe.
    2. This is especially true because updating the @aws-amplify/cli package can cause expected changes to the generated files that are required even if not caused directly by user changes to their GraphQL schema, and so running a codegen after updating the package version without any GraphQL schema changes should be able to show if the version has introduced changes or not; currently that's not clear, it could just be non-deterministic reordering.
  2. Git Commit history is not polluted with a ton of unnecessary changes making it hard to browse file history.

Screenshots
An example diff highlighting one such apparently unnecessary reordering:

amplify-codegen-reordering

Desktop (please complete the following information):

  • OS: macOS 11.0.1
  • Node Version: 15.2.0

Additional context
Git commit history is important to in order to understand when particular bugs may have been introduced and by what changes, and so unnecessary noise in codegen files is more important than it may seem.

[GraphQL Transformer] Do not generate cyclical relationships when --max-depth is higher than necessary

Is your feature request related to a problem? Please describe.
We've been using --max-depth=5 in our projects. This leads to massive generated GraphQL operations that are needlessly recursive/cyclical. Since the underlying data structure is not recursive, we do not need the generated operations to recurse.

Describe the solution you'd like
The GraphQL transformer should detect when it's about to create a cycle, and continue to the next field or model at that point. To support others who DO represent recursive/self-referential data structures, preserve the existing behavior by adding a --recursive / -R parameter to the CLI operations and to the underlying API configuration.

Describe alternatives you've considered
Manually determine the minimum depth needed to represent all relationships (which may still generate cycles in other parts of the schema).

Additional context
Love everything you're doing, please keep going!

Specify codegen target directory

Is your feature request related to a problem? Please describe.
A customer is experiencing that fixed codegen target deviates from the actual src directory of the project.

Describe the solution you'd like
Enable specifying desired target src directory when running amplify codegen models

Describe alternatives you've considered
N/A

Additional context
Customer issue on Android platform

Better Codegen: Pagination Support

Is your feature request related to a problem? Please describe.
Is there any chance codegen can be enhanced to allow for pagination out of the box? It'd be great to not have to write my own queries.ts with this ability.

Describe the solution you'd like
Take a model like this:

type User @model {
  id: ID!
  todos: [Todo] @connection(fields:["id"])
}

type Todo @model {
  id: ID!
  userID: ID!
  user: User @connection(fields:["userID"]
}

As codegen operates currently, a queries file will be generated that looks something lik:

export const getUser = 
  GetUser($id: ID!) {
    getUser($id: ID!) {
      id
      todos  {
        items {
          id
        }
      } 
    }
  }

To my understanding, pagination can only be achieved by then implementing a custom query like so:

export const getUser = 
  GetUser($id: ID!, $limit: Int, $nextToken: String) {
    getUser($id: ID!, $limit: Int, $nextToken: String) {
      id
      todos(limit: $limit, nextToken: $nextToken)  {
        items {
          id
        }
      } 
    }
  }

I think this is a fairly easy opportunity to automate this process with codegen.

Describe alternatives you've considered
I use string interpolation to implement this functionality but it's really annoying when the schema changes to have to re-update the query.

Type Casting API.graphql

Is your feature request related to a problem? Please describe.
The API.ts codegen is very useful for inputs, but is not as useful for typing results of API.graphql(graphqlOperation(createSomeObject, {})). API.grapqhl returns a GraphQLResult or an Observable -- but it isn't able to tell which one it will return and neither are generic, which causes typing challenges.

Describe the solution you'd like

import { CreateSomeObjectMutation, OnCreateSomeObject } from './API';
const result = API.graphql<Mutation, CreateSomeObjectMutation>(graphqlOperation(createSomeObject, {...})) 

// None of the below code should throw a type error. It should expect the object to have this shape.
if(result.data) {
  result.data.createSomeObject
} else {
  console.log(result.errors);
}
const { fieldA } = result.data.createSomeObject;

const observableResult = API.graphql<Subscription, OnCreateSomeObject>(graphqlOperation(onCreateSomeObject, {...})) 

observableResult.then(....???... )

Describe alternatives you've considered
Type casting the result. This works but is less declarative IMO and requires more code.

Additional context

Add support for passing parameter when running subscription in Angular service

Since authorized subscriptions should work by now, following a few tickets aws-amplify/amplify-cli#504, aws-amplify/amplify-cli#1021, aws-amplify/amplify-cli#1766, aws-amplify/amplify-cli#1810.
I don't understand how I can use that subscriptions now with the generated JavaScript client. How can I pass the owner to the subscription?

type Todo @model @auth(rules: [{allow: owner}]){
  id: ID!
  title: String!
  owner: String
}
this.apiService.OnCreateTodoListener.subscribe((evt) => {
      console.log("added: ", evt);
});

Graphql schema limitations for using amplify codegen

Which Category is your question related to?
Amplify Codegen

Amplify CLI Version
4.29.3

What AWS Services are you utilizing?
AppSync

Provide additional details e.g. code snippets

I have GraphQL schema which is deployed to AWS AppSync, and trying to use amplify codegen to generate static types for it.
Experimentally it was found out that codegen fails if:

  1. Types implementing the same interface have properties of different type. F.e. something like this
interface Object {
  id: String
}
type Child1 implements Object {
  id: String
  location: Location
}
type Child2 implements Object {
  id: String
  location: String
}

Will produce Fields "location" conflict because they return conflicting types String and Location. Use different aliases on the fields to fetch both if this was intentional.

  1. Subqueries for types with required arguments also throw errors. F.e.:
type Child2 implements Object {
  id: String
  location(city: String!): String
}

Will produce Field "location" argument "city" of type "String!" is required, but it was not provided.

So I was wondering if there are some limitations/rules which amplify codegen imposes on graphql schema, or there's some configuration that can be used to resolve these problems.

Using enums in our graphql schema

We are using enums in our graphql schema in Amplify/AppSync.

We are confused as to what Amplify enforces and how to use the enums. Simply saving the string values works fine but we'd really like to limit available options to enums to add integrity to the code.

What is the best way to save an enum using a mutator and to compare queried values using the enum. The generated /src/graphql files don't seem to expose the enum values.

Codegen can't generate code at designated path

Describe the bug
I've tried to generate graphql code like below

? Choose the code generation language target typescript
? Enter the file name pattern of graphql queries, mutations and subscriptions ./graphql/**/*.ts
? 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
? Enter the file name for the generated code ./graphql/API.ts
? Do you want to generate code for your newly created GraphQL API Yes
โœ” Generated GraphQL operations successfully and saved at src/graphql

it's expected to generate the code at /graphql/*/ts but the actual graphql code are generated at src/graphql/*.ts
Is it possible to generate the code other than /src?

Amplify CLI Version
4.26.1

To Reproduce
amplify codegen models with a path which doesn't include /src

Expected behavior
graphql code will be generated at /graphql/*./ts instead of /src/graphql/*.ts

Desktop (please complete the following information):

  • OS: macOS 10.14.6
  • Node Version v12.16.1

Codegen for iOS AppSync creates incorrect GraphQL document for maximum depth 2

Describe the bug

The schema is a User model with [Post] model.

type User @model {
  id: ID!
  fullName: String!
  emailAddress: String!
  posts: [Post] @connection(name: "UserPostConnection")
}

type Post @model {
  id: ID!
  text: String!
  user: User @connection(name: "UserPostConnection")
  createdAt: String
  updatedAt: String
}

in Amplify CLI 4.12.0 (current version installed on my system). amplify add api, amplify push and choosing max depth of 2 is generating correct selection set in the API.swift file used for AppSyncClient. See awslabs/aws-mobile-appsync-sdk-ios#376 (comment) for more context

in 4.17.2, as observed by another developer, when setting the max depth to 2, the "posts" in the "user" selection set is not being generated correctly. See awslabs/aws-mobile-appsync-sdk-ios#376 (comment) for more context. Setting it to 3 works as expected. where it be returned as part of a call to get user, ie. selection set contains posts { items { <fields> } }

Amplify CLI Version
Some issue introduced between > 4.12.0 and 4.17.2

Expected behavior
A maximum depth of 2 should mean that the selection set that is generated contains the "posts" inside the "user".

query GetUser($id: ID!) {
    getUser(id: $id) {
    __typename
    id
    fullName
    emailAddress
    posts {
      __typename
      items {
        __typename
        id
        text
        createdAt
        updatedAt
      }
      nextToken
    }
  }
}

but instead it is generating

query GetUser($id: ID!) {
   getUser(id: $id) {
    __typename
    id
    fullName
    emailAddress
    posts {
      __typename
      nextToken
    }
  }
}

Additional context
Didn't notice any transformer changes in the changelog
https://github.com/aws-amplify/amplify-cli/blob/master/packages/amplify-cli/CHANGELOG.md
maybe it's somewhere in transformer/codegen https://github.com/aws-amplify/amplify-cli/blob/master/packages/graphql-transformer-common/CHANGELOG.md

Multiple Code Generation Targets

Is your feature request related to a problem? Please describe.
I have a few lambdas that interface with my amplify appsync api. I've been copying and pasting mutations from the auto-generated folders (output from amplify codegen) into these lambdas in order to carry out the mutations. However, it's really hard to keep up with this when the schema changes. In fact it has broken some of my subscription because the selection set of one of my mutations was not in line. I know that's slightly off topic, but hopefully it demonstrates the pitfall.

Describe the solution you'd like
It'd be nice to be able to add multiple targets to the amplify codegen command. For instance, instead of having src/graphql and src/API.ts, I'd like to specify additional locations where I can have easy access to these convenient definitions.

Describe alternatives you've considered
Manually copy and paste the mutations or queries I need.

Get the introspection schema with amplify pull (without pulling the backend ressources)

Is your feature request related to a problem? Please describe.
When a front-end engineer wants to use a GraphQL API, he will pull the Amplify project to access it. He does not have the intention of modifying the APIs or Functions within that Amplify project. However, he wants to use amplify codegen which would require to download the introspection schema from the AppSync console. Not a very nice workflow since he want's to regenerate his code as soon as there is new stuff added to the API.

Describe the solution you'd like
It would be nice to be able to do amplify codegen, without having to download the introspection schema manually. The current solution is to pull the backend by saying "yes" when prompted by the CLI to this question "Do you plan on modifying this backend?". Maybe, another question would be, would you like to pull the introspection schema? And each subsequent pull would update the schema in question. This way, it is easy for front-end devs to keep up with the schema.

Bug in Angular codegen for GraphQL API subscriptions

Describe the bug
I'm just getting started with AWS and am currently setting up an angular project that makes use of the 'APIService', which is code-generated by the Amplify cli from my local schema.graphql file.
Im an trying to use the APIService to subscribe to the creation of a new database obj (i.e. 'Country').

Generated code:

  OnCreateCountryListener: Observable<
    OnCreateCountrySubscription
  > = API.graphql(
    graphqlOperation(
      `subscription OnCreateCountry {
        onCreateCountry {
          __typename
          id
          name {
            __typename
            value
            languageCode
          }
          createdAt
          updatedAt
        }
      }`
    )
  ) as Observable<OnCreateCountrySubscription>;

...

export type OnCreateCountrySubscription = {
  __typename: "Country";
  id: string;
  name: Array<{
    __typename: "MultiLangInfo";
    value: string;
    languageCode: LanguageCode;
  } | null> | null;
  createdAt: string;
  updatedAt: string;
};

My issue is, that when I subscribe to the generated subsription method, incoming events are expected to be of type 'OnCreateCountrySubscription'. However, when I try to access for example the property 'name', it results as undefined.
By logging the incoming event I noticed that the object is structured as follows:

Google Chrome console output:

{provider: AWSAppSyncRealTimeProvider, value: {โ€ฆ}}
  provider: AWSAppSyncRealTimeProvider {_config: {โ€ฆ}, socketStatus: 1, keepAliveTimeout: 300000, subscriptionObserverMap: 
  Map(2), promiseArray: Array(0), โ€ฆ}
    value:
      data:
        onCreateCountry:
          createdAt: "2020-10-31T12:48:10.879Z"
          id: "00a86220-4d62-4746-b6c0-7f24d64c85d5"
          name: [{โ€ฆ}]
          updatedAt: "2020-10-31T12:48:10.879Z"
__typename: "Country"
__proto__: Object
__proto__: Object
__proto__: Object
__proto__: Object

When I access the object as follows:

APIService.OnCreateCountryListener(c: OnCreateCountrySubscription  => {
  const createdCountry = c .value.data.onCreateCountry;
  // those properties do not exist on the type  'OnCreateCountrySubscription' 
  // -> results in TSError
}

... I get the object in a structure as it would be expected from the type 'OnCreateCountrySubscription' itself. But obviously the typescript compiler sees this as an error.

For me it seems like the type conversion for incoming events is not set up properly in the code generator.

Amplify CLI Version
4.32.0

To Reproduce
GraphQL schema that is used by the angular code generator:

enum LanguageCode {
  DE
  EN
}

type Country @model {
  id: ID!
  name: [MultiLangInfo]
}

type MultiLangInfo {
  value: String!
  languageCode: LanguageCode!
}

Expected behavior
Incoming events are epxtected to actually be of type 'OnCreateCountrySubscription'.

Desktop (please complete the following information):

  • OS: Windows
  • Node Version v12.19.0

Additional context
Add any other context about the problem here.

Feature Request: Use codegen in headless mode seperate from push

Is your feature request related to a problem? Please describe.
When setting up the build configuration for multiple frontend environments with a shared backend, I have the need to make the build process use amplify pull to get the most up-to-date metadata to connect to the backend (e.x. the aws-exports.js file for a React webapp). However, to use any of the GraphQL statements generated by amplify codegen, it seems like I need to store a copy of the statements in each one of the frontend repositories in order to use them. It would be preferable if I could generate the statements during/after pulling to reduce manually duplicating the same files across multiple repositories.

Describe the solution you'd like
I think either one of these proposed solutions would work, though the latter would most likely be easier to implement.

  • Give an option when running amplify pull to generate the GraphQL statements if a GraphQL API is detected in the backend (possibly only on the first pull). Something like
The current backend environment has a GraphQL API. Would you like to generate new GraphQl statements? (Y/n)

Along with the other prompts which appear when running amplify codegen. For headless mode, it would work similarly to how it does for amplify push by providing a --codegen flag to the command.

  • Give amplify codegen add a headless mode, similar to that suggested in aws-amplify/amplify-cli#2005 and aws-amplify/amplify-cli#852. This would allow for automated statement generation if I use amplify pull to get the entire backend definition, which would include the schema. Alternatively, I could just include the schema file in each repository, which would at least minimize the number of files that need to be manually copied and maintained across each one.

Describe alternatives you've considered

  • Using amplify pull to get the entire backend definition and then using amplify push --codegen in headless mode. This doesn't work in this case since just pulling the backend means there are no changes and thus amplify push doesn't run. Even if it did, it wouldn't be ideal to allow the build process to potentially change the backend since it doesn't need to do so.

File name pattern for graphql query generation ignored.

Describe the bug

GraphQL compiled files never placed into the directory stated in amplify step by step procedure.

To Reproduce

When I run

amplify api add

Then select GraphQL, create a schema, and finish generating my Schema...

I run,

amplify push

Then it asks if I want to generate the code for the GraphQL API... I say YES.
Chooses my code generation language. ... I say javascript.
Enter the file name pattern of graphql queries, mutations, and subscriptions (src/graphql/**/*.js)

I change this to app/graphql/**/*.js ... because that's where my code is positioned in my boilerplate.

Amplify ignores this and places it in src/graphql/**/*.js outside of my project.

Expected behavior

I expect graphql/* to be placed in app/ not src/

Ability to generate different filename.swift files from directories of .graphql files

Is your feature request related to a problem? Please describe.

Yes, https://github.com/aws-amplify/amplify-cli/issues/2122

Describe the solution you'd like
amplify codegen --max-depth --input=MySubAPIDirectory --output=MySubAPIDirectory.swift

would produce an api using just the .graphql files in MySubAPIDirectory and save it as MySubAPIDirectory.swift

Basically, I don't want to create the massive namespace polluting API.swift that has everything in it. I want nice clean sub apis with just the queries, mutations, and subscriptions that I use in my app.

Describe alternatives you've considered
See the bug report for how I'm doing it now. It produces an error and is a hack.

How do I generate exportable graphql input types using `amplify codegen`?

** Which Category is your question related to? **

codegen

** What AWS Services are you utilizing? **

appsync, dynamodb

** Provide additional details e.g. code snippets **

I'm trying to follow the documentation here https://aws-amplify.github.io/docs/js/api#aws-appsync-sdk and there is an example for using buildMutation given:

import { listTodos } from './graphql/queries';
import { createTodo, CreateTodoInput } from './graphql/mutations';

(async () => {
  const result = await client.mutate(buildMutation(client,
    gql(createTodo),
    {
      inputType: gql(CreateTodoInput),
      variables: {
        input: {
          name: 'Use AppSync',
          description: 'Realtime and Offline',
        }
      }
    },
    (_variables) => [ gql(listTodos) ],
    'Todo'));

  console.log(result);
})();

Specifically, import { createTodo, CreateTodoInput } from './graphql/mutations';

When I run amplify codegen, the generated src/graphql/mutations.js does not include input types (e.g. CreateTodoInput in the case of the example given). How do I generate these, so I can use buildMutation in a similar manner?

Just noticed I used aws instead of amplify everywhere. My bad :) aws mindshare is strong

[request] offer to run `amplify codegen` directly after `amplify configure codegen`

Describe the bug

using amplify configure codegen to configure typescript code doesnt generate code.

Amplify CLI Version
4.24

To Reproduce

  • have a very simple amplify init setup with a single graphql api in javascript (git repo here https://github.com/sw-yx/testamplify12121)
  • then run amplify configure codegen and try to switch the generated code from javascript to typescript
  • nothing happens

Expected behavior

  • typescript code should be generated

Screenshots
image

Desktop (please complete the following information):

  • OS: mac
  • Node Version. 12.8

codegen on pull: amplify codegen statements from other frontends with a multi frontend environment setup

Is your feature request related to a problem? Please describe.
When working with multiple frontends (e.g. various projects implemented in ReactJS) It would be super that the files of the queries, mutations and subscriptions could be downloaded in some way in these new frontends, brought from the main backend, and saved at an specific folder something similar when running the following command:

amplify codegen statements

It saves the queries, mutations and subscriptions and schema.json at the following default location /src/graphql/*.js

Describe the solution you'd like
Something similar to the following:

amplify codegen statements --appId xxxxxxxxxxxxxx --envName itRocks

Describe alternatives you've considered
Pull the backend schema definition from cloud, and generate the schema, queries, mutations and subscriptions and save it at the default location /src/graphql/*.js

Additional context

Thanks in advance
Paco

amplify codegen model adds non-existent Id field and ignores the key definition

Describe the bug
While generating the model files (Java/Android in my case) the codegen tool on its own adds Id field to the model, while it is NOT in the schema. Of course that doesn't work down the line because this field does not exist. The problem is here: https://github.com/aws-amplify/amplify-cli/blob/9951402777b047277e6e05c6cb84fea92c238e82/packages/amplify-codegen-appsync-model-plugin/src/visitors/appsync-visitor.ts#L199 I used @key directive without the key name to specify HK, which is also not supported. This is not as much as a bug but just really strange implementation that on purpose generates invalid models. Also how is that supposed to work with models that have HK + SK? Code sample down below.

type UserProfile @model @key(fields: ["userId"]) {
  userId: ID!
}

Result:

@ModelConfig(pluralName = "UserProfiles")
@Index(name = "undefined", fields = {"userId"})
public final class UserProfile implements Model {
  public static final QueryField ID = field("id");
  public static final QueryField USER_ID = field("userId");

Expectation: the codegen model tool picks up that the HK is called userId and uses it accordingly, instead of generating invalid models.

Amplify CLI Version
4.6.0

To Reproduce
Create a model with HK other then Id and run amplify codegen model

Expected behavior
The specified column is used as HK.

API '$ amplify codegen models': types without @model directive

API, Bug, code-gen

Describe the bug

$ amplify codegen models amplify API (preview) command is not generating front-end code for types without @model directive, while traditional API sdk generates them.

Amplify CLI Version: amplify -v: 4.6.0

Platform target: iOS

To Reproduce

type Task @model {
    id: ID!
    title: String!
    description: String
    status: String
}
type Note {
    id: ID!
    content: String!
}

When generating front-end code with iOS target:

  • API.swift (old sdk): contains strongly typed code for both Tasks and Notes
  • /amplify/generated/models/ (new preview): only contains code to work with Tasks

Expected behavior

I expected to get front-end code to manage graphQL types without backend DB deployment (without @model). So I can hook up my custom resolvers using the new amplify iOS/android framework (preview).

Improving generated code of amplify codegen (swift)

Is your feature request related to a problem? Please describe.

This feature request/improvement is strictly related to amplify codegen

I've noticed the incredible amount of redundancy (type-wise) when a simple schema is created as code generator will create a duplicate type for every operation (and level) a query has indicated, when this could easily be addressed with type aliases when getting a type.

This is frustrating as I need to write several times the same type conversion to map things to a type that isn't absurd all across my code.

Describe the solution you'd like

Imagine the following schema:

enum Gender {
	male
	female
	unspecified
}

type Person {
	id: ID!
	firstName: String!
	surname: String!
	address: String
	gender: Gender
}

input ModelPersonFilterInput {
	id: ModelIDFilterInput
	name: ModelStringFilterInput
	surname: ModelStringFilterInput
	address: ModelStringFilterInput
	gender: ModelGenderFilterInput
	and: [ModelPersonFilterInput]
	or: [ModelPersonFilterInput]
	not: ModelPersonFilterInput
}

type Query {
	getPersonBy(id: ID!): Person
	listPeople(filter: ModelPersonFilterInput, limit: Int, nextToken: String): Person
}

input CreatePersonInput {
	id: ID
	name: String!
	surname: String!
	address: String
	gender: Gender
}

input UpdatePersonInput {
	id: ID!
	name: String
	surname: String
	address: String
	gender: Gender
}

type Mutation {
	createPerson(input: CreatePersonInput!): Person
	updatePerson(input: UpdatePersonInput!): Person
}

When I download the schema.json and call amplify codegen the generated file will contain no less than 6 or 7 type definitions for Person which are absolutely identical. I completely understand those with the name Create and Update passed in as part of the mutation because well... inputs were defined like that. But my CreatePerson type will define internally a Person which gets redefined in UpdatePerson, ListPeople and GetPersonBy

And I am specifying here something without connections with other structures in "many to many" relationships.

Describe alternatives you've considered

Ideally I would like a single type definition for person and if it is hard to prevent conflicts with other types, create type aliases for each of the operations (mutations, queries or subscriptions) just pointing the one definition. It makes refactoring/data structure revisions so much manageable.

The schema.json file contains the type definition in a single place (as an object) so the block declaration should be able to create a direct connection to the already specified type instead of having to redeclare it (or just replace the reference with yet another type).

If that direct reference is problematic (or we don't want to introduce a massive backwards compatibility issue as it will break the code of many) then we could just use a type alias in place of the structure definition.

'BelongsTo' is generated instead of 'HasOne'

Describe the bug
According to the official doc, a project has one team. After I run amplify codegen models, the connection part shows that project belongs to team instead. The output is similar across all the platforms(including iOS, Android, JS and flutter).
The schema is as following.

type Project @model {
  id: ID!
  name: String
  team: Team @connection
}

type Team @model {
  id: ID!
  name: String!
}

Take swift modelgen as an example. The output schema for project is:

// swiftlint:disable all
import Amplify
import Foundation

extension Project {
  // MARK: - CodingKeys 
   public enum CodingKeys: String, ModelKey {
    case id
    case name
    case team
  }
  
  public static let keys = CodingKeys.self
  //  MARK: - ModelSchema 
  
  public static let schema = defineSchema { model in
    let project = Project.keys
    
    model.pluralName = "Projects"
    
    model.fields(
      .id(),
      .field(project.name, is: .optional, ofType: .string),
      .belongsTo(project.team, is: .optional, ofType: Team.self, targetName: "projectTeamId")
    )
    }
}

Amplify CLI Version
v4.40.0

To Reproduce

  • amplify init a new project and choose any frontend type
  • amplify add api and choose graphql
  • replace the amplify/schema.graphql with the above schema
  • run amplify codegen models

Expected behavior
The HAS_ONE should be generated instead of BELONGS_TO

Screenshots
None

Desktop (please complete the following information):

  • OS: Mac
  • Node Version: v12.18.3

Additional context
This is a bug for a long time and datastore implementation is based on it. One concern is that if there will be breaking changes to datastore once this is fixed.

Add support of gatsby's gatsby-source-graphql plugin fieldName

Is your feature request related to a problem? Please describe.

Gatsby requires to include fieldName for any custom graphql endpoint in the following way:

resolve: "gatsby-source-graphql",
      options: {
        typeName: "Blog",
        fieldName: "appsync",
        url: config.aws_appsync_graphqlEndpoint,
        headers: {
          'x-api-key': APPSYNC_KEY
        }
      },

this makes amplify codegen feature useless.

Describe the solution you'd like

allow to include a "prefix" field at codegen step

Nested Typescript Types are not generated as Types

Describe the bug
When running amplify codegen with Typescript option, if the Schema contains nested Types, they will be generated as plain objects with no proper Type.

Amplify CLI Version
4.19.0

To Reproduce
Consider the following Schema:

type Query { 
    listTest(from: AWSDateTime!, to: AWSDateTime!): myTypeConnection 
} 
type myTypeConnection {
    items: [myType]
    nextToken: String
}
type myType {
    id: ID! some_string: String!
    some_date: AWSDateTime!
}

The resulting codegen TS file will contain:

export type ListTestQuery = {
  listTest:  {
    __typename: "myTypeConnection",
    items:  Array< {
      __typename: "myType",
      id: string,
      some_string: string,
      some_date: string
    } | null > | null,
    nextToken: string | null,
  } | null,
};

Expected behavior
Since we defined proper types in GraphQL schema, I expected all GraphQL types to be transpiled into Typescript Types. Something like:

export type MyType {
  id: string,
  some_string: string,
  some_date: string
}

export type MyTypeConnection {
    items: Array< MyType | null > | null,
    nextToken: string | null,
}

export type ListTestQuery = {
  listTest: MyTypeConnection | null,
};

Desktop (please complete the following information):

  • OS: Ubuntu 18.04.4 LTS
  • Node v11.15.0

Additional context
If this is not a bug kindly let me know and I'll open a feature request. I see no reason why any Type defined in the Schema can't become a Type in generated Typescript code, especially since the addition of the --max-depth which I tried to no avail. Thus, I consider this a bug.

Thanks in advance

RFC: Amplify codegen generating enums.js file in src/graphql folder

Problem:

Currently Amplify codegen generates GraphQL statements(queries, mutations and eventHandlers), but doesn't address the enums.

Quite often we define some "lookup" values in enums, which can change over time. When changes happen, updates have to be done on the both sides, back-end and front-end. This leads to potential discrepancies, and unnecessary work on both sides.

Solution:

The process of updating enums would be simplified and discrepancies avoided, by Amplify codegen generating an additional file beside queries, mutations, and subscriptions, called enums.js. That file would contain lookup values, which, once imported, would always provide updated values without a need to do any updates on the client side.

Developer Experience:

$ amplify codegen

Result (graphql folder):
$ ls src/graphql
mutations.js     queries.js       subscriptions.js     enums.js

Client side:

import { orderStatus } from '../../graphql/enums'

Dynamic runtime subscription support

I need some help here.
The APIService generated by codegen has generated this function.

SubscribeToNewMessageListener: Observable<SubscribeToNewMessageSubscription> = API.graphql(
    graphqlOperation(
      `subscription SubscribeToNewMessage($conversationId: ID!) {
        subscribeToNewMessage(conversationId: $conversationId) {
          __typename
          author {
            __typename
            cognitoId
            id
            username
            registered
          }
          content
          conversationId
          createdAt
          id
          isSent
          recipient {
            __typename
            cognitoId
            id
            username
            registered
          }
          sender
        }
      }`
    )
  ) as Observable<SubscribeToNewMessageSubscription>;

I'm trying to call this listener from an angular page but I can not pass the parameter to the function
always get "Variable 'conversationId' has coerced Null value for NonNull type 'ID!'".
I have tried in all ways but I can not send it.

This is more or less my code.

constructor(
        private api: APIService
    ) {}

    ngOnInit() {
        this.api.SubscribeToNewMessageListener
        .map(msg => msg.conversationId = 'randomGUID')
        .subscribe({
            next: (x) => {console.log('Next',x)},
            error: (e) => {console.log('Error', e)},
            complete: () => {}
        })
    }

Another subscription without parameters, however, it works for me simply by subscribing to it.

Please need help.
Thanks you.

Graphql mutations, queries, subscriptions not created in specified directory.

Describe the bug
When going through the tutorial for amplify I'm asked about generating graphql files.

? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes

Here I specify the file pattern being graphql/**/*.js.

However the code generation tool writes these files to src/graphql instead.

The way I fixed this was to manually edit .graphqlconfig.yml and run amplify codegen.

Amplify CLI Version
4.18.1

Do we fully support fragments?

** Which Category is your question related to? **
GraphQL transformer codegen

** Provide additional details e.g. code snippets **
I'm adding a fragment in a custom GraphQL query file. For example:

fragment SheetParts on Sheet {
  id,
  name,
  bpm,
}

query ListItemPage($id: ID!) {
  getList(id: $id) {
    name,
    sheets {
      items {
        ...SheetParts
      }
    }
  }
}

query MyLibraryPage($limit: Int, $nextToken: String) {
  listSheets(limit: $limit, nextToken: $nextToken) {
    nextToken,
    items {
      ...SheetParts
    }
  }
}

Codegen gracefully generates SheetPartsFragment into my API, but when requesting the qery through the generated API, I get this error:

core.js:15724 ERROR Error: Uncaught (in promise): Object: {"data":null,"errors":[{"path":null,"locations":[{"line":9,"column":9,"sourceName":null}],"message":"Validation error of type UndefinedFragment: Undefined fragment SheetParts @ 'getList/sheets/items'"}]}

Am I missing something?

Thanks

Codegen add with apiId breaking when initialising new dev

Describe the bug
When adding codegen to a project (appsync not created with amplify) with apiId option. If a new developper enter the project and init amplify selecting an existing env, amplify status will tells him that pushed changes will delete it.

To Reproduce
Steps to reproduce the behavior:

  1. Create an amplify project and add codegen: amplify add codegen --apiId AppSyncAPIid
  2. Push changes and push in git also (.graphqlconfig.yml is also in git repo)
  3. Checkout project on another dev computer
  4. Execute amplify init to select right role,...
  5. amplify status will show:
    | Category | Resource name | Operation | Provider plugin |
    | -------- | ----------------------- | --------- | ----------------- |
    | Auth | xxx | No Change | awscloudformation |
    | Hosting | xx | No Change | awscloudformation |
    | Api | xxx | Delete | |
    | Function | xx | No Change | awscloudformation |

Only way to get normal status again is to remove api and add it again.

Expected behavior
All category should be in "No Change" state and the new dev should get the amplify working fine after init.

Desktop (please complete the following information):
Cli version: 1.12.0 on mac (created the project and added the api)
Cli version: 3.9.0 on windows/linux (joined project after)

Additional context
One thing that was maybe different and can help debugging: One dev was on mac and the other one was on windows so the .graphqlconfig.yml changed the / to \ . I don't know if this could be the problem or help debugging it... (problem also occurs on a linux as second dev laptop).

Delete Blog Input has ID (primary key) string or null or undefined with typescript.

Note: If your issue/bug is regarding the AWS Amplify Console service, please log it in the
Amplify Console GitHub Issue Tracker

Describe the bug
A clear and concise description of what the bug is.
After generating typescript code for simple schema Blog has id (string) & title (string). In API.ts you find following code

export type DeleteBlogInput = {
  id?: string | null,
};

How it's possible to delete blog with undefined or null id. However at AppSync console with graphiql it is showing that id (string) is required to delete note.

I deleted API and created again few times & also generated code with amplify codegen

To Reproduce
Steps to reproduce the behavior:
create react app
amplify init
amplify add api
schema is simple

type Blog @model {
     id: ID!
     title: string!
}

amplify push

Expected behavior
I would expect to have following generated code

export type DeleteBlogInput = {
  id: string,
};

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: macOS Catalina
  • Browser: Chrome
  • Version: 77

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

DataStore codegen wrong message for union types

Describe the bug
When a union type is defined in the schema.graphql, an attempt to generate DataStore models fails with the following message:

Unknown type SearchResult for field items. Did you forget to add the @model directive

Amplify CLI Version
4.21.1

To Reproduce

  • Create a schema with a union type.
  • run amplify codegen models

Sample schema:

union SearchResult = Contact | User | Entity
type SearchableConnection {
  items: [SearchResult]
  nextToken: String
  total: Int
}

Expected behavior
A clear message stating that union types are not supported in DataStore.

Screenshots
N/A.

Desktop (please complete the following information):

  • OS: MacOS 10.14.6
  • Node Version: 12.8.0

Additional context
Reported originally by @lenarmazitov: aws-amplify/amplify-swift#544

No way to pass subscription parameters to Angular generated API

Filtering subscriptions by field types does not work for Angular generated API.service.ts

When defining subscription types for Angular there is no way to pass the defined parameter via the generated API

To Reproduce
Steps to reproduce the behavior:
Step 1: Define an entity and set subscriptions to null as per (https://docs.amplify.aws/cli/graphql-transformer/examples#filter-subscriptions-by-model-fields-andor-relations)

type ChangeSource @model(subscriptions: null) @auth(rules: [ { allow: groups, groupsField: "group"}])

{

id: ID!
group: String!
source: String!
action: Int!
target: String!
createdAt: String
}

  1. amplify push

  2. Then add the required subscription with the parameter to filter by
    type Subscription {
    onCreateChangeSource(group: String): ChangeSource @aws_subscribe(mutations: ["createChangeSource"])
    }

  3. amplify push

generates

OnCreateChangeSourceListener: Observable<
OnCreateChangeSourceSubscription

= API.graphql(
graphqlOperation(
subscription OnCreateChangeSource($group: String) { onCreateChangeSource(group: $group) { __typename id group source action target createdAt updatedAt } }
)
) as Observable;
What I canExpected behavior

The API should then allow for a call like
const subscription = this.apiService.OnCreateChangeSourceListener(grpName).subscribe({
next: (data) => console.log(data),
error: (error) => console.error(error)
})
However it does not provide a way to pass any parameters

Code Snippet
API only allows an unfiltered subscription

const subscription = this.apiService.OnCreateChangeSourceListener.subscribe({
next: (data) => console.log(data),
error: (error) => console.error(error)
})
What is Configured?
The configuration for Amplify CLI:

  • Auth (Cognito User Pools), API (Rest, GraphQL and Storage (s3) configured.
  • amplify cli 4.29.3 and Angular 8.2.x
Environment
npx envinfo --system --binaries --browsers --npmPackages --npmGlobalPackages

System:
OS: macOS 10.15.7
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Memory: 147.73 MB / 8.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 12.13.1 - /usr/local/bin/node
npm: 6.14.8 - /usr/local/bin/npm
Browsers:
Brave Browser: 86.1.16.68
Chrome: 86.0.4240.198
Firefox: 79.0
Safari: 14.0
npmPackages:
@angular-devkit/build-angular: ~0.803.20 => 0.803.25
@angular/animations: ~8.2.14 => 8.2.14
@angular/cdk: ~8.2.3 => 8.2.3
@angular/cli: ~8.3.23 => 8.3.25
@angular/common: ~8.2.14 => 8.2.14
@angular/compiler: ~8.2.14 => 8.2.14
@angular/compiler-cli: ~8.2.14 => 8.2.14
@angular/core: ~8.2.14 => 8.2.14
@angular/forms: ~8.2.14 => 8.2.14
@angular/language-service: ~8.2.14 => 8.2.14
@angular/material: ^8.2.3 => 8.2.3
@angular/platform-browser: ~8.2.14 => 8.2.14
@angular/platform-browser-dynamic: ~8.2.14 => 8.2.14
@angular/router: ~8.2.14 => 8.2.14
@capacitor/cli: 1.5.0 => 1.5.0
@capacitor/core: 1.5.0 => 1.5.0
@ionic-native/core: ^5.0.0 => 5.21.6
@ionic-native/splash-screen: ^5.0.0 => 5.21.6
@ionic-native/status-bar: ^5.0.0 => 5.21.6
@ionic/angular: ^5.0.0 => 5.0.1
@ionic/angular-toolkit: ^2.1.1 => 2.1.2
@react-native-community/netinfo: ^5.9.7 => 5.9.7
@syncfusion/ej2-angular-charts: ^18.1.52 => 18.1.52
@syncfusion/ej2-angular-gantt: ^18.1.48 => 18.1.48
@syncfusion/ej2-angular-schedule: ^18.2.47 => 18.2.47
@types/jasmine: ~3.3.8 => 3.3.16
@types/jasminewd2: ~2.0.3 => 2.0.8
@types/node: ~8.9.4 => 8.9.5
aws-amplify: ^3.3.2 => 3.3.2
aws-sdk: ^2.760.0 => 2.760.0
codelyzer: ^5.0.0 => 5.2.1
core-js: ^2.5.4 => 2.6.11
hammerjs: ^2.0.8 => 2.0.8
jasmine-core: ~3.4.0 => 3.4.0
jasmine-spec-reporter: ~4.2.1 => 4.2.1
karma: ~4.1.0 => 4.1.0
karma-chrome-launcher: ~2.2.0 => 2.2.0
karma-coverage-istanbul-reporter: ~2.0.1 => 2.0.6
karma-jasmine: ~2.0.1 => 2.0.1
karma-jasmine-html-reporter: ^1.4.0 => 1.5.2
ngx-quill: ^8.0.0 => 8.0.0
protractor: ~5.4.0 => 5.4.3
quill: ^1.3.7 => 1.3.7
quill-blot-formatter: ^1.0.5 => 1.0.5
quill-emoji: ^0.1.8 => 0.1.8
quill-image-drop-module: ^1.0.3 => 1.0.3
quill-image-resize-module: ^3.0.0 => 3.0.0
rxjs: ~6.5.1 => 6.5.4
serverless-domain-manager: ^3.3.1 => 3.3.1
stripe: ^8.24.0 => 8.24.0
ts: ^0.2.2 => 0.2.2
ts-node: ~7.0.0 => 7.0.1
tslib: ^1.9.0 => 1.11.0
tslint: ~5.15.0 => 5.15.0
typescript: ~3.5.1 => 3.5.3
zen-observable: ^0.8.15 => 0.8.15
zen-observable-ts: ^0.8.21 => 0.8.21
zone.js: ~0.9.1 => 0.9.1
npmGlobalPackages:
@angular/cli: 1.0.0
@aws-amplify/cli: 4.29.3
@ionic/cli-plugin-ionic-angular: 1.3.0
@ionic/cli: 6.11.8
bower: 1.8.0
cordova: 7.0.1
create-react-app: 1.4.3
firebase-tools: 4.2.1
gcloud: 0.37.2
ios-deploy: 1.9.1
ios-sim: 4.1.1
javascript-qrcode: 1.0.7
mocha: 3.5.0
n: 2.1.4
nativescript: 2.2.1
nodemon: 1.18.4
npm: 6.14.8
qrcode-svg: 1.0.0
react-create-app: 2.0.6
serverless: 1.79.0
to: 0.2.9
uglify-js: 2.7.5
uglifyjs: 2.4.10
update: 0.7.4
util: 0.10.3
xcodeproj: 0.0.0

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

You can turn on the debug mode to provide more info for us by setting window.LOG_LEVEL = 'DEBUG'; in your app.

Code generation not configured error

** Which Category is your question related to? **
CLI Codegen
** What AWS Services are you utilizing? **
Appsync
** Provide additional details e.g. code snippets **

I have been using the cli to build a project for some time, and recently updated the schema in Appsync. When attempting to run amplify codegen I receive the error "code generation is not configured. Configure it by running $amplify codegen add".

Running codegen configure does modify my current .graphqlconfig.yml file, so it seems only trying to update creates issues.

Any help updating?

Automatic code generation

Is your feature request related to a problem? Please describe.
Automatic code generation is only offered in two forms. One of them can be done via the AppSync Management console and the other is done using the AWS Amplify CLI.

Describe the solution you'd like
As a user I would like to generate code automatically without using the AppSync Management console or the AWS Amplify CLI so that I can make use of this feature without being dependant on the AppSync Management console or the AWS Amplify CLI.

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.