Как добавить объединение типа в Apollo graphql
Я создал этот вопрос на тот случай, если кому-нибудь будет интересно, как добавить объединение / полиморфные типы в Apollo. Надеюсь, это поможет им.
В этом примере я хотел, чтобы ответ был либо Worksheet
или же ApiError
// typedefs.js
export default [`
schema {
query: Query
}
type Query {
worksheet(id: String!): Worksheet | Error
}
type Worksheet {
id: String!
name String
}
type ApiError {
code: String!
message: String!
}
`];
// resolvers.js
export default {
Query: {
worksheet(_, args, { loaders }) {
return loaders.worksheet.get(args.id).catch(() => {
// ApiError
return {
code: '1',
message: 'test'
}
});
}
}
};
// Express Server
import { graphqlExpress } from 'apollo-server-express';
import { makeExecutableSchema } from 'graphql-tools';
import typeDefs from './typedefs';
import resolvers from './resolvers';
...
app.post(
'/graphql',
graphqlExpress(req => ({
makeExecutableSchema({ typeDefs, resolvers }),
context: mkRequestContext(req.ctx, req.log),
formatError: formatGraphQLError(req.ctx, req.log)
}))
);
1 ответ
В GraphQL для добавления типа объединения в typedefs вы должны определить объединение
т.е. union WorksheetOrError = Worksheet | ApiError
// typedefs.js
export default [
`
schema {
query: Query
}
type Query {
worksheet(id: String!): WorksheetOrError
}
union WorksheetOrError = Worksheet | ApiError
type Worksheet {
id: String!
name String
}
type ApiError {
code: String!
message: String!
}
`];
В резольверах вы должны определить резолвер для типа объединения, который имеет свойство __resolveType. Это поможет сообщить исполнителю GraphQL, к какому типу относится результат.
// resolvers.js
export default {
Query: {
worksheet() {
...
}
},
WorksheetOrError: {
__resolveType(obj) {
if (obj.id) {
return 'Worksheet';
}
if (obj.code) {
return 'ApiError';
}
return null;
}
},
};
Чтобы создать GraphQL-запрос в Apollo Client
// Your application code.
// This is my Worksheet Query in my React code.
const WorksheetQuery = gql`
query GetWorksheet($worksheetId: String!) {
worksheet(id: $worksheetId) {
... on Worksheet {
id
name
}
... on ApiError {
code
message
}
}
}
Теперь вы можете проверить __typename
чтобы проверить, какой тип в ответе.
Примечание: для тех, кому интересно, почему я не использую ошибки GraphQL. Это потому, что Apollo плохо обрабатывает ошибки, когда сталкивается с ошибкой graphQL. Так что для работы я пытаюсь вернуть обычай
ApiError
в моем ответе.