I'm trying to get GraphQL Subscriptions working (without Apollo) using these libraries:
import { graphqlHTTP } from 'express-graphql';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
I've been reading the source of these libraries and everything written online I can find and just can't get Graphiql to initiate the socket connection. It's probably a small configuration issue I'm missing - can you spot it?
BEHAVIOR:
When I open GraphiQL and attempt to create a subscription, I immediately get returned a null
result and no connection is made in Chrome's Network > WS tab. The subscribe
method doesn't get called but the resolve
method does though payload
is empty. 2 days trying to sort this out. Please help.
import http from "http";
import express from "express";
import { graphqlHTTP } from "express-graphql";
import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/lib/use/ws";
import graphQLSchema from "./graphql";
const { NODE_ENV } = process.env;
console.log(`NODE_ENV: ${NODE_ENV}`);
(async () => {
/**
* Setup Express
*/
const app = express();
/**
* Setup GraphQL Server
*/
const API_ENDPOINT = "/api";
const PORT = 8080
const ENABLE_GRAPHIQL = NODE_ENV !== "production";
app.use(
API_ENDPOINT,
graphqlHTTP((req, res, graphQLParams) => {
return {
schema: graphQLSchema,
graphiql: ENABLE_GRAPHIQL,
context: { req, res },
};
})
);
const httpServer = http.createServer(app);
const wsServer = new WebSocketServer({
server: httpServer,
path: API_ENDPOINT,
});
/**
* Start Server
*/
try {
httpServer.listen(8080, () => {
console.log(` GraphQL available at http://localhost:${PORT}${API_ENDPOINT}`);
// create and use the websocket server
useServer(
{ schema: graphQLSchema },
wsServer
);
const wsAddress = wsServer.address();
console.log(` WebSockets listening on ws://localhost:${wsAddress.port}${API_ENDPOINT}`);
});
} catch (error) {
console.error(error);
}
})();
Subscription: {
invitationCreated: {
resolve: payload => {
console.log(payload);
return payload;
},
subscribe: () => pubsub.asyncIterator('INVITATION_CREATED'),
},
}
type Subscription {
invitationCreated: Invitation
}
Result:
subscription invitationCreatedSub {
invitationCreated {
email
}
}
# returns -->
{
"data": {
"invitationCreated": null
}
}
EDIT
I found out you can do websockets in Postman which gives a little more insight: