AWS Amplify GraphQL Transformer Core
This package, `@aws-amplify/graphql-transformer-core`, serves as the foundational framework within AWS Amplify for converting GraphQL Schema Definition Language (SDL) into AWS CloudFormation templates. It is integral to how Amplify provisions serverless GraphQL APIs on AWS AppSync, DynamoDB, Lambda, and OpenSearch. Currently at version 9.0.7, it is actively maintained as part of the broader AWS Amplify monorepo, with releases tied to the Amplify CLI and API category updates. Its key differentiators include simplifying complex cloud infrastructure setup through GraphQL directives like `@model`, `@auth`, `@connection`, and `@searchable`, abstracting away much of the underlying AWS service configuration. A significant architectural shift from Transformer V1 to V2 introduced deny-by-default authorization, explicit data modeling directives (`@primaryKey`, `@index`, `@hasOne`, `@hasMany`), and a new AppSync Pipeline Resolver architecture.
Common errors
-
Data source with name NONE_DS is now preventing amplify push from succeeding.
cause During GraphQL Transformer V1 to V2 migration, or after schema changes, sometimes a 'NONE_DS' (none data source) can remain or be incorrectly referenced.fixManually delete the 'NONE_DS' data source in the AWS AppSync console for your API. You might need to temporarily revert to a V1 schema, push, delete the data source, and then re-apply the V2 schema and push again. -
Expected type AuthStrategy, found private.
cause This error typically indicates an issue with the `@auth` directive syntax or an incompatibility with the GraphQL Transformer's expected `AuthStrategy` enum values, particularly when using custom or outdated `@auth` rules.fixVerify that your `@auth` rules adhere to the correct syntax for your Transformer version (V1 vs. V2). Ensure `allow` strategies like `owner`, `groups`, `public`, `private` (if supported) are correctly configured. In V2, `private` generally implies `allow: private, provider: userPools` or `iam`. -
GraphQL API has a new version. Run 'amplify migrate api' to migrate your schema to the new version.
cause Your Amplify project's GraphQL API is still using the V1 GraphQL Transformer, and a new version (V2) is available and recommended.fixExecute `amplify migrate api` in your CLI to initiate the migration process. Carefully review the migration guide and output for manual steps required after the automated migration. -
ValidationError: Only one resolver is allowed per field.
cause This error can occur during or after a GraphQL Transformer migration (e.g., V1 to V2), indicating that multiple resolver configurations are being generated or detected for a single field, which is not allowed by AppSync.fixThis can sometimes be resolved by simply running `amplify push` again. If it persists, review your schema for conflicting directives or custom resolver files. Ensure that custom VTL resolvers adhere to the V2 pipeline resolver slotting mechanism, avoiding direct overrides where pipeline integration is expected.
Warnings
- breaking The migration from GraphQL Transformer V1 to V2 introduced significant breaking changes. Key directives like `@key` were replaced by `@primaryKey` and `@index`. The `@auth` directive shifted to a deny-by-default model, requiring explicit authorization rules. OpenSearch integration was updated to OpenSearch version 7.10, potentially causing data loss during migration if not handled with snapshots and re-indexing.
- gotcha When using custom transformers or integrating with other GraphQL tooling, ensure that the version of the `graphql` package installed in your project matches the version that `graphql-transformer-core` depends on. Mismatched versions can lead to unexpected parsing errors or runtime issues.
- breaking The architecture of generated resolvers changed significantly with Transformer V2, moving to AppSync Pipeline Resolvers. This impacts custom resolver logic and overrides. If you had custom VTL resolvers in V1, they need to be re-evaluated and potentially refactored to fit the V2 pipeline resolver model.
- gotcha Repeated deployments or complex schemas can sometimes lead to AWS CloudFormation stack limits, such as exceeding the maximum number of IAM policies per role. This is more common during the V1 to V2 migration due to the generated resource changes.
Install
-
npm install graphql-transformer-core -
yarn add graphql-transformer-core -
pnpm add graphql-transformer-core
Imports
- GraphQLTransform
import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core' - TransformConfig
import { TransformConfig } from '@aws-amplify/graphql-transformer-core' - TransformerContext
import { TransformerContext } from '@aws-amplify/graphql-transformer-core' - ModelTransformer
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'
Quickstart
import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core';
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';
import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer';
import { print, parse } from 'graphql';
async function generateCloudFormation() {
const schema = `
type Post @model @auth(rules: [{ allow: public, operations: [read] }, { allow: owner, ownerField: "owner" }]) {
id: ID!
title: String!
content: String
owner: String
}
type Comment @model {
id: ID!
post: Post @hasOne
text: String!
}
`;
const transformers = [
new ModelTransformer(),
new AuthTransformer(),
// You would include other transformers (e.g., ConnectionTransformer) here
];
const transform = new GraphQLTransform({
schema,
transformers,
});
try {
const output = await transform.transform();
console.log('Generated CloudFormation template (truncated):');
// In a real scenario, you'd save `output.stacks.Root.json` to a file.
const cfnTemplate = JSON.stringify(output.stacks.Root.json, null, 2);
console.log(cfnTemplate.substring(0, 500) + '\n...(truncated for brevity)');
console.log('\nGenerated GraphQL Schema (truncated):');
// The transformed schema with additional types and directives can also be accessed.
const transformedSchemaSDL = print(parse(output.schema));
console.log(transformedSchemaSDL.substring(0, 500) + '\n...(truncated for brevity)');
} catch (e) {
console.error('Error during transformation:', e);
}
}
generateCloudFormation();