So I have this two schemas
Schema1
type Permission {
relation: Relation
}
enum Relation {
ONE
TWO
THREE
}
Schema2
type Permission {
relation: Relation
}
enum Relation {
FOUR
FIVE
SIX
}
The expect result is something similar to: (but I'm open to different ideas) The queries I would like to make after the merge are:
{
permissions{
relation
}
}
And get a result like
"permissions": [
{
"relation": "ONE"
},
{
"relation": "SIX"
}
]
or
"permissions": [
{
"relation": "schema1ONE"
},
{
"relation": "schema2SIX"
}
]
And mutations like:
mutation{
createPermission(
relation: ONE
){
relation
}
}
mutation{
createPermission(
relation: SIX
){
relation
}
}
or
mutation{
createPermission(
relation: schema1ONE
){
relation
}
}
mutation{
createPermission(
relation: schema2SIX
){
relation
}
}
I'm trying using the transformSchema
function on graphql-tools but can't quite figure it out correctly:
const Schema1 = await getRemoteSchema('schema1_url', 'schema1');
const Schema2 = await getRemoteSchema('schema2_url', 'schema2');
const schemas = [Schema1, Schema2]
const schema = mergeSchemas({
schemas: schemas,
resolvers: {}
});
getRemoteSchema definition
export const getRemoteSchema = async (uri: string, schemaName: string): Promise<GraphQLSchema> => {
const httpLink = new HttpLink({ uri, fetch });
const schema = await introspectSchema(httpLink);
const executableSchema = makeRemoteExecutableSchema({
schema,
httpLink,
});
// transform schema by renaming root fields and types
const renamedSchema = transformSchema(
executableSchema,
[
new RenameTypes(name => {
if (name == 'Relation') {
return schemaName + name
} else {
return name
}
}),
// new RenameRootFields((operation, name) => `${schemaName}_${name}`)
]
);
return renamedSchema;
}
I made this glitch https://glitch.com/edit/#!/schema-stitching-conflict So it's easier to see the problem.
Schema stitching combines multiple subschemas and creates a combined proxy layer called gateway that a client can use to make requests. This means that you can combine smaller GraphQL schemas from different modules or even different remote services into one schema called the gateway.
Combining schemas may be as simple as allowing a value to be validated against multiple criteria at the same time. These keywords correspond to well known boolean algebra concepts like AND, OR, XOR, and NOT.
The docs say Schema Stitching is deprecated in favor of Apollo Federation. Of course, Federation can replace Schema Stitching in general. However, there are some cases only Schema Stitching makes sense.
Hence, we can create two separate schemas, the Admin and Public schemas, and expose them under endpoints /graphql/admin and /graphql respectively.
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.
Schema stitching can also be used to customise an existing GraphQL API. For example: You want to extend the schema of an existing GraphQL API by adding more fields to an existing type whose data comes from another data source
GraphQL Schema Stitching is the mechanism of composing multiple GraphQL schemas together into a single unified schema. This plays strongly into the concept of “back-ends for front-ends” which is building a specialised API designed specifically for the app in question.
In theory, you could connect any schema that uses GraphQL as a subschema, but this isn't the case in practice. Federation uses custom directives to combine the subschemes into one schema.
You need both RenameTypes
and RenameRootFields
transforms,
RenameTypes
to transform the typenames
from: Permission
and Relation
(The colliding types),
to: schema1_Permission
, schema2_Permission
and: schema1_Relation
, schema1_Relation
RenameRootFields
to transform the Query names for those types
from: permission(id: ID!): Permission
to: schema1_permission(id: ID!): schema1_Permission
and schema2_permission(id: ID!): schema2_Permission
and: permissions: [Permission]
to: schema1_permissions: [schema1_Permission]
and schema2_permissions: [schema2_Permission]
The transform would be something like:
const {
makeExecutableSchema,
addMockFunctionsToSchema,
transformSchema,
RenameTypes,
RenameRootFields
} = require('graphql-tools');
const schema1 = makeExecutableSchema({
typeDefs: `
type Permission {
id: ID!
text: String
relation: Relation
}
type Query {
permissions: [Permission]
permission(id: ID!): Permission
}
enum Relation {
ONE
TWO
THREE
}
`
});
addMockFunctionsToSchema({ schema: schema1 });
const renamedSchema1 = transformSchema(
schema1,
[
new RenameTypes(name => {
if (name == 'Relation' || name == 'Permission') {
return 'schema1_' + name
} else {
return name
}
}, { renameBuiltins: false, renameScalars: true }),
new RenameRootFields((_op, name) => {
return name.includes('ermission') ? `schema1_${name}` : name
})
]
);
references: https://www.apollographql.com/docs/graphql-tools/schema-transforms/ https://www.apollographql.com/docs/graphql-tools/schema-stitching/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With