Reorganization. Split remote/result/request. Split picsum specific api.
This commit is contained in:
parent
5f9bdd5511
commit
c3c629943c
6 changed files with 550 additions and 532 deletions
71
src/request.ts
Normal file
71
src/request.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import { z } from "zod"
|
||||
import { Result } from "./result"
|
||||
|
||||
// === Request Errors ===
|
||||
export type RequestError =
|
||||
| { tag: "networkError"; error: unknown }
|
||||
| { tag: "httpError"; status: number; statusText: string }
|
||||
| { tag: "jsonParseError"; error: unknown }
|
||||
| { tag: "invalidResponse"; error: z.ZodError }
|
||||
|
||||
export const RequestError = {
|
||||
toString(error: RequestError): string {
|
||||
switch (error.tag) {
|
||||
case "networkError":
|
||||
return "Network error. Check your connection and try again."
|
||||
case "httpError":
|
||||
return `Server returned ${String(error.status)} ${error.statusText}.`
|
||||
case "jsonParseError":
|
||||
return "The server returned an invalid response."
|
||||
case "invalidResponse":
|
||||
return "The image data had an unexpected format."
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// === Generic safe fetch functions ===
|
||||
export async function fetchJsonSafe(url: string): Promise<Result<unknown, RequestError>> {
|
||||
let response: Response
|
||||
try {
|
||||
response = await fetch(url)
|
||||
} catch (error: unknown) {
|
||||
return Result.err({ tag: "networkError", error })
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return Result.err({
|
||||
tag: "httpError",
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
})
|
||||
} else {
|
||||
try {
|
||||
const json: unknown = await response.json()
|
||||
return Result.ok(json)
|
||||
} catch (error: unknown) {
|
||||
return Result.err({ tag: "jsonParseError", error })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assumes `f` is some sort of a zod parsing function that may throw `z.ZodError`
|
||||
export async function fetchJsonSafeWith<A>(
|
||||
url: string,
|
||||
f: (json: unknown) => A,
|
||||
): Promise<Result<A, RequestError>> {
|
||||
const result = await fetchJsonSafe(url)
|
||||
switch (result.tag) {
|
||||
case "error":
|
||||
return Result.err(result.error)
|
||||
case "ok":
|
||||
try {
|
||||
return Result.ok(f(result.value))
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return Result.err({ tag: "invalidResponse", error })
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue