@graphql-tools/url-loader
Version:
A set of utils for faster development of GraphQL tools
54 lines (53 loc) • 2.07 kB
JavaScript
import { meros as merosIncomingMessage } from 'meros/node';
import { meros as merosReadableStream } from 'meros/browser';
import { mapAsyncIterator } from '@graphql-tools/utils';
import { dset } from 'dset/merge';
import { addCancelToResponseStream } from './event-stream/addCancelToResponseStream.js';
function isIncomingMessage(body) {
return body != null && typeof body === 'object' && 'pipe' in body;
}
export async function handleMultipartMixedResponse(response, controller) {
const body = await response.body;
const contentType = response.headers.get('content-type') || '';
let asyncIterator;
if (isIncomingMessage(body)) {
// Meros/node expects headers as an object map with the content-type prop
body.headers = {
'content-type': contentType,
};
// And it expects `IncomingMessage` and `node-fetch` returns `body` as `Promise<PassThrough>`
asyncIterator = (await merosIncomingMessage(body));
}
else {
// Nothing is needed for regular `Response`.
asyncIterator = (await merosReadableStream(response));
}
const executionResult = {};
const resultStream = mapAsyncIterator(asyncIterator, (part) => {
if (part.json) {
const chunk = part.body;
if (chunk.path) {
if (chunk.data) {
const path = ['data'];
dset(executionResult, path.concat(chunk.path), chunk.data);
}
if (chunk.errors) {
executionResult.errors = (executionResult.errors || []).concat(chunk.errors);
}
}
else {
if (chunk.data) {
executionResult.data = chunk.data;
}
if (chunk.errors) {
executionResult.errors = chunk.errors;
}
}
return executionResult;
}
});
if (controller) {
return addCancelToResponseStream(resultStream, controller);
}
return resultStream;
}