Skip to content

Instantly share code, notes, and snippets.

@patroza
Forked from ColemanGariety/fetch.ts
Last active April 5, 2020 20:50
Show Gist options
  • Save patroza/dc5436d07bd574c8661654beac1e4a43 to your computer and use it in GitHub Desktop.
Save patroza/dc5436d07bd574c8661654beac1e4a43 to your computer and use it in GitHub Desktop.
import * as TE from "fp-ts/lib/TaskEither"
import { pipe } from "fp-ts/lib/pipeable"
import { Do } from "fp-ts-contrib/lib/Do"
type Error1 = { errors: object[]; type: "1" }
type Error2 = { errors: object[]; response: Response; type: "2" }
type Error3 = { errors: object[]; result: unknown; type: "3" }
type Errors = Error1 | Error2 | Error3
export const post = (url: string, body: object) =>
Do(TE.taskEither)
.bind(
"response",
TE.tryCatch(
() =>
fetch(url, {
method: "POST",
body: JSON.stringify(body),
}),
(error) =>
({
errors: [error as object],
type: "1" as const,
} as Error1),
),
)
.bindL("result", ({ response }) =>
pipe(
TE.tryCatch(
() => response.json(),
(error) =>
({
response,
errors: [error as object],
type: "2",
} as Error2),
),
TE.mapLeft((err) => err as Errors),
TE.chain((result) => {
if (!response.ok) {
return TE.left({
result,
response,
errors: RA.cons(
`Got ${response.status} POSTing to ${url}`,
"errors" in result ? result.errors : [],
),
})
}
return TE.right(result)
}),
),
)
.return(({ result }) => result)
@patroza
Copy link
Author

patroza commented Apr 5, 2020

Disclaimer: I do not recommend to write a fetch function like this ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment