import { AuthenticationError, FeatureNotFoundError, NetworkError, } from './errors'; import { RequestResult } from './types'; import { ClientError } from 'graphql-request'; import { KanaGroupClientFullConfig } from './KanaGroupClientConfig'; export async function request( config: KanaGroupClientFullConfig, call: () => Promise, ): Promise> { 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; }