react-relay-network-modern
Version:
Network Layer for React Relay and Express (Batch Queries, AuthToken, Logging, Retry)
68 lines (54 loc) • 1.94 kB
Flow
// @flow
/* eslint-disable no-console */
import type { Middleware, RelayRequestAny, MiddlewareNextFn } from '../definition';
import type RelayResponse from '../RelayResponse';
type PersistedQueriesMiddlewareOptions = {| hash: string |};
async function makePersistedQueryRequestWithFallback(
o: {
req: RelayRequestAny,
next: MiddlewareNextFn,
options?: PersistedQueriesMiddlewareOptions,
},
original = false,
hasRunFallback: boolean = false
): Promise<RelayResponse> {
const makeFallback = async (prevError: Error) => {
if (hasRunFallback) {
throw prevError;
}
return makePersistedQueryRequestWithFallback(o, true, true);
};
const makeRequest = async () => {
try {
// We make a new duplicate request and see if the backend is able to
// process it
// If the backend rejects it we fallback to the original request (which has the text query)
const persistedQueriesReq = JSON.parse(JSON.stringify(o.req));
const { cacheID, id, text: queryText } = persistedQueriesReq.operation;
const queryId = id || cacheID;
if (!queryId && (!o.options?.hash || !queryText)) {
throw new Error('Either query id or hashing function & query must be defined!');
}
// Add doc_id to the request and remove the query text
const body = JSON.parse(persistedQueriesReq.fetchOpts.body);
delete body.query;
body.doc_id = queryId;
persistedQueriesReq.fetchOpts.body = JSON.stringify(body);
delete persistedQueriesReq.operation.text;
return await o.next(original ? o.req : persistedQueriesReq);
} catch (e) {
return makeFallback(e);
}
};
return makeRequest();
}
export default function persistedQueriesMiddleware(
options?: PersistedQueriesMiddlewareOptions
): Middleware {
return (next) => (req) =>
makePersistedQueryRequestWithFallback({
req,
next,
options,
});
}