aws-amplify / aws-amplify/amplify-cli
RFC: Plugins support in Amplify Codegen
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 825
- Avg merge
- 11d 23h
- Merged PRs (30d)
- 2
Description
_This is a Request For Comments (RFC). RFCs are intended to elicit feedback regarding a proposed change to the Amplify Framework. Please feel free to post comments or questions here._
**Summary**:
The current [Amplify GraphQL code generator](https://github.com/aws-amplify/amplify-codegen) needs improvements to make it more flexible and easily extensible. This RFC describes a plugins based architecture together with a re-designed configuration which could make the Amplify GraphQL code generator more flexible by allowing customizations at plugin level and easily extensible by supporting custom code generator plugins.
**Motivation**:
The motivation for this proposal comes from several developer requests listed in the **Related Issues** below. To summarize, developers want :
* To Generate type annotations at multiple destinations from a shared GraphQL schema
* To Generate type annotations or GraphQL statements from GraphQL schema split across multiple files
* Ability to use custom plugins to generate type annotations and also specify customizations for the plugins we provide.
* Better documentation for the codegen configuration
A plugins based architecture also brings several advantages to the current state of Amplify GraphQL code generator:
* More engagement from the developer community by encouraging them to build custom plugins. This could help us build a broader collection of plugins supporting multiple language targets quickly.
* Opportunity to refactor our current [GraphQL code generation packages](https://github.com/aws-amplify/amplify-codegen/tree/master/packages) (statements, types and models generators) into smaller plugins specific to the target language. For example, `@aws-amplify/graphql-typescript-types-generator` , `@aws-amplify/graphql-swift-types-generator` etc.
* It would make releasing experimental or optional features easier because the change radius would be limited to a plugin. This would give us an opportunity to add more customizations for each codegen language target.
In the absence of a plugins based architecture, it would become increasingly difficult to maintain the current GraphQL code generation packages as the number of supported language targets increases with time.
It would also be harder to add customizations for each language target being code generated.
**Detailed Design**:
1. **Re-Designed Configuration File:** This is a sample configuration file that supports plugins based architecture:
``` yml
schema:./amplify/backend/api/apiName/build/schema.graphql // resolved GraphQL schema. Accepts a list.
generates:
statements:
src/graphql:
plugins:
- @aws-amplify/graphql-typescript-docs-generator
types:
src/API.ts:
plugins:
- @aws-amplify/graphql-typescript-types-generator
models:
src/models: // treats models generation for Amplify Datastore as another types generation task
schema: ./amplify/backend/api/apiName/schema.graphql //overrides the top level schema
plugins:
- @aws-amplify/appsync-typscript-modelgen-plugin
```
_This is subject to change and will be updated in the RFC if need be. Any suggestions are welcome._
2. **Plugin Interfaces:** We will define the interfaces which the plugins are expected to implement in order for the generator to use them. The current types, statements and models generators will implement these interfaces and hence, can readily be used as plugins to the new architecture.
Some anticipated additions include:
* amplify-codegen-core package will be added which handles:
* reading and parsing the re-designed configuration file
* executing the specified plugins with appropriate plugin configurations
* Collect and write the plugin outputs
* amplify-codegen-plugins-common package will be added which:
* defines the interfaces a plugin must/can implement
* defines the type definitions like PluginOutput and methods common to all plugins
**Developer Experience**:
The current GraphQL configuration (named `.graphqlconfig.yml`) is not well documented and its structure is confusing to developers. As part of this effort, we would like to make the configuration file as the source of truth for the generator. The amplify codegen add CLI walkthrough would help the developer create a minimal configuration file, which we will then prompt him/her to edit to add any customizations. We will clearly document how to create and maintain the configuration file.
The `codegen add` workflow will generate the re-designed configuration which can be re-configured using `codegen configure`.
The `codegen statements` workflow will use the plugins defined in the statements section of the re-designed config to generate the GraphQL operations.
The `codegen types` workflow will use the plugins defined in the types section of the re-designed config to generate the type annotations at corresponding output location. By default, types generators use the statements generation output. This behavior can however be customized to specify location to custom statements.
The `codegen models` workflow will use the plugins defined in the models section of the re-designed config to generate the type annotations at corresponding output location. These are intended to be used in combination with [Amplify Datastore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js#code-generation-amplify-cli).
The `codegen` workflow will run the statements, types and models workflows.
Refer **Appendix** for more information.
We will provide a guide to creating custom plugins for the developers. We will also provide API documentation for the supported plugins including the customizations they support.
**Drawbacks and Adoption Strategy**:
The developer would need to migrate to using the re-designed configuration.
We will continue to support the options that are present in the current configuration, for example, maxDepth, region, apiId etc. The output of the generators should remain the same when appropriately configured.
In addition to the detailed documentation for the re-designed configuration, we will provide a migration guide to help the developers quickly make the switch.
The initial release will provide a [Feature Flag](https://github.com/aws-amplify/amplify-codegen/blob/master/FeatureFlags.md) with a pre-defined deprecation date which allows the existing customers to test the plugins architecture before making the switch.
**Related Issues**:
* https://github.com/aws-amplify/amplify-codegen/issues/49
* https://github.com/aws-amplify/amplify-codegen/issues/39#issuecomment-538312222
* https://github.com/aws-amplify/amplify-codegen/issues/44
* https://github.com/aws-amplify/amplify-codegen/issues/35
**Appendix**:
**Architecture Overview**
This section gives an overview of the re-designed architecture. _It is subject to change and should be treated as a sample._
Consider a simple schema using a statements generator, two types generators and a models generator plugins:
```yml
schema:./amplify/backend/api/apiName/build/schema.graphql // resolved GraphQL schema
generates:
statements:
src/graphql:
plugins:
-
types:
src/API.ts:
plugins:
-
src/other/API.ts:
schema: ./amplify/backend/api/apiName/schema.graphql //overrides the top level schema
plugins:
-
models:
src/models:
schema: ./amplify/backend/api/apiName/schema.graphql //overrides the top level schema
plugins:
-
```
`amplify codegen statements` workflow: Generates GraphQL statements from a given GraphQL schema.

`amplify codegen types` workflow: Generates type annotations in specific target language from given GraphQL schema and GraphQL statements.

`amplify codegen models` workflow: Generates type annotations in specific target language from given GraphQL schema, to be used with [Amplify Datastore](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js#code-generation-amplify-cli)

`amplify codegen` workflow: Generates GraphQL statements from a given GraphQL schema. Then, uses the schema and the generated statements to generate type annotations in specific target language. Also, generates the type annotations called Datastore Models from the given GraphQL schema.

The context being passed to various plugins will contain the information that it needs to generate the code.
**Terminology**:
* “_GraphQL statements_“ refers to the GraphQL queries, mutations and subscriptions.
* “_statements generator_” refers to a plugin that generates GraphQL statements from given GraphQL schema. Also referred to as “_docs generator_”. [See Example](https://github.com/aws-amplify/amplify-codegen/tree/master/packages/graphql-docs-generator).
* “_types generator_” refers to a plugin that generates language specific type annotations from given GraphQL schema and GraphQL statements. [See Example](https://github.com/aws-amplify/amplify-codegen/tree/master/packages/graphql-types-generator).
* “_models generation_” refers generating the language specific type annotations or Models that are used to work with Amplify Datastore. Refer for [more information](https://docs.amplify.aws/lib/datastore/getting-started/q/platform/ios#code-generation-platform-integration).
* “_codegen_”, “_typegen_”, “_docgen_” are short forms for “_code generation_”, “_types generator_” and “_statements generator_” respectively.
* “_type annotations_” refers to the language specific type definitions generated for @model annotated types and statements. For example,
```javascript
// Given the schema with a simple query:
type Todo {
id: ID!
name: String!
description: String
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
}
type Query {
getTodo(id: ID!): Todo
}
// Type annotations in typescript look like:
export type Todo = {
__typename: "Todo",
id?: string,
name?: string,
description?: string | null,
createdAt?: string,
updatedAt?: string,
};
export type GetTodoQueryVariables = {
id?: string,
};
export type GetTodoQuery = {
getTodo?: {
__typename: "Todo",
id: string,
name: string,
description?: string | null,
createdAt: string,
updatedAt: string,
} | null,
};
```
**References**:
The current code generation packages (statements, types and models) can be found [here](https://github.com/aws-amplify/amplify-codegen/tree/master/packages)
Special thanks to pointing out the following resources in some of the feature-requests:
* https://github.com/apollographql/apollo-tooling
* https://github.com/dotansimha/graphql-code-generator
Contributor guide
Assessment
This issue has not been assessed yet.