import { err, ok, Result, ResultAsync } from 'neverthrow'; import { ClientErrors, ErrorCodes, ErrorWithCode, newError, } from '../types/errors'; export const safeDecode = ResultAsync.fromThrowable( (response: Response) => response.json() as Promise, (error): ErrorWithCode => newError('DecodeError', 'Unable to decode response', { error, }), ); export const safeFetch = async ( input: string | URL | globalThis.Request, init?: RequestInit, ): Promise>> => { const response = await fetch(input, init); if (!response.ok) { const notOkDecodeResult = await safeDecode>(response); if (notOkDecodeResult.isErr()) { return err(notOkDecodeResult.error); } return err(notOkDecodeResult.value); } const okDecodeResult = await safeDecode(response); if (okDecodeResult.isErr()) { return err(okDecodeResult.error); } return ok(okDecodeResult.value); };