Как добавить запросы root и viewer на существующий сервер GraphQL для поддержки Relay
Я некоторое время работал с GraphQL и смог успешно запустить простой сервер GraphQL. Теперь я пытаюсь заставить его поддерживать Relay, мою конечную цель, и у меня возникают проблемы с добавлением поддержки запроса корневого узла и запроса средства просмотра.
Я понимаю концепцию как узла, так и средства просмотра, но я не заставляю его работать так, как я структурировал свой код. Вот мой код, организованный в отдельные файлы:
./graphql/User/types.js
import {
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
} from 'graphql';
import { GraphQLLong } from '../scalars';
import { NodeInterface } from '../interfaces';
const fields = {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
email: {
type: GraphQLString
},
firstName: {
type: GraphQLString
},
lastName: {
type: GraphQLString
},
jobTitle: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
};
export const UserType = new GraphQLObjectType({
name: 'User',
description: 'User',
interface: NodeInterface,
fields: fields
})
./graphql/User/queries.js
import { GraphQLNonNull, GraphQLID, GraphQLList } from 'graphql';
import { UserType, UserInputType } from './types';
import UserModel from '../../models/User';
const User = {
type: UserType,
description: 'Get single user',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(root, params) {
params.deleted = false;
return UserModel.find(params).exec();
}
}
const Users = {
type: new GraphQLList(UserType),
description: 'Get all users',
resolve(root) {
const companies = UserModel.find({ deleted: false }).exec();
if (!companies) {
throw new Error('Error getting users.')
}
return companies;
}
}
export default {
User,
Users
}
./graphql/Company/types.js
import {
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
} from 'graphql';
import { GraphQLLong } from '../scalars';
import { UserType } from '../User/types';
import { NodeInterface } from '../interfaces';
import UserModel from '../../models/User';
const fields = {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString
},
ein: {
type: GraphQLString
},
users: {
type: new GraphQLList(UserType),
resolve(company) {
const { _id } = company;
return UserModel.find({ companyId: _id }).exec();
}
}
};
export const CompanyType = new GraphQLObjectType({
name: 'Company',
description: 'Company',
interface: NodeInterface,
fields: fields
})
./graphql/Company/queries.js
import { GraphQLNonNull, GraphQLID, GraphQLList } from 'graphql';
import { CompanyType, CompanyInputType } from './types';
import CompanyModel from '../../models/Company';
const Company = {
type: CompanyType,
description: 'Get single company',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(root, params) {
params.deleted = false;
return CompanyModel.find(params).exec();
}
}
const Companies = {
type: new GraphQLList(CompanyType),
description: 'Get all companies',
resolve(root) {
const companies = CompanyModel.find({ deleted: false }).exec();
if (!companies) {
throw new Error('Error getting companies.')
}
return companies;
}
}
export default {
Company,
Companies
}
./graphql/interfaces.js
import {
GraphQLInterfaceType,
GraphQLNonNull,
GraphQLID
} from 'graphql';
const NodeInterface = new GraphQLInterfaceType({
name: 'Node',
fields: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolveType: (source) => {
return source.__type;
}
});
export default NodeInterface;
./graphql/schema.js
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
import queries from './queries';
import mutations from './mutations';
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: queries
}),
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: mutations
})
});
./graphql/queries.js
import {
GraphQLObjectType,
GraphQLNonNull,
GraphQLID
} from 'graphql';
import { NodeInterface } from './interfaces';
import CompanyQueries from './Company/queries';
import UserQueries from './User/queries';
const RootQuery = new GraphQLObjectType({
name: 'RootQuery',
description: 'The root query',
fields: {
viewer: {
type: NodeInterface,
resolve(source, args, context) {
return { result: "VIEWER!" };
}
},
node: {
type: NodeInterface,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(source, args, context, info) {
return { result: "NODE QUERY" };
}
}
}
});
export default {
RootQuery,
...CompanyQueries,
...UserQueries
}
./server.js
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import morgan from 'morgan';
import graphqlHTTP from 'express-graphql';
import schema from './graphql/schema';
// set up example server
const app = express();
app.set('port', (process.env.API_PORT || 3001));
// logger
app.use(morgan('dev'));
// parse body
app.use(bodyParser.json());
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true,
pretty: true
}));
const mongoUri = process.env.MONGO_URI || 'mongodb://localhost/testdb';
mongoose.set('debug', true);
mongoose.connect(mongoUri, {
useMongoClient: true,
});
export default app;
RootQuery не добавляется в схему. На самом деле я получаю эту ошибку:
Error: Query.RootQuery field type must be Output Type but got: undefined.
Концептуально я не знаю, как исправить этот код:
a) Я не знаю, как добавить этот RootQuery к моему запросу, и я не знаю, нужно ли мне сохранять другие мои запросы на моем сервере (поскольку Relay в основном полагается на запросы узлов).
б) я также не вижу, как мой RootQuery обнаружит тип объекта и вернет его в return source.__type
, Я добавил этот фрагмент кода, но я не знаю, как или где данный тип заполнит это поле.
Хотя я немного разбираюсь в GraphQL, видно, что у меня пока нет основ того, как построить Relay, требуется корневой запрос (не говоря о paginators, но это мой следующий шаг после того, как я это решу).
Помощь приветствуется.
0 ответов
Проблема, похоже, в
import queries from './queries';
new GraphQLObjectType({
name: 'Query',
fields: queries
}),
const RootQuery = new GraphQLObjectType({
…
});
export default {
RootQuery,
…
};
В queries
что вы передаете как поля для Query
Тип - это объект типов, а не объект конфигураций полей. Они отсутствуютtype
а также resolve
properties, как сообщается в сообщении об ошибке.