-
Hey everyone! I'm using schema stitching to setup a gateway that merges a remote schema and a local one. The local schema extends the remote schema types with additional fields. This part works great. But the local schema also overwrites existing remote schema fields. I need to be able to define the local schema as the canonical source of truth for specific fields on specific types. This is what I'm struggling to figure out. I tried marking the fields and/or parent types as canonical but to no avail. Please does someone have any pointers? Am I trying to do something Schema Stitching isn't meant to do? Here's an example setup I'm using: # Remote schema definition
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String
age: Int
} // Local schema definition
const localSchema = createSchema({
typeDefs: `
type Query {
getUserById(id: ID!): User
}
type User {
id: ID!
name: String @canonical # This doesn't seem to affect the resolution the way I think it does
intro: String!
}
`,
resolvers: {
Query: {
getUserById: (_, { id }) => ({ id }),
},
User: {
intro: () => 'Hello!',
name: () => 'Velma', // I want this to take precedence over the remote schema
},
},
});
// Stitched schema
const stitchedSchema = stitchSchemas({
subschemas: [
{
schema: remoteSchemaDefinition,
executor: remoteSchemaExecutor,
batch: true,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'user',
args: ({ id }) => ({ id }),
},
},
},
{
schema: localSchema,
batch: true,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUserById',
args: ({ id }) => ({ id }),
},
},
},
],
}); |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
Looks like the stitched schema definition's resolver has precedence over whatever sub-schemas return, so it seems I could use it, but that goes against the local schema being the source of truth. const stitchedSchema = stitchSchemas({
subschemas: [
{
schema: remoteSchemaDefinition,
executor: remoteSchemaExecutor,
batch: true,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'user',
args: ({ id }) => ({ id }),
},
},
},
{
schema: localSchema,
batch: true,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUserById',
args: ({ id }) => ({ id }),
},
},
},
],
resolvers: {
User: {
name: {
selectionSet: '{ id }',
resolve: () => 'Velma', // Works, but takes control away from the local schema
},
},
},
}); |
Beta Was this translation helpful? Give feedback.
-
Canonical directive is part of stitching directives. If you want to mark fields as canonical programmatically, you can use "merge"; merge: {
User: {
fields: {
name: {
canonical: true
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Alright, I figured it out. First, what I'm trying to accomplish is similar to Apollo's @override directive. I want to be able to specify which subschema should be used for a resolutiuon of a specific duplicate field. I could not achieve this using canonical definitions. However, I figured my intended functionality works under two conditions:
For example, this works: const stitchedSchema = stitchSchemas({
subschemas: [
{
schema: await schemaFromExecutor(remoteSchemaExecutor),
executor: remoteSchemaExecutor,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUser',
args: ({ id }) => ({ id }),
},
},
},
// localSchema is placed last in the array
{
schema: localSchema,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUser', // The fieldName is exactly the same as the remote schema
args: ({ id }) => ({ id }),
},
},
},
],
}); This does not: const stitchedSchema = stitchSchemas({
subschemas: [
{
schema: await schemaFromExecutor(remoteSchemaExecutor),
executor: remoteSchemaExecutor,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUser',
args: ({ id }) => ({ id }),
},
},
},
// Even though localSchema is placed last in the array
{
schema: localSchema,
merge: {
User: {
selectionSet: '{ id }',
fieldName: 'getUserById', // The fieldName is DIFFERENT so it won't work
args: ({ id }) => ({ id }),
},
},
},
],
}); |
Beta Was this translation helpful? Give feedback.
Alright, I figured it out.
First, what I'm trying to accomplish is similar to Apollo's @override directive. I want to be able to specify which subschema should be used for a resolutiuon of a specific duplicate field.
I'm using this to migrate away from a monolith API.
I could not achieve this using canonical definitions.
However, I figured my intended functionality works under two conditions:
subschemas
arraymerge
option is using the exact samefieldName
For example, this works: