@kiwicom/smart-faq
Version:
Smart FAQ
124 lines (104 loc) • 2.83 kB
JavaScript
// @noflow
import {
Environment,
Network,
RecordSource,
Store,
QueryResponseCache,
} from 'relay-runtime';
import idx from 'idx';
import * as fallbacks from "../../fallbacks/"; // eslint-disable-line
import { DEFAULT_LOCALE } from '../helpers/translationUtils';
require('isomorphic-fetch');
// used when smart FAQ installed as dependency
const uri = 'https://graphql.kiwi.com';
const cache = new QueryResponseCache({ size: 200, ttl: 30 * 60 * 1000 });
export const ERROR_FORBIDDEN = 'Forbidden 403';
const getFallbackData = (error, operation) => {
if (operation.name in fallbacks) {
return fallbacks[operation.name];
} else {
throw error;
}
};
const handleForbiddenError = json => {
if (
json.errors &&
json.errors.length > 0 &&
json.errors.some(
error => idx(error, _ => _.extensions.proxy.statusCode) === '403',
)
) {
throw new Error(ERROR_FORBIDDEN);
}
};
const composeRequestBody = (operation, variables) =>
JSON.stringify({
query: operation.text, // GraphQL text from input
variables,
operationName: operation.name,
});
const composeRequest = (headers, operation, variables) => {
const body = composeRequestBody(operation, variables);
return [
process.env.GRAPHQL_URI || uri,
{
method: 'POST',
headers,
body,
},
];
};
export async function fetchQuery(headers, operation, variables) {
let fallbackData = null;
let response = null;
try {
response = await fetch(...composeRequest(headers, operation, variables));
} catch (error) {
fallbackData = getFallbackData(error, operation);
}
let json = fallbackData;
if (!json) {
json = await response.json();
}
handleForbiddenError(json);
return json;
}
const buildQueryFetcher = (
token: string = '',
kwAuthToken: string = '',
locale: string = DEFAULT_LOCALE,
) => {
return async (operation, variables, cacheConfig) => {
const forceFetch = cacheConfig.force;
const isQuery = operation.operationKind === 'query';
if (!forceFetch && isQuery) {
const cachedData = cache.get(operation.text, variables);
if (cachedData) {
return cachedData;
}
}
const headers = {
'Content-Type': 'application/json',
'Accept-Language': locale,
'KW-Auth-Token': kwAuthToken,
Authorization: token,
};
const json = await fetchQuery(headers, operation, variables);
if (!forceFetch && isQuery) {
cache.set(operation.text, variables, json);
}
return json;
};
};
const createEnvironment = (
token: ?string,
kwAuthToken: ?string,
locale: ?string,
) => {
return new Environment({
network: Network.create(buildQueryFetcher(token, kwAuthToken, locale)),
store: new Store(new RecordSource()),
});
};
export default createEnvironment;