UNPKG

graphql-yoga

Version:
87 lines (86 loc) • 3.54 kB
import { getOperationAST } from 'graphql'; import { handleMaybePromise, iterateAsync } from '@whatwg-node/promise-helpers'; import { getIncrementalSpecForRequest } from './plugins/result-processor/accept.js'; export function processResult({ request, result, fetchAPI, onResultProcessHooks, serverContext, }) { const log = serverContext.log; let resultProcessor; const acceptableMediaTypes = []; let acceptedMediaType = '*/*'; return handleMaybePromise(() => iterateAsync(onResultProcessHooks, onResultProcessHook => { log.debug('Running onResultProcess hook'); return onResultProcessHook({ request, acceptableMediaTypes, result, setResult(newResult) { result = newResult; }, resultProcessor, setResultProcessor(newResultProcessor, newAcceptedMimeType) { resultProcessor = newResultProcessor; acceptedMediaType = newAcceptedMimeType; }, serverContext, }); }), () => { // If no result processor found for this result, return an error if (!resultProcessor) { log.debug({ accept: request.headers.get('accept'), acceptableMediaTypes }, 'No result processor matched, responding 406'); const response = new fetchAPI.Response(null, { status: 406, statusText: 'Not Acceptable', headers: { accept: acceptableMediaTypes.join('; charset=utf-8, '), }, }); log.debug({ status: response.status }, 'Sending response'); return response; } log.debug({ acceptedMediaType }, 'Result processor selected'); return handleMaybePromise(() => resultProcessor(result, fetchAPI, acceptedMediaType), response => { log.debug({ status: response.status }, 'Sending response'); return response; }); }); } export function processRequest({ params, enveloped, request, log, onOperationType, }) { // Parse GraphQLParams let document; try { document = enveloped.parse(params.query); } catch (err) { log.debug({ err }, 'Parsing failed'); throw err; } // Get the actual operation const operation = getOperationAST(document, params.operationName); onOperationType?.(operation?.operation); log.debug({ operationType: operation?.operation }, 'Parsed GraphQL document'); // Validate parsed Document Node const errors = enveloped.validate(enveloped.schema, document); if (errors.length > 0) { log.debug({ errors }, 'Validation failed'); return { errors }; } // Build the context for the execution return handleMaybePromise(() => enveloped.contextFactory(), contextValue => { const executionArgs = { schema: enveloped.schema, document, contextValue, variableValues: params.variables, operationName: params.operationName, }; if (request) { const incrementalSpec = getIncrementalSpecForRequest(request); if (incrementalSpec) { executionArgs.incrementalSpec = incrementalSpec; } } // Choose the right executor const executeFn = operation?.operation === 'subscription' ? enveloped.subscribe : enveloped.execute; // Get the result to be processed return executeFn(executionArgs); }); }