2017-11-10 3 views
1

Ich habe ein Problem in Bezug auf GraphQL Schema Stitching. Ich habe zwei Graphql Schemen:Apollo Graphql Schema Stitching Konflikt

type Name { 
    firstname: String! 
    lastname: String! 
} 

type Address { 
    street: String! 
    number: Int! 
} 

type User { 
    name: Name! 
    address: Address! 
} 

type Query { 
    user(userId: String!): User 
} 

und

type User { 
    age: String! 
} 

type Query { 
    user(userId: String!): User 
} 

jetzt habe ich versucht, das Schema mit graphql-Tool der mergeSchemas Funktion zu fusionieren:

const schema = mergeSchemas({ 
    schemas: [schema1, schema2] 
}); 

Aber statt dem, was ich bin versuchen zu erreichen (ein erweiterter Benutzertyp):

type Name { 
    firstname: String! 
    lastname: String! 
} 

type Address { 
    street: String! 
    number: Int! 
} 

type User { 
    name: Name! 
    address: Address! 
    age: String! 
} 

type Query { 
    user(userId: String!): User 
} 

Es ergab sich: Typ Name { Vorname: String! Nachname: String! }

type Address { 
    street: String! 
    number: Int! 
} 

type User { 
    name: Name! 
    address: Address! 
} 

type Query { 
    user(userId: String!): User 
} 

Nur einer der UserTypes wird im letzten Schema angezeigt. Ich versuchte mit der onTypeConflict API in mergeSchemas, um den Typ zu erweitern, aber ich habe keine Ergebnisse erzielt.

Gibt es eine Möglichkeit, Schemas zusammenzuführen, indem Typen bei Konflikten erweitert werden?

+0

helfen Was Sie Ziel? Sie können nur einen Benutzertyp haben. Möchten Sie sie zusammenführen oder möchten Sie nur den zweiten Benutzertyp? Was in Ihrem Fall passiert, ist das Standardverhalten, das den ersten gefundenen Typ aller Typen mit demselben Namen annimmt. –

+0

Idealerweise möchte ich den Benutzertyp erweitern. Ich habe meine Frage entsprechend bearbeitet. –

+0

Das Problem ist, dass dies keine lokalen Schemas sind, daher kann ich nicht einfach "type User" in "extend type User" ändern. Ich hole sie mit 'makeRemoteExecutableSchema' –

Antwort

0

Hier ist eine mögliche Lösung zum Zusammenführen der Objekttypen. Vielleicht ist es sinnvoll, nach Typnamen in onTypeConflict zu filtern, statt jeden Typ zusammenzuführen.

import cloneDeep from 'lodash.clonedeep' 
import { GraphQLObjectType } from 'graphql/type/definition' 
import { mergeSchemas } from 'graphql-tools' 

function mergeObjectTypes (leftType, rightType) { 
    if (!rightType) { 
    return leftType 
    } 
    if (leftType.constructor.name !== rightType.constructor.name) { 
    throw new TypeError(`Cannot merge with different base type. this: ${leftType.constructor.name}, other: ${rightType.constructor.name}.`) 
    } 
    const mergedType = cloneDeep(leftType) 
    mergedType.getFields() // Populate _fields 
    for (const [key, value] of Object.entries(rightType.getFields())) { 
    mergedType._fields[key] = value 
    } 
    if (leftType instanceof GraphQLObjectType) { 
    mergedType._interfaces = Array.from(new Set(leftType.getInterfaces().concat(rightType.getInterfaces()))) 
    } 
    return mergedType 
} 

const schema = mergeSchemas({ 
    schemas: [schema1, schema2], 
    onTypeConflict: (leftType, rightType) => { 
    if (leftType instanceof GraphQLObjectType) { 
     return mergeObjectTypes(leftType, rightType) 
    } 
    return leftType 
    } 
}) 

Credits: Die mergeObjectTypes Funktion von Jared Wolinsky geschrieben wurde.

+0

Hey! Vielen Dank für Ihre Antwort, es wird versucht, die beiden GraphQL-Benutzertypen zusammenzuführen, aber es gibt ein Problem. Wenn ich den Code ausführe, protokolliert er einen Fehler, dass der 'Name' Typ nicht gefunden wurde. Ich denke, dies passiert, weil es zuerst den Konflikt behandelt, bevor er irgendeinen der anderen Typen "importiert". Haben Sie eine Idee, wie Sie dieses Problem lösen können? –

0

Dies sollte

extend type User { 
    age: String! 
} 
+0

Außer dass ich keine lokalen Schemas habe, versuche ich entfernte Schemas mit graphql-Werkzeugen zu verschmelzen. –