AWS AppSync中避免Mutation重复定义Input类型的方案咨询
Hey there! I’ve dealt with this exact headache in AWS AppSync before—having to duplicate Profile/Address into InputProfile/InputAddress feels so redundant, especially when working with local (NONE-type) data sources. Let’s walk through the best solutions to reuse your existing types without hitting those validation errors.
First, let’s quickly clarify why you can’t just pass Profile directly: GraphQL enforces a strict separation between output type definitions and input input definitions. Even with local data sources, AppSync adheres to this spec, so raw object types won’t work as mutation arguments. But there are workarounds!
1. Use the @inputObject Directive (Transformer v2+)
If you’re using AWS AppSync’s GraphQL Transformer v2 (common with Amplify or CDK), the @inputObject directive lets you mark an existing object type as usable both as an output and input type. This eliminates the need for duplicate input definitions entirely.
Example schema:
type Profile @inputObject { id: ID! name: String! address: Address @inputObject } type Address @inputObject { street: String! city: String! } type Mutation { updateProfile(profile: Profile!): Profile } type Subscription { profileUpdated: Profile @aws_subscribe(mutations: ["updateProfile"]) }
Now you can pass a Profile object directly to your updateProfile mutation, and it will work seamlessly with your subscription. Note: This doesn’t support complex types like unions or interfaces, but it’s perfect for simple nested object structures like your Profile/Address setup.
2. Reduce Redundancy with Reusable Field Fragments
If you can’t use @inputObject (e.g., manual schema writing, older Transformer versions), you can use GraphQL fragments to centralize field definitions, so you only write them once and reference them in both your object and input types.
Example schema:
# Shared field definitions for Profile fragment ProfileCoreFields on Profile { id: ID! name: String! } # Shared field definitions for Address fragment AddressCoreFields on Address { street: String! city: String! } # Output type type Profile { ...ProfileCoreFields address: Address } type Address { ...AddressCoreFields } # Input type (reuses the same field definitions) input InputProfile { id: ID! name: String! address: InputAddress } input InputAddress { street: String! city: String! }
While you still have separate input types, you only maintain the field definitions once. This cuts down on typos and makes updates much easier.
3. Generate Input Types Programmatically
For larger schemas, consider automating input type generation using a script. You can parse your GraphQL schema AST, identify object types, and auto-generate corresponding input types with the Input prefix.
Here’s a quick example using the graphql npm package:
const { parse, print, visit } = require('graphql'); // Parse your existing schema string const schemaAST = parse(` type Profile { id: ID! name: String! address: Address } type Address { street: String! city: String! } `); // Traverse the AST to generate input types const inputTypes = []; visit(schemaAST, { ObjectTypeDefinition(node) { // Skip root types like Query/Mutation if (['Query', 'Mutation', 'Subscription'].includes(node.name.value)) return; // Convert object type to input type const inputType = { kind: 'InputObjectTypeDefinition', name: { kind: 'Name', value: `Input${node.name.value}` }, fields: node.fields.map(field => ({ ...field, // Recursively replace object types with their input counterparts type: visit(field.type, { NamedType(typeNode) { if (typeNode.name.value !== 'String' && typeNode.name.value !== 'ID') { return { ...typeNode, name: { ...typeNode.name, value: `Input${typeNode.name.value}` } }; } return typeNode; } }) })) }; inputTypes.push(inputType); } }); // Add generated input types to the schema schemaAST.definitions.push(...inputTypes); // Print the updated schema with input types console.log(print(schemaAST));
This script will auto-generate InputProfile and InputAddress for you, ensuring consistency between your output and input types without manual duplication.
内容的提问来源于stack exchange,提问作者Riku92

