Response
Response module provides constructors and utilities for managing immutable interpretations of HTTP responses.
The Response Type
Section titled “The Response Type”A Response represents immutable and clonable HTTP Response data. It is a base element of the Response module.
import { import Response
Response } from 'fx-fetch';
type type Type = Response.Response
Type = import Response
Response.export Response
Represents immutable HTTP response.
Response;The Input Type
Section titled “The Input Type”A Response.Input represents all the possible inputs that can be used to create a Response.
Concrete types that make up the Input union:
import { import Response
Response } from 'fx-fetch';
type type Type = Response.Response | Response.Response.Parts | Response.Response.Options | Response
Type = import Response
Response.export Response
Represents immutable HTTP response.
Response.type Response.Input = Response.Response | Response.Response.Parts | Response.Response.Options | Response
Input;globalThis.Response— vanilla JS responseResponse.Response.Parts— Object with response partsResponse.Response— Existing Response can be used too
Constructors
Section titled “Constructors”unsafeMake
Section titled “unsafeMake”Creates a Response from any of Response.Input.
Throws an IllegalArgumentException if the provided input is invalid.
import { import Response
Response } from 'fx-fetch';
// ┌─── Response.Response// ▼const const response: Response.Response
response = import Response
Response.function unsafeMake(input: Response.Response.Input): Response.Responseexport unsafeMake
Creates a immutable Response object.
unsafeMake({ body: string
body: 'Hello, world!', status: number
status: 200,});Similar to unsafeMake, but returns an Option instead of throwing an error if the input is invalid.
If the input is invalid, it returns None. If valid, it returns Some containing the Response.
import { import Option
Option } from 'effect';import { import Response
Response } from 'fx-fetch';
// ┌─── Option.Option<Response.Response>// ▼const const response: Option.Option<Response.Response>
response = import Response
Response.function make(input: import("/home/runner/work/fx-fetch/fx-fetch/packages/fx-fetch/dist/Response/Response").Response.Input): Option.Option<Response.Response>export make
Creates a Response from the given input, returning None if the input is invalid.
make({ body: string
body: 'Hello, world!', status: number
status: 200,});from Response.Parts
Section titled “from Response.Parts”For creating a Response from an object Response.Parts use same functions make or unsafeMake.
The Parts type is super primitive. It’s basically an object with all the properties of a JS response, but with better DX.
Everything except the url is optional.
import { import Response
Response } from 'fx-fetch';
const const parts: Response.Response.Parts
parts: import Response
Response.export Response
Represents immutable HTTP response.
Response.type Response.Parts = { readonly body?: BodyInput; readonly headers?: HeadersInput; readonly redirected?: boolean; readonly status?: number; readonly statusText?: string; readonly type?: ResponseType; readonly url?: Url.Input;}
Parts = { body?: BodyInput
body: 'Hello, world!', headers?: HeadersInput
headers: { 'Content-Type': 'text/plain', 'X-Custom-Header': ['CustomValue', 'AnotherValue'], }, redirected?: boolean
redirected: false, status?: number
status: 200, statusText?: string
statusText: 'OK', type?: ResponseType
type: 'cors', url?: Url.Input
url: 'https://example.com/api',};
const const response: Response.Response
response = import Response
Response.function unsafeMake(input: Response.Response.Input): Response.Responseexport unsafeMake
Creates a immutable Response object.
unsafeMake(const parts: Response.Response.Parts
parts);Properties url and headers have flexible input types.
urlis of typeUrl.Input. Read more about it in Url module documentation.headerscan be almost anything what you can imagine as headers.- Record of strings
- Entries (array of tuples)
Mapof strings- Same as
HeadersInitin Fetch API - many more…
Reading body
Section titled “Reading body”readJson
Section titled “readJson”The readJson function reads the body of a Response and parses it as JSON.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<unknown, MalformedJsonError>// ▼const const payload: Effect<unknown, MalformedJsonError, never>
payload = import Response
Response.function readJson(response: Response.Response): Effect<unknown, MalformedJsonError, never>export readJson
Reads a JSON response.
readJson(const response: Response.Response
response);If you want a shortcut that combines fetching and reading JSON, use Fetch.fetchJson.
readText
Section titled “readText”The readText function reads the body of a Response and parses it as text.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<string, MalformedTextError>// ▼const const payload: Effect<string, MalformedTextError, never>
payload = import Response
Response.function readText(response: Response.Response): Effect<string, MalformedTextError, never>export readText
Reads a text response.
readText(const response: Response.Response
response);If you want a shortcut that combines fetching and reading text, use Fetch.fetchText.
readBlob
Section titled “readBlob”The readBlob function reads the body of a Response and parses it as a Blob.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<Blob, MalformedBlobError>// ▼const const payload: Effect<Blob, MalformedBlobError, never>
payload = import Response
Response.function readBlob(response: Response.Response): Effect<Blob, MalformedBlobError, never>export readBlob
Reads a Blob response.
readBlob(const response: Response.Response
response);If you want a shortcut that combines fetching and reading blob, use Fetch.fetchBlob.
readFormData
Section titled “readFormData”The readFormData function reads the body of a Response and parses it as form data.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<FormData, MalformedFormDataError>// ▼const const payload: Effect<FormData, MalformedFormDataError, never>
payload = import Response
Response.function readFormData(response: Response.Response): Effect<FormData, MalformedFormDataError, never>export readFormData
Reads a FormData response.
readFormData(const response: Response.Response
response);If you want a shortcut that combines fetching and reading form data, use Fetch.fetchFormData.
readBytes
Section titled “readBytes”The readBytes function reads the body of a Response and parses it as bytes.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<Uint8Array<ArrayBuffer>, MalformedBytesError>// ▼const const payload: Effect<Uint8Array<ArrayBufferLike>, MalformedBytesError, never>
payload = import Response
Response.function readBytes(response: Response.Response): Effect<Uint8Array<ArrayBufferLike>, MalformedBytesError, never>export readBytes
Reads a Bytes response.
readBytes(const response: Response.Response
response);If you want a shortcut that combines fetching and reading bytes, use Fetch.fetchBytes.
readArrayBuffer
Section titled “readArrayBuffer”The readArrayBuffer function reads the body of a Response and parses it as an ArrayBuffer.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<ArrayBuffer, MalformedArrayBufferError>// ▼const const payload: Effect<ArrayBuffer, MalformedArrayBufferError, never>
payload = import Response
Response.function readArrayBuffer(response: Response.Response): Effect<ArrayBuffer, MalformedArrayBufferError, never>export readArrayBuffer
Reads a ArrayBuffer response.
readArrayBuffer(const response: Response.Response
response);If you want a shortcut that combines fetching and reading bytes, use Fetch.fetchArrayBuffer.
readReadableStream
Section titled “readReadableStream”The readReadableStream function reads the body of a Response and parses it as a ReadableStream.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<// │ ReadableStream<Uint8Array<ArrayBuffer>>,// │ MalformedBytesError// │ >// ▼const const payload: Effect<ReadableStream<Uint8Array<ArrayBufferLike>>, MalformedReadableStreamError, never>
payload = import Response
Response.function readReadableStream(response: Response.Response): Effect<ReadableStream<Uint8Array<ArrayBufferLike>>, MalformedReadableStreamError, never>export readReadableStream
Reads a ReadableStream response.
readReadableStream(const response: Response.Response
response);If you want a shortcut that combines fetching and reading bytes, use Fetch.fetchReadableStream.
readJsonWithSchema
Section titled “readJsonWithSchema”The readJsonWithSchema function reads the body of a Response, parses it as JSON, and validates it against a provided schema.
import { import Schema
Schema } from 'effect';import { import Response
Response } from 'fx-fetch';
const const UserSchema: Schema.Struct<{ id: typeof Schema.Int; name: typeof Schema.String;}>
UserSchema = import Schema
Schema.function Struct<{ id: typeof Schema.Int; name: typeof Schema.String;}>(fields: { id: typeof Schema.Int; name: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.Int; name: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.Int
id: import Schema
Schema.class Int
Int, name: typeof Schema.String
name: import Schema
Schema.class Stringexport String
String,});
// ┌─── Effect<// │ typeof UserSchema.Type,// │ MalformedJsonError | ParseError// │ >// ▼const const payload: Effect<{ readonly id: number; readonly name: string;}, MalformedJsonError | ParseError, never>
payload = import Response
Response.readJsonWithSchema<{ readonly id: number; readonly name: string;}, { readonly id: number; readonly name: string;}, never>(response: Response.Response, schema: Schema.Schema<{ readonly id: number; readonly name: string;}, { readonly id: number; readonly name: string;}, never>): Effect<{ readonly id: number; readonly name: string;}, MalformedJsonError | ParseError, never> (+1 overload)export readJsonWithSchema
Reads a JSON response with the given schema.
readJsonWithSchema(const response: Response.Response
response, const UserSchema: Schema.Struct<{ id: typeof Schema.Int; name: typeof Schema.String;}>
UserSchema);readJsonWithStandardSchemaV1
Section titled “readJsonWithStandardSchemaV1”The readJsonWithStandardSchemaV1 function reads the body of a Response, parses it as JSON,
and validates it against a provided Standard Schema compatible schema.
This function works with any schema library that implements the Standard Schema specification, including Zod, Valibot, ArkType, and others.
import { Response } from 'fx-fetch';import { z } from 'zod';
const UserSchema = z.object({ id: z.number(), name: z.string(),});
// ┌─── Effect.Effect<// │ { id: number; name: string },// │ MalformedJsonError | ParseError// │ >// ▼const payload = Response.readJsonWithStandardSchemaV1(response, UserSchema);readStream
Section titled “readStream”The readStream function reads the body of a Response and parses it as an Effect Stream.
import { import Response
Response } from 'fx-fetch';// ┌─── Effect<// │ Stream<Uint8Array<ArrayBufferLike>, MyError>,// │ MalformedReadableStreamError// │ >// ▼const const payload: Effect<Stream<Uint8Array<ArrayBufferLike>, MyError, never>, MalformedReadableStreamError, never>
payload = import Response
Response.readStream<MyError>(response: Response.Response, options: Options<MyError>): Effect<Stream<Uint8Array<ArrayBufferLike>, MyError, never>, MalformedReadableStreamError, never> (+1 overload)export readStream
Reads a ReadableStream response.
readStream(const response: Response.Response
response, { onError: (error: unknown) => MyError
onError: (err: unknown
err) => new constructor MyError<{}>(args: void): MyError
MyError(), releaseLockOnEnd?: boolean | undefined
releaseLockOnEnd: true, // optional});Errors
Section titled “Errors”NotOkError
Section titled “NotOkError”A NotOkError represents an error that occurs when a Response has a non-OK status code.
The error contains the following properties:
response- TheResponsethat caused the error.reason- A string indicating the category of the error based on the status code.'informational'for status codes 100-199'redirection'for status codes 300-399'client-error'for status codes 400-499'server-error'for status codes 500-599
import { import Response
Response } from 'fx-fetch';
function function fn(error: Response.NotOkError): void
fn(error: Response.NotOkError
error: import Response
Response.class NotOkError
Thrown if the response is not OK. So the status code is not in the range 200-299.
NotOkError) { error: Response.NotOkError
error.response: Response.Response
response; // ◀︎── Response.Response error: Response.NotOkError
error.reason: "client-error" | "informational" | "redirection" | "server-error"
reason; // ◀︎── 'client-error' | 'informational' | 'redirection' | 'server-error'}Catching Errors
Section titled “Catching Errors”notOkEither
Section titled “notOkEither”Encapsulates both success Response and NotOkError failure of an Effect into an Either type of Response.
Transforms an Effect<Response, NotOkError> into an Effect<Either<Response, Response>>.
import { import Effect
Effect, import Either
Either } from 'effect';import { import Fetch
Fetch, import Request
Request, import Response
Response } from 'fx-fetch';
// ┌─── Effect.Effect<// │ void,// │ | Fetch.FetchError// │ | Fetch.AbortError// │ | Fetch.NotAllowedError// │ Fetch.Fetch// │ >// ▼const const program: Effect.Effect<void, Fetch.AbortError | Fetch.FetchError | Fetch.NotAllowedError, Fetch.Fetch>
program = import Effect
Effect.const gen: <YieldWrap<Effect.Effect<Either.Either<Response.Response, Response.Response>, Fetch.AbortError | Fetch.FetchError | Fetch.NotAllowedError, Fetch.Fetch>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Either.Either<Response.Response, Response.Response>, Fetch.AbortError | Fetch.FetchError | Fetch.NotAllowedError, Fetch.Fetch>>, void, never>) => Effect.Effect<...> (+1 overload)
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
Effect.gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
Example
import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = ( total: number, discountRate: number): Effect.Effect<number, Error> => discountRate === 0 ? Effect.fail(new Error("Discount rate cannot be zero")) : Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () { const transactionAmount = yield* fetchTransactionAmount const discountRate = yield* fetchDiscountRate const discountedAmount = yield* applyDiscount( transactionAmount, discountRate ) const finalAmount = addServiceCharge(discountedAmount) return `Final amount to charge: ${finalAmount}`})
gen(function* () { const const request: Request.Request
request = import Request
Request.function unsafeMake(input: Request.Request.Input): Request.Requestexport unsafeMake
Creates a immutable Request object. Throws an error if the input is invalid.
unsafeMake({ url: string
url: './my-endpoint' });
// ┌─── Either.Either< // │ Response.Response, // Ok response 200-399 // │ Response.Response // NotOk response 400-599 // │ > // ▼ const const result: Either.Either<Response.Response, Response.Response>
result = yield* import Fetch
Fetch.function fetch(request: Request.Request): Effect.Effect<Response.Response, Fetch.Fetch.ErrorType, Fetch.Fetch>export fetch
fetch(const request: Request.Request
request).Pipeable.pipe<Effect.Effect<Response.Response, Fetch.Fetch.ErrorType, Fetch.Fetch>, Effect.Effect<Either.Either<Response.Response, Response.Response>, Fetch.AbortError | Fetch.FetchError | Fetch.NotAllowedError, Fetch.Fetch>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Response.Response, Fetch.Fetch.ErrorType, Fetch.Fetch>) => Effect.Effect<Either.Either<Response.Response, Response.Response>, Fetch.AbortError | Fetch.FetchError | Fetch.NotAllowedError, Fetch.Fetch>): Effect.Effect<...> (+21 overloads)
pipe( import Response
Response.function notOkEither<E, R>(self: Effect.Effect<Response.Response, E | Response.NotOkError, R>): Effect.Effect<Either.Either<Response.Response, Response.Response>, E, R>export notOkEither
Encapsulates both success Response and NotOkError failure of an Effect into an Either type of Response.
notOkEither );});