Last active
May 30, 2024 14:38
-
-
Save ashbuilds/490d504d703a5ddfcdf504f6c21e220d to your computer and use it in GitHub Desktop.
Implementing GraphQL Subscriptions with Websockets in a Bun Server using graphql-yoga
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Bun from 'bun' | |
import { createYoga, YogaInitialContext, YogaServerInstance } from 'graphql-yoga' | |
import { makeHandler } from "graphql-ws/lib/use/bun"; | |
import { ExecutionArgs } from "@envelop/types"; | |
import { schema } from './graphql/schema'; | |
interface IUserContext { | |
token?: string; | |
} | |
const PORT = process.env.PORT || 4000; | |
const yoga: YogaServerInstance<{}, YogaInitialContext> = createYoga({ | |
graphqlEndpoint: '/graphql', | |
schema, | |
graphiql: { | |
subscriptionsProtocol: 'WS', | |
}, | |
context: async ({ request }): Promise<IUserContext> => { | |
return { | |
token: request.headers.get("token") ?? "" | |
} | |
} | |
}) | |
const websocketHandler = makeHandler({ | |
schema, | |
execute: (args: ExecutionArgs) => args.rootValue.execute(args), | |
subscribe: (args: ExecutionArgs) => args.rootValue.subscribe(args), | |
onSubscribe: async (ctx, msg) => { | |
const {schema, execute, subscribe, contextFactory, parse, validate} = yoga.getEnveloped({ | |
...ctx, | |
req: ctx.extra.request, | |
socket: ctx.extra.socket, | |
params: msg.payload | |
}) | |
const args = { | |
schema, | |
operationName: msg.payload.operationName, | |
document: parse(msg.payload.query), | |
variableValues: msg.payload.variables, | |
contextValue: await contextFactory(), | |
rootValue: { | |
execute, | |
subscribe | |
} | |
} | |
const errors = validate(args.schema, args.document) | |
if (errors.length) return errors | |
return args | |
}, | |
}) | |
const server: Bun.Server = Bun.serve({ | |
fetch: (request: Request, server: Bun.Server): Promise<Response> | Response => { | |
// Upgrade the request to a WebSocket | |
if (server.upgrade(request)) { | |
return new Response() | |
} | |
return yoga.fetch(request, server) | |
}, | |
port: PORT, | |
websocket: websocketHandler, | |
}) | |
console.info( | |
`🚀 Server is running on ${new URL( | |
yoga.graphqlEndpoint, | |
`http://${server.hostname}:${server.port}` | |
)}` | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this line cannot set request to context (line 34)
req: ctx.extra.request,
it is undefined so cannot access headers