Deprecated: this code has been incorporated into the GraphQL Tools stitching-directives package.
This utility converts an Apollo Federation SDL string into a Schema Stitching SDL string.
⚠️ NOTE: integration with Apollo Federation and its evolving roadmap is NOT a core concern of GraphQL Tools Schema Stitching. While the two systems have plenty of similarities and you can pull many strings to make them talk to each other, there is no formal contract that guarentees their interoperability. This package interfaces known commonalities between the two systems. Buyer beware that you're assuming your own testing and maintenance overhead if you choose to couple these systems in a production environment.
Schema Stitching supports freeform service bindings that may integrate with any GraphQL query, including the _entities
query setup by Federation services. That means Federation SDLs may be converted to a Stitching SDL and added to a stitched gateway...
Federation SDL:
type Widget @key(fields: "id") {
id: ID! @external
name: String
price: Int @external
shippingCost: Int @requires(fields: "price")
parent: Widget @provides(fields: "price")
}
converted Stitching SDL:
type Widget @key(selectionSet: "{ id }") {
id: ID!
name: String
shippingCost: Int @computed(selectionSet: "{ price }")
parent: Widget
}
scalar _Any
union _Entity = Widget
type Query {
_entities(representations: [_Any!]!): [_Entity]! @merge
}
The translated SDL is configured for the Schema Stitching query planner, see complete translation logic.
Install the package:
npm install federation-to-stitching-sdl
Fetch the SDL from a Federation service:
query {
_service {
sdl
}
}
Convert the Federation SDL to a Stitching SDL:
const federationToStitchingSDL = require('federation-to-stitching-sdl');
const { stitchingDirectives } = require('@graphql-tools/stitching-directives');
// config is only needed when customizing stitching directive names...
const config = stitchingDirectives();
const stitchingSDL = federationToStitchingSDL(federationSDL, config);
A working example can be found in the Schema Stitching Handbook. A compact summary of the major parts looks like this:
const federationToStitchingSDL = require('federation-to-stitching-sdl');
const { stitchSchemas } = require('@graphql-tools/stitch');
const { stitchingDirectives } = require('@graphql-tools/stitching-directives');
const { buildSchema, print } = require('graphql');
const { fetch } = require('cross-fetch');
const stitchingConfig = stitchingDirectives();
const executor = async ({ document, variables }) => {
const query = typeof document === 'string' ? document : print(document);
const result = await fetch('http://localhost:4001/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables }),
});
return result.json();
};
const federationSDL = await executor({ document: '{ _service { sdl } }' });
const stitchingSDL = federationToStitchingSDL(federationSDL, stitchingConfig);
const gatewaySchema = stitchSchemas({
subschemaConfigTransforms: [stitchingConfig.stitchingDirectivesTransformer],
subschemas: [{
schema: buildSchema(stitchingSDL),
executor
}]
});
Federation and Stitching use fundamentally similar patterns to combine underlying subservices (in fact, both tools have shared origins in Apollo Stitching). However, Federation SDLs are nuanced because they are incomplete (they omit their own spec), they may contain baseless type extensions (which are invalid GraphQL), and they may contain fields that the service has no data for (the "external" fields). These nuances are normalized for Schema Stitching as follows:
- Prepend a directives type definition string.
- Turn all baseless type extensions into base types.
- Rewrite
@key(fields: "id")
as@key(selectionSet: "{ id }")
. - Rewrite
@requires(fields: "price")
as@computed(selectionSet: "{ price }")
. - Remove fields with an
@external
directive unless they are part of the@key
. Stitching expects schemas to only publish fields that they actually have data for. Remove any remaining@external
directives. - Remove all
@provides
directives. They are no longer necessary once the indirection of@external
fields is eliminated. Stitching's query planner can automate the optimial selection of as many fields as possible from as few services as possible. - Collect the names of all types marked with
@key
(Entities). If there are one or more names:- Add an
_Any
scalar. - Add an
_Entity
union populated with all unique names. - Add an
_entities(representations: [_Any!]!): [_Entity]! @merge
query.
- Add an