@apollo/client
Version:
A fully-featured caching GraphQL client.
97 lines • 3.25 kB
JavaScript
import { DeepMerger, hasDirectives, isNonEmptyArray, } from "@apollo/client/utilities/internal";
class DeferRequest {
hasNext = true;
errors = [];
extensions = {};
data = {};
mergeIn(normalized, merger) {
if (normalized.data !== undefined) {
this.data = merger.merge(this.data, normalized.data);
}
if (normalized.errors) {
this.errors.push(...normalized.errors);
}
Object.assign(this.extensions, normalized.extensions);
}
handle(
// we'll get `undefined` here in case of a `no-cache` fetch policy,
// so we'll continue with the last value this request had accumulated
cacheData = this.data, chunk) {
this.hasNext = chunk.hasNext;
this.data = cacheData;
this.mergeIn(chunk, new DeepMerger());
if (hasIncrementalChunks(chunk)) {
const merger = new DeepMerger();
for (const incremental of chunk.incremental) {
let { data, path, errors, extensions } = incremental;
if (data && path) {
for (let i = path.length - 1; i >= 0; --i) {
const key = path[i];
const isNumericKey = !isNaN(+key);
const parent = isNumericKey ? [] : {};
parent[key] = data;
data = parent;
}
}
this.mergeIn({
errors,
extensions,
data: data ? data : undefined,
}, merger);
}
}
const result = { data: this.data };
if (isNonEmptyArray(this.errors)) {
result.errors = this.errors;
}
if (Object.keys(this.extensions).length > 0) {
result.extensions = this.extensions;
}
return result;
}
}
/**
* This handler implements the `@defer` directive as specified in this historical commit:
* https://github.com/graphql/graphql-spec/tree/48cf7263a71a683fab03d45d309fd42d8d9a6659/spec
*/
export class Defer20220824Handler {
isIncrementalResult(result) {
return "hasNext" in result;
}
extractErrors(result) {
const acc = [];
const push = ({ errors, }) => {
if (errors) {
acc.push(...errors);
}
};
if (this.isIncrementalResult(result)) {
push(result);
if (hasIncrementalChunks(result)) {
result.incremental.forEach(push);
}
}
if (acc.length) {
return acc;
}
}
prepareRequest(request) {
if (hasDirectives(["defer"], request.query)) {
const context = request.context ?? {};
const http = (context.http ??= {});
http.accept = [
"multipart/mixed;deferSpec=20220824",
...(http.accept || []),
];
}
return request;
}
startRequest(_) {
return new DeferRequest();
}
}
// only exported for use in tests
export function hasIncrementalChunks(result) {
return isNonEmptyArray(result.incremental);
}
//# sourceMappingURL=defer20220824.js.map