Поддерживает ли GraphQLSchema тип подписки, кроме запросов и мутаций? - PullRequest
0 голосов
/ 18 апреля 2019

отображение типа подписки в graphiql Я использовал запрос и мутацию с 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',
        });
});
...