I am trying to pass the pubsub to resolvers. I am able to pass pubsub to subscription ‘subscribe’ functions via the useServer function, and as far as I can tell from research the expressMiddleware context should be passed to all resolvers, but when logging it out I’m just getting the request object.
index.ts
const express = require('express')
import router from './routes/index'
import cors from 'cors'
import { graphqlHTTP } from 'express-graphql'
import { GraphQLObjectType, GraphQLSchema } from 'graphql'
import http from 'http'
import { ApolloServer } from '@apollo/server'
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'
import mongoose, { RootQuerySelector } from 'mongoose'
import * as mutations from './graphql/mutations'
import * as queries from './graphql/queries'
import { newMessages } from './graphql/subscriptions/newMessages'
import { PubSub } from 'graphql-subscriptions'
import { WebSocketServer } from 'ws'
import { useServer } from 'graphql-ws/lib/use/ws'
import { expressMiddleware } from '@apollo/server/express4'
type AppContext = {
token?: string
}
const RootQueryType = new GraphQLObjectType({
name: 'Query',
description: 'Root Query',
fields: () => queries
})
const RootMutationType = new GraphQLObjectType({
name: 'Mutation',
description: 'Root Mutation',
fields: () => mutations
})
const RootSubscriptionType = new GraphQLObjectType({
name: 'Subscription',
description: 'Root Subscription',
fields: () => ({
newMessages
})
})
const schema = new GraphQLSchema({
query: RootQueryType,
mutation: RootMutationType,
subscription: RootSubscriptionType
})
const startServer = async () => {
const app = express()
app.use(cors())
app.use(router)
const pubsub = new PubSub()
const httpServer = http.createServer(app)
const wsServer = new WebSocketServer({ server: httpServer })
const serverCleanup = useServer(
{
schema,
context: async (ctx, msg, args) => {
return {
pubsub
}
},
onConnect: () => ({ pubsub })
},
wsServer
)
const server = new ApolloServer<AppContext>({
schema,
csrfPrevention: true,
cache: 'bounded',
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart () {
return {
async drainServer () {
await serverCleanup.dispose()
}
}
}
}
]
})
await server.start()
app.use(
'/graphql',
graphqlHTTP({
schema,
graphiql: true
}),
express.json(),
expressMiddleware(server, {
context: async () => ({ pubsub })
})
)
const url = `mongodb+srv://${process.env.MONGO_USERNAME}:${process.env.MONGO_PASSWORD}@${process.env.MONGO_URL}/?retryWrites=true&w=majority`
mongoose.connect(url)
await new Promise(resolve => {
const listener = httpServer.listen(
{
port:
process.env.NODE_ENV === 'production'
? process.env.PORT || 80
: process.env.DEV_PORT || 8080
},
(res: void) => resolve(res)
)
})
console.log(
`get poppin' at ${
process.env.NODE_ENV === 'production'
? process.env.PORT || 80
: process.env.DEV_PORT || 8080
} /graphql`
)
}
startServer()
postMessage.js
import { GraphQLString } from 'graphql'
import { MessageGQL } from '../../../types/gqlOutputTypes/Message'
import { MessageGroup } from '../../schema/Message'
import { Message } from '../../../types/tsTypes/Message'
import { PubSub } from 'graphql-subscriptions'
import { MessageGQLInput } from '../../../types/gqlInputTypes/MessageGQLInput'
import { MessageGroupType } from '../../types/MessageGroupType'
type NewMessage = {
id: string
message: Message
}
export const postMessage = {
type: MessageGroupType,
description: 'Add a message to a group',
args: {
id: { type: GraphQLString },
message: { type: MessageGQLInput }
},
resolve: async (
_parent: undefined,
args: NewMessage,
context: { pubsub: PubSub }
) => {
const { id, message } = args
const messageGroup = await MessageGroup.findById(id)
messageGroup.messages.push(message)
console.log(context)
// pubsub.publish('MESSAGE_SENT', {
// messageSent: messageGroup.messages
// }),
messageGroup.save()
return messageGroup
}
}
console.log is logging request object.
package.json
{
"name": "trvlr-be",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": "18.12.1",
"npm": "8.19.2"
},
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "npx tsc",
"compile": "tsc -p .",
"dev": "concurrently "npx tsc --watch" "nodemon -q dist/index.js"",
"start": "node dist/index.js",
"deploy": "git push heroku main",
"codegen": "graphql-codegen --config codegen.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"@apollo/client": "^3.8.7",
"@apollo/server": "^4.9.5",
"@types/cors": "^2.8.12",
"@types/googlemaps": "^3.43.3",
"@types/node-fetch": "^2.6.2",
"apollo-server": "^3.12.0",
"apollo-server-core": "^3.11.1",
"apollo-server-express": "^3.11.1",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-graphql": "^0.12.0",
"firebase": "^9.14.0",
"graphql": "^16.6.0",
"graphql-subscriptions": "^2.0.0",
"graphql-ws": "^5.14.2",
"mongoose": "^6.7.3",
"node-fetch": "^2.6.7",
"pusher": "^5.1.3",
"url": "^0.11.0",
"uuid": "^9.0.0",
"ws": "^8.14.2"
},
"devDependencies": {
"@graphql-codegen/cli": "5.0.0",
"@graphql-codegen/introspection": "4.0.0",
"@graphql-codegen/typescript": "4.0.1",
"@graphql-codegen/typescript-mongodb": "2.4.6",
"@graphql-codegen/typescript-resolvers": "4.0.1",
"@types/express": "^4.17.14",
"@types/google.maps": "^3.52.6",
"@types/react-native-maps": "^0.24.2",
"@types/uuid": "^8.3.4",
"concurrently": "^7.5.0",
"nodemon": "^2.0.20",
"react-native-debugger": "^1.1.0",
"typescript": "^4.9.3"
}
}
I have tried using the 3rd, 4th and 5th arguments, I have tried changing the structure of my server and I have tried using the context field of the Apolloserver object, the useServer function and the express Middleware function.