import { FutureResult } from '@ephox/katamari'; import * as Http from './Http'; import type { ResponseBodyDataTypes, ResponseType, ResponseTypeMap } from './HttpData'; import { type HttpError, HttpErrorCode } from './HttpError'; import type { GetDelInit, HttpRequest, JwtToken, JwtTokenFactory, PostPutInit } from './HttpTypes'; const headers = (headersInput: HttpRequest['headers'], token: string) => { const authHeader = { Authorization: 'Bearer ' + token }; return headersInput ? { ...headersInput, ...authHeader } : authHeader; }; type RunMethod = (token: JwtToken) => FutureResult>; const requestFreshToken = (tokenFactory: JwtTokenFactory): FutureResult> => tokenFactory(true); const requestCachedToken = (tokenFactory: JwtTokenFactory): FutureResult> => tokenFactory(false); const tryAgain = (tokenFactory: JwtTokenFactory, runMethod: RunMethod) => (error: HttpError) => error.status === HttpErrorCode.Unauthorized ? requestFreshToken(tokenFactory).bindFuture(runMethod) : FutureResult.error(error); const runWithToken = (runMethod: RunMethod, tokenFactory: JwtTokenFactory): FutureResult> => requestCachedToken(tokenFactory).bindFuture( (token) => runMethod(token).bind((result) => result.fold(tryAgain(tokenFactory, runMethod), FutureResult.pure)) ); export const post = (init: PostPutInit, tokenFactory: JwtTokenFactory): FutureResult> => runWithToken((token) => Http.post({ ...init, headers: headers(init.headers, token) }), tokenFactory); export const put = (init: PostPutInit, tokenFactory: JwtTokenFactory): FutureResult> => runWithToken((token) => Http.put({ ...init, headers: headers(init.headers, token) }), tokenFactory); export const get = (init: GetDelInit, tokenFactory: JwtTokenFactory): FutureResult> => runWithToken((token) => Http.get({ ...init, headers: headers(init.headers, token) }), tokenFactory); export const del = (init: GetDelInit, tokenFactory: JwtTokenFactory): FutureResult> => runWithToken((token) => Http.del({ ...init, headers: headers(init.headers, token) }), tokenFactory);