I am following along the tutorial on official about using Subscriptions. But I am getting this error saying
Internal error occurred during message handling. Please check your implementation. Error: Subscription field must return Async Iterable. Received: undefined."
Here is my code`
Server.ts
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import { makeExecutableSchema } from "@graphql-tools/schema";
import cors from "cors";
import express from "express";
import { PubSub } from "graphql-subscriptions";
import { useServer } from "graphql-ws/lib/use/ws";
import http from "http";
import { WebSocketServer } from "ws";
import { PrismaClient } from "@prisma/client";
import resolvers from "./graphql/resolver";
import typeDefs from "./graphql/typeDefs";
import { getServerSession } from "./lib/getServerSession";
import { GraphQlContext, SubscriptionContext } from "./types/types";
const corsOption = {
origin: "http://localhost:3000",
credentials: true,
};
const main = async () => {
const app = express();
const httpServer = http.createServer(app);
const schema = makeExecutableSchema({
typeDefs,
resolvers,
});
const prisma = new PrismaClient();
const pubsub = new PubSub();
// Creating the WebSocket server
const wsServer = new WebSocketServer({
// This is the `httpServer` we created in a previous step.
server: httpServer,
// Pass a different path here if app.use
// serves expressMiddleware at a different path
path: "/subscriptions",
});
// Hand in the schema we just created and have the
// WebSocketServer start listening.
const serverCleanup = useServer(
{
schema,
context: async (ctx: SubscriptionContext): Promise<GraphQlContext> => {
if (ctx.connectionParams && ctx.connectionParams.session) {
const { session } = ctx.connectionParams;
return { session, prisma, pubsub };
}
return { session: null, prisma, pubsub };
},
},
wsServer
);
const server = new ApolloServer({
schema,
csrfPrevention: true,
cache: "bounded",
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
await server.start();
app.use(
"/",
cors(corsOption),
express.json(),
expressMiddleware(server, {
context: async ({ req, res }): Promise<GraphQlContext> => {
const session = await getServerSession(req.headers.cookie as string);
return { session, prisma, pubsub };
},
})
);
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve)
);
console.log(`🚀 Server ready at http://localhost:4000/`);
};
main();
Mutation and Subscription part in resolver.ts
Mutation: {
createConversation: async (
_: any,
args: { participantIds: string[] },
context: GraphQlContext
) => {
const { session, prisma, pubsub } = context;
const { participantIds } = args;
const userId = session?.user.id;
if (!session) new GraphQLError("Not Authorized");
try {
const conversation = await prisma.conversation.create({
data: {
participants: {
createMany: {
data: participantIds.map((id) => ({
userId: id,
hasSeenLastMessage: id === userId,
})),
},
},
},
include: conversationPopulate,
});
pubsub.publish("CONVERSATION_CREATED", {
conversationCreated: conversation,
});
return { conversationId: conversation.id };
} catch (error: any) {
throw new GraphQLError(error?.message);
}
},
},
Subscription: {
conversationCreated: {
subsrcibe: (_: any, __: any, { pubsub }: GraphQlContext) => {
return pubsub.asyncIterator(["CONVERSATION_CREATED"]);
},
},
},
And I don’t think it’s relate but this is what is showing in front end browser