diff --git a/.changeset/pink-jobs-accept.md b/.changeset/pink-jobs-accept.md new file mode 100644 index 00000000000..28fdaf8550a --- /dev/null +++ b/.changeset/pink-jobs-accept.md @@ -0,0 +1,18 @@ +--- +'@apollo/server-integration-testsuite': minor +'@apollo/server': minor +--- + +Updating the ApolloServer constructor to take in a stringifyResult function that will allow a consumer to pass in a function that formats the result of an http query. + +Usage: +```ts +const server = new ApolloServer({ + typeDefs, + resolvers, + stringifyResult: (value: FormattedExecutionResult) => { + return JSON.stringify(value, null, 2); + }, +}); +``` + diff --git a/packages/server/src/ApolloServer.ts b/packages/server/src/ApolloServer.ts index 7daeb70783f..cf72d046c7d 100644 --- a/packages/server/src/ApolloServer.ts +++ b/packages/server/src/ApolloServer.ts @@ -15,6 +15,7 @@ import { type TypedQueryDocumentNode, type ValidationContext, type ValidationRule, + type FormattedExecutionResult, } from 'graphql'; import { type KeyValueCache, @@ -179,6 +180,7 @@ export interface ApolloServerInternals { // flip default behavior. status400ForVariableCoercionErrors?: boolean; __testing_incrementalExecutionResults?: GraphQLExperimentalIncrementalExecutionResults; + stringifyResult: (value: FormattedExecutionResult) => string; } function defaultLogger(): Logger { @@ -332,6 +334,7 @@ export class ApolloServer { config.status400ForVariableCoercionErrors ?? false, __testing_incrementalExecutionResults: config.__testing_incrementalExecutionResults, + stringifyResult: config.stringifyResult ?? prettyJSONStringify, }; } diff --git a/packages/server/src/__tests__/ApolloServer.test.ts b/packages/server/src/__tests__/ApolloServer.test.ts index 0656e902644..d48a0cf0e6a 100644 --- a/packages/server/src/__tests__/ApolloServer.test.ts +++ b/packages/server/src/__tests__/ApolloServer.test.ts @@ -141,6 +141,42 @@ describe('ApolloServer construction', () => { // @ts-expect-error takesConfig({ modules: [] }); }); + describe('with configuration options', () => { + it('stringifyResult', async () => { + const server = new ApolloServer({ + typeDefs, + resolvers, + stringifyResult: (value: FormattedExecutionResult) => { + let result = JSON.stringify(value, null, 10000); + result = result.replace('world', 'stringifyResults works!'); // replace text with something custom + return result; + }, + }); + + await server.start(); + + const request = { + httpGraphQLRequest: { + method: 'POST', + headers: new HeaderMap([['content-type', 'application-json']]), + body: { query: '{ hello }' }, + search: '', + }, + context: async () => ({}), + }; + + const { body } = await server.executeHTTPGraphQLRequest(request); + assert(body.kind === 'complete'); + expect(body.string).toMatchInlineSnapshot(` + "{ + "data": { + "hello": "stringifyResults works!" + } + }" + `); + await server.stop(); + }); + }); }); const failToStartPlugin: ApolloServerPlugin = { diff --git a/packages/server/src/externalTypes/constructor.ts b/packages/server/src/externalTypes/constructor.ts index 7ab4addf8ef..ffd1cf6f783 100644 --- a/packages/server/src/externalTypes/constructor.ts +++ b/packages/server/src/externalTypes/constructor.ts @@ -8,6 +8,7 @@ import type { Logger } from '@apollo/utils.logger'; import type { IExecutableSchemaDefinition } from '@graphql-tools/schema'; import type { DocumentNode, + FormattedExecutionResult, GraphQLFieldResolver, GraphQLFormattedError, GraphQLSchema, @@ -88,7 +89,7 @@ interface ApolloServerOptionsBase { includeStacktraceInErrorResponses?: boolean; logger?: Logger; allowBatchedHttpRequests?: boolean; - + stringifyResult?: (value: FormattedExecutionResult) => string; introspection?: boolean; plugins?: ApolloServerPlugin[]; persistedQueries?: PersistedQueryOptions | false; diff --git a/packages/server/src/runHttpQuery.ts b/packages/server/src/runHttpQuery.ts index b47684c3ca5..a22df8aa2b2 100644 --- a/packages/server/src/runHttpQuery.ts +++ b/packages/server/src/runHttpQuery.ts @@ -260,7 +260,7 @@ export async function runHttpQuery({ ...graphQLResponse.http, body: { kind: 'complete', - string: prettyJSONStringify( + string: internals.stringifyResult( orderExecutionResultFields(graphQLResponse.body.singleResult), ), },