showing subscription type in graphiql我使用了GraphqlSchema查询和变异,与SDL(模式定义语言)相比,我个人更喜欢GraphqlSchema,在SDL中,反引号``包裹了整个查询。 我一直在尝试向其添加订阅,但是,出现错误 subscriptionClient.subscribe不是graphiql中的函数。
有人有什么问题吗?
架构文件
// define types
// define relationship between types
// define root queries: how do we intially get into data
const Book = require('../models/book');
const Author = require('../models/author');
const graphql = require('graphql');
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();
const _ = require('lodash');
const {
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLSchema,
GraphQLInt,
GraphQLList,
GraphQLNonNull } = graphql;
const SOMETHING_CHANGED_TOPIC = 'something_changed';
// this is a function that takes in object type
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({ // we put every detail in function, which needs to be explicitly called, else we get errors on the types
id: { type: GraphQLString },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args) {
return Author.findById(parent.authorID);
}
}
})
});
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({ authorID: parent.id })
}
}
})
});
// user uses exact names as written below when he wants to query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } }, //book(id:"123") {name }
resolve(parent, args) {
//code to get data from db
return Book.findById(args.id);
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
pubsub.publish(SOMETHING_CHANGED_TOPIC, { somethingChanged: "123" });
return Book.find({});
}
},
author: {
type: AuthorType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Author.findById(args.id);
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args) {
return Author.find({});
}
}
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
age: { type: GraphQLInt }
},
resolve(parent, args) {
let author = new Author({
name: args.name,
age: args.age
}); // local instance of author model
return author.save();
}
},
addBook: {
type: BookType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
genre: { type: GraphQLString },
authorID: { type: new GraphQLNonNull(GraphQLID) }
},
resolve(parent, args) {
let book = new Book({
name: args.name,
genre: args.genre,
authorID: args.authorID
}); // local instance of book model
return book.save();
}
}
}
});
const Subscription = new GraphQLObjectType({
name: 'Subscription',
fields: {
somethingChanged: {
type: GraphQLString,
resolve: () => {
console.log('..........inside here');
subscribe: () => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC)
},
subscribe: () => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC)
.then(response => console.log('........', response))
.catch(err => console.log('........', err))
},
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation,
subscription: Subscription
});
package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon ./app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^1.11.0"
},
"dependencies": {
"cors": "^2.8.5",
"esm": "^3.2.22",
"express": "^4.16.4",
"express-graphql": "^0.7.1",
"graphql": "^14.2.1",
"graphql-server-express": "^1.4.0",
"graphql-subscriptions": "^1.1.0",
"loadash": "^1.0.0",
"lodash": "^4.17.11",
"mongoose": "^5.4.14",
"nodemon": "^1.18.11",
"subscriptions-transport-ws": "0.8.3"
}
}
app.js
const express = require('express');
//const graphqlHTTP = require('express-graphql');
const schema = require('./schema/schema');
const {
graphqlExpress,
graphiqlExpress,
} = require('graphql-server-express');
const mongoose = require('mongoose');
const cors = require('cors');
const { printSchema, buildSchema } = require('graphql');
const config = require('./config.json');
const bodyParser = require('body-parser');
const graphql = require('graphql');
const { execute, subscribe } = graphql;
const { createServer } = require('http');
const { SubscriptionServer } = require('subscriptions-transport-ws');
mongoose.connect(config.mongoURL, function () { /* dummy function */ })
.then(() => {
console.log('Connected with mongo');
})
.catch(err => { // mongoose connection error will be handled here
console.error('Mongo connection error:', err.stack);
process.exit(1);
});
mongoose.connection.once('open', () => {
console.log('Connected to database');
});
/** somthing something something something something something */
const PORT = 7900;
const server = express();
server.use('*', cors({ origin: 'http://localhost:3000' }));
server.use('/graphql', bodyParser.json(), graphqlExpress({
schema
}));
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://localhost:${PORT}/subscriptions`
}));
// We wrap the express server so that we can attach the WebSocket for subscriptions
const ws = createServer(server);
ws.listen(PORT, () => {
console.log(`GraphQL Server is now running on http://localhost:${PORT}`);
// Set up the WebSocket for handling GraphQL subscriptions
new SubscriptionServer({
execute,
subscribe,
schema,
onConnect() {
console.log('connected to subscription server');
}
}, {
server: ws,
path: '/subscriptions',
});
});