From d9c4bf9899ff3f67152a6deec75aec0e38fcc3b7 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Tue, 12 Mar 2024 13:54:23 +0300 Subject: [PATCH] feat: variable batching --- .changeset/quiet-owls-occur.md | 5 ++++ .../graphql-yoga/__tests__/batching.spec.ts | 30 +++++++++++++++++++ packages/graphql-yoga/src/server.ts | 3 ++ .../src/utils/process-batched-params.ts | 16 ++++++++++ 4 files changed, 54 insertions(+) create mode 100644 .changeset/quiet-owls-occur.md create mode 100644 packages/graphql-yoga/src/utils/process-batched-params.ts diff --git a/.changeset/quiet-owls-occur.md b/.changeset/quiet-owls-occur.md new file mode 100644 index 0000000000..f3b0e34055 --- /dev/null +++ b/.changeset/quiet-owls-occur.md @@ -0,0 +1,5 @@ +--- +'graphql-yoga': minor +--- + +Support variable batching diff --git a/packages/graphql-yoga/__tests__/batching.spec.ts b/packages/graphql-yoga/__tests__/batching.spec.ts index a141c2393f..2785ca3453 100644 --- a/packages/graphql-yoga/__tests__/batching.spec.ts +++ b/packages/graphql-yoga/__tests__/batching.spec.ts @@ -7,12 +7,14 @@ describe('Batching', () => { type Query { hello: String bye: String + greetings(name: String!): String! } `, resolvers: { Query: { hello: () => 'hello', bye: () => 'bye', + greetings: (_root, { name }) => `hello, ${name}`, }, }, }); @@ -287,4 +289,32 @@ describe('Batching', () => { ], }); }); + it('variable batching', async () => { + const yoga = createYoga({ + schema, + batching: {}, + }); + const query = /* GraphQL */ ` + query ($name: String!) { + greetings(name: $name) + } + `; + const res = await yoga.fetch('http://yoga/graphql', { + method: 'POST', + headers: { + accept: 'application/graphql-response+json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query, + variables: [{ name: 'Alice' }, { name: 'Bob' }, { name: 'Charlie' }], + }), + }); + const result = await res.json(); + expect(result).toEqual([ + { data: { greetings: 'hello, Alice' } }, + { data: { greetings: 'hello, Bob' } }, + { data: { greetings: 'hello, Charlie' } }, + ]); + }); }); diff --git a/packages/graphql-yoga/src/server.ts b/packages/graphql-yoga/src/server.ts index 031e988624..3e137a5d53 100644 --- a/packages/graphql-yoga/src/server.ts +++ b/packages/graphql-yoga/src/server.ts @@ -67,6 +67,7 @@ import { YogaMaskedErrorOpts, } from './types.js'; import { maskError } from './utils/mask-error.js'; +import { processBatchedParams } from './utils/process-batched-params.js'; /** * Configuration options for the server @@ -535,6 +536,8 @@ export class YogaServer< }); } + requestParserResult = processBatchedParams(requestParserResult); + const result = (await (Array.isArray(requestParserResult) ? Promise.all( requestParserResult.map(params => diff --git a/packages/graphql-yoga/src/utils/process-batched-params.ts b/packages/graphql-yoga/src/utils/process-batched-params.ts new file mode 100644 index 0000000000..10e8fbdf8c --- /dev/null +++ b/packages/graphql-yoga/src/utils/process-batched-params.ts @@ -0,0 +1,16 @@ +import { GraphQLParams } from '../types.js'; + +export function processBatchedParams( + params: GraphQLParams | GraphQLParams[], +): GraphQLParams | GraphQLParams[] { + if (Array.isArray(params)) { + return params.map(param => processBatchedParams(param)).flat(); + } + if (Array.isArray(params.variables)) { + return params.variables.map(variables => ({ + ...params, + variables, + })); + } + return params; +}