From 82041cef20f55fda408abed86825ba126a68a143 Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:15:07 +0200 Subject: [PATCH 1/2] feat: add custom wobe context on apollo (#29) --- .../wobe-graphql-apollo/src/index.test.ts | 63 ++++++++++++++++++- packages/wobe-graphql-apollo/src/index.ts | 47 +++++++------- 2 files changed, 83 insertions(+), 27 deletions(-) diff --git a/packages/wobe-graphql-apollo/src/index.test.ts b/packages/wobe-graphql-apollo/src/index.test.ts index 23fbb68..b1da71e 100644 --- a/packages/wobe-graphql-apollo/src/index.test.ts +++ b/packages/wobe-graphql-apollo/src/index.test.ts @@ -4,6 +4,65 @@ import getPort from 'get-port' import { WobeGraphqlApolloPlugin } from '.' describe('Wobe GraphQL Apollo plugin', () => { + it('should have custom wobe context in graphql context', async () => { + const port = await getPort() + + const wobe = new Wobe<{ customType: string }>().beforeHandler((ctx) => { + ctx.customType = 'test' + }) + + wobe.usePlugin( + await WobeGraphqlApolloPlugin({ + options: { + typeDefs: `#graphql + type Query { + hello: String + } + `, + resolvers: { + Query: { + hello: (_, __, context) => { + context.res.setCookie('before', 'before') + + expect(context.res).toBeDefined() + expect(context.request).toBeDefined() + expect(context.customType).toEqual('test') + return 'Hello from Apollo!' + }, + }, + }, + }, + context: async () => { + return { tata: 'test' } + }, + }), + ) + + wobe.listen(port) + + const res = await fetch(`http://127.0.0.1:${port}/graphql`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: ` + query { + hello + } + `, + }), + }) + + expect(res.status).toBe(200) + expect(res.headers.get('set-cookie')).toBe('before=before;') + expect(await res.json()).toEqual({ + data: { hello: 'Hello from Apollo!' }, + }) + + wobe.stop() + }) + it('should have WobeResponse in graphql context', async () => { const port = await getPort() @@ -20,9 +79,9 @@ describe('Wobe GraphQL Apollo plugin', () => { resolvers: { Query: { hello: (_, __, context) => { - context.response.setCookie('before', 'before') + context.res.setCookie('before', 'before') - expect(context.response).toBeDefined() + expect(context.res).toBeDefined() expect(context.request).toBeDefined() return 'Hello from Apollo!' }, diff --git a/packages/wobe-graphql-apollo/src/index.ts b/packages/wobe-graphql-apollo/src/index.ts index d9e16d1..e041cfc 100644 --- a/packages/wobe-graphql-apollo/src/index.ts +++ b/packages/wobe-graphql-apollo/src/index.ts @@ -7,7 +7,13 @@ import { ApolloServerPluginLandingPageLocalDefault, ApolloServerPluginLandingPageProductionDefault, } from '@apollo/server/plugin/landingPage/default' -import type { Wobe, MaybePromise, WobePlugin, WobeResponse } from 'wobe' +import type { + Wobe, + MaybePromise, + WobePlugin, + WobeResponse, + Context, +} from 'wobe' const getQueryString = (url: string) => url.slice(url.indexOf('?', 11) + 1) @@ -22,14 +28,11 @@ export const WobeGraphqlApolloPlugin = async ({ options, graphqlEndpoint = '/graphql', graphqlMiddleware, - context, + context: apolloContext, }: { options: ApolloServerOptions graphqlEndpoint?: string - context?: (options: { - request: Request - response: WobeResponse - }) => MaybePromise + context?: (options: Context) => MaybePromise } & GraphQLApolloPluginOptions): Promise => { const server = new ApolloServer({ ...options, @@ -47,11 +50,8 @@ export const WobeGraphqlApolloPlugin = async ({ await server.start() - return (wobe: Wobe) => { - const getResponse = async ( - request: Request, - wobeResponse: WobeResponse, - ) => { + return (wobe: Wobe) => { + const getResponse = async (context: Context) => { const fetchEndpoint = async (request: Request) => { const res = await server.executeHTTPGraphQLRequest({ httpGraphQLRequest: { @@ -65,11 +65,8 @@ export const WobeGraphqlApolloPlugin = async ({ search: getQueryString(request.url), }, context: async () => ({ - request: request, - response: wobeResponse, - ...(context - ? await context({ request, response: wobeResponse }) - : {}), + ...context, + ...(apolloContext ? await apolloContext(context) : {}), }), }) @@ -86,19 +83,19 @@ export const WobeGraphqlApolloPlugin = async ({ return new Response() } - if (!graphqlMiddleware) return fetchEndpoint(request) + if (!graphqlMiddleware) return fetchEndpoint(context.request) return graphqlMiddleware(async () => { - const response = await fetchEndpoint(request) + const response = await fetchEndpoint(context.request) return response - }, wobeResponse) + }, context.res) } - wobe.get(graphqlEndpoint, async ({ request, res: wobeResponse }) => { - const response = await getResponse(request, wobeResponse) + wobe.get(graphqlEndpoint, async (context) => { + const response = await getResponse(context) - for (const [key, value] of wobeResponse.headers.entries()) { + for (const [key, value] of context.res.headers.entries()) { if (key === 'set-cookie') { response.headers.append('set-cookie', value) continue @@ -110,10 +107,10 @@ export const WobeGraphqlApolloPlugin = async ({ return response }) - wobe.post(graphqlEndpoint, async ({ request, res: wobeResponse }) => { - const response = await getResponse(request, wobeResponse) + wobe.post(graphqlEndpoint, async (context) => { + const response = await getResponse(context) - for (const [key, value] of wobeResponse.headers.entries()) { + for (const [key, value] of context.res.headers.entries()) { if (key === 'set-cookie') { response.headers.append('set-cookie', value) continue From d5dc858f64615a9b852b0fa1647b3ce21e4a002d Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:15:16 +0200 Subject: [PATCH 2/2] feat(wobe-graphql-yoga): feat add custom wobe context (#30) --- packages/wobe-graphql-yoga/src/index.test.ts | 62 +++++++++++++++++++- packages/wobe-graphql-yoga/src/index.ts | 46 ++++++--------- 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/packages/wobe-graphql-yoga/src/index.test.ts b/packages/wobe-graphql-yoga/src/index.test.ts index 1e184ae..3798bfa 100644 --- a/packages/wobe-graphql-yoga/src/index.test.ts +++ b/packages/wobe-graphql-yoga/src/index.test.ts @@ -5,6 +5,62 @@ import getPort from 'get-port' import { WobeGraphqlYogaPlugin } from '.' describe('Wobe GraphQL Yoga plugin', () => { + it('should set the wobe response in the graphql context', async () => { + const port = await getPort() + const wobe = new Wobe<{ customType: string }>().beforeHandler((ctx) => { + ctx.customType = 'test' + }) + + wobe.usePlugin( + WobeGraphqlYogaPlugin({ + typeDefs: ` + type Query { + hello: String + } + `, + resolvers: { + Query: { + hello: (_, __, context: any) => { + context.res.setCookie('tata', 'tata') + expect(context.test).toBeDefined() + expect(context.res).toBeDefined() + expect(context.request.headers).toBeDefined() + expect(context.customType).toEqual('test') + return 'Hello from Yoga!' + }, + }, + }, + context: () => { + return { test: 'test' } + }, + }), + ) + + wobe.listen(port) + + const res = await fetch(`http://127.0.0.1:${port}/graphql`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query: ` + query { + hello + } + `, + }), + }) + + expect(res.headers.get('set-cookie')).toBe('tata=tata;') + expect(res.status).toBe(200) + expect(await res.json()).toEqual({ + data: { hello: 'Hello from Yoga!' }, + }) + + wobe.stop() + }) + it('should set the wobe response in the graphql context', async () => { const port = await getPort() const wobe = new Wobe() @@ -18,10 +74,10 @@ describe('Wobe GraphQL Yoga plugin', () => { `, resolvers: { Query: { - hello: (_, __, context) => { - context.response.setCookie('tata', 'tata') + hello: (_, __, context: any) => { + context.res.setCookie('tata', 'tata') expect(context.test).toBeDefined() - expect(context.response).toBeDefined() + expect(context.res).toBeDefined() expect(context.request.headers).toBeDefined() return 'Hello from Yoga!' }, diff --git a/packages/wobe-graphql-yoga/src/index.ts b/packages/wobe-graphql-yoga/src/index.ts index 2f4a66c..4edc0c8 100644 --- a/packages/wobe-graphql-yoga/src/index.ts +++ b/packages/wobe-graphql-yoga/src/index.ts @@ -4,14 +4,17 @@ import { type GraphQLSchemaWithContext, type YogaServerOptions, } from 'graphql-yoga' -import type { MaybePromise, Wobe, WobePlugin, WobeResponse } from 'wobe' +import type { + Context, + MaybePromise, + Wobe, + WobePlugin, + WobeResponse, +} from 'wobe' export type GraphqlYogaContext = | MaybePromise> - | ((context: { - request: Request - response: WobeResponse - }) => MaybePromise) + | ((context: any) => MaybePromise) export interface GraphqlYogaPluginOptions { graphqlMiddleware?: ( @@ -43,30 +46,19 @@ export const WobeGraphqlYogaPlugin = ({ }), }) - const handleGraphQLRequest = async ( - request: Request, - res: WobeResponse, - ) => { + const handleGraphQLRequest = async (context: Context) => { const getResponse = async () => { - if (!graphqlMiddleware) - return yoga.handle(request, { - response: res, - request, - }) + if (!graphqlMiddleware) return yoga.handle(context.request, context) return graphqlMiddleware( - async () => - yoga.handle(request, { - response: res, - request, - }), - res, + async () => yoga.handle(context.request, context), + context.res, ) } const response = await getResponse() - for (const [key, value] of res.headers.entries()) { + for (const [key, value] of context.res.headers.entries()) { if (key === 'set-cookie') { response.headers.append('set-cookie', value) continue @@ -78,14 +70,12 @@ export const WobeGraphqlYogaPlugin = ({ return response } - return (wobe: Wobe) => { - wobe.get( - options?.graphqlEndpoint || '/graphql', - async ({ request, res }) => handleGraphQLRequest(request, res), + return (wobe: Wobe) => { + wobe.get(options?.graphqlEndpoint || '/graphql', async (context) => + handleGraphQLRequest(context), ) - wobe.post( - options?.graphqlEndpoint || '/graphql', - async ({ request, res }) => handleGraphQLRequest(request, res), + wobe.post(options?.graphqlEndpoint || '/graphql', async (context) => + handleGraphQLRequest(context), ) } }