Contentful
Due to the continued development, iterations and scalability of our CMS it will become hard to maintain and manage a manually written schema. As such we should continue to use Contentfuls hosted instance.
This combined with the recent evolvement of schema stitching means that the previously large gap in between schema-stitching and federation is no longer there and they are becoming more closely aligned.
Overview
Why Stitching
One of the main benefits of GraphQL is that we can query for all data in a single request to one schema. As that schema grows though, it may become preferable to break it up into separate modules or microservices that can be developed independently. This is certainly how things are working currently as the mobile rides schema was developed independently of the ecommerce schema. We also have the need to stitch third-party schemas, in our case, contentful. But we should allow this to be flexible for other APIs such as Newstore.
Considerations
Duplicate Types
Stitching has two strategies for handling types duplicated across subschemas: an automatic merge strategy (default), and an older manual resolution strategy. We may select between these strategies using the mergeTypes option.
Automatic merge
Types with the same name are automatically merged by default in GraphQL Tools v7. That means objects, interfaces, and input objects with the same name will consolidate their fields across subschemas, and unions/enums will consolidate all of their members. The combined gateway schema will then smartly delegate portions of a request to the proper origin subschema(s)
Automatic merging will only encounter conflicts on type descriptions and fields. By default, the final definition of a type or field found in the subschemas array is used, or a specific definition may be marked as canonical to prioritize it.
Merge validations
The automatic merge strategy also validates the integrity of merged schemas. Validations may be set to error, warn, or off for the entire schema or scoped for specific types and fields.
Manual resolution
By setting mergeTypes: false, only the final description and fields for a type found in the subschemas array will be used, and automated query planning will be disabled. You may manually resolve differences between conflicting types with an onTypeConflict handler:
Adding transforms
Another strategy to avoid conflicts while combining schemas is to modify one or more of the subschemas using transforms. Transforming allows a schema to be groomed in such ways as adding namespaces, renaming types, or removing fields (to name a few) prior to stitching it into the combined gateway schema. These transforms should be added directly to subschema config:
import { FilterRootFields, RenameTypes } from '@graphql-tools/wrap'
const postsSubschema = {
schema: postsSchema,
transforms: [
new FilterRootFields((operation, rootField) => rootField !== 'postsByUserId'),
new RenameTypes(name => `Post_${name}`)
]
}
In the example above, we transform the postsSchema by removing the postsByUserId root field and adding a Post_ prefix to all types in the schema. These modifications will only be present in the combined gateway schema.
Error handling
Whether you're merging types, using schema extensions, or simply combining schemas, any errors returned by a subschema will flow through the stitching process and report at their mapped output positions. It's fairly seamless to provide quality errors from a stitched schema by following some basic guidelines:
- Report errors! Having a subschema return null without an error for missing or failed records is a poor development experience to begin with. This omission will compound should an unexpected value produce a misleading failure in gateway stitching. Reporting proper GraphQL errors will contextualize failures in subschemas, and by extension, within the stitched schema.
- Map errors to array positions. When returning arrays of records (a common pattern while batch loading), make sure to return errors for specific array positions rather than erroring out the entire array. For example, an array should be resolved as:
- Assure valid error paths. The GraphQL errors spec prescribes a path attribute mapping an error to its corresponding document position. Stitching uses these paths to remap subschema errors into the combined result. While GraphQL libraries should automatically configure this path for you, the accuracy may vary by programming language.