@usekana/client-kana-js
Version:
Kana frontend JavaScript client
67 lines (55 loc) • 1.77 kB
text/typescript
import {
AuthenticationError,
FeatureNotFoundError,
NetworkError,
} from './errors';
import { RequestResult } from './types';
import { ClientError } from 'graphql-request';
import { KanaGroupClientFullConfig } from './KanaGroupClientConfig';
export async function request<T, E>(
config: KanaGroupClientFullConfig,
call: () => Promise<T>,
): Promise<RequestResult<T, E>> {
for (let i = 1; i < Number.MAX_SAFE_INTEGER; i++) {
try {
const data = await call();
return { data };
} catch (error: any) {
const knownError = formatError(error);
if (config.retry && config.retry(knownError, i)) {
continue;
}
if (config.onError) {
await config.onError(knownError);
}
return { error: knownError };
}
}
throw new Error('this line should not be called, internal error');
}
const knownErrors = [AuthenticationError, NetworkError, FeatureNotFoundError];
const knownErrorsMap: any = {};
for (const err of knownErrors) {
knownErrorsMap[err.name] = err;
}
function formatError(error: Error) {
if ((error as any).code === 'ECONNREFUSED') {
return new NetworkError('No network connection.');
}
if (error instanceof ClientError) {
const firstGraphQLError = error.response?.errors?.length
? error.response?.errors[0]
: undefined;
if (firstGraphQLError?.message?.startsWith('Unauthenticated')) {
return new AuthenticationError(firstGraphQLError.message);
}
if (firstGraphQLError?.extensions?.exception) {
const exp = firstGraphQLError.extensions.exception as any;
const knownErrorType = knownErrorsMap[exp.name ?? ''];
if (knownErrorType) {
return new knownErrorType(exp.message);
}
}
}
return error;
}