/** * @since 1.0.0 */ import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type { RuntimeFiber } from "effect/Fiber" import type * as FiberRef from "effect/FiberRef" import type { Inspectable } from "effect/Inspectable" import type { Layer } from "effect/Layer" import type { Pipeable } from "effect/Pipeable" import type * as Predicate from "effect/Predicate" import type { Ref } from "effect/Ref" import type * as Schedule from "effect/Schedule" import type { Scope } from "effect/Scope" import type { NoExcessProperties, NoInfer } from "effect/Types" import type { Cookies } from "./Cookies.js" import type * as Error from "./HttpClientError.js" import type * as ClientRequest from "./HttpClientRequest.js" import type * as ClientResponse from "./HttpClientResponse.js" import * as internal from "./internal/httpClient.js" /** * @since 1.0.0 * @category type ids */ export const TypeId: unique symbol = internal.TypeId /** * @since 1.0.0 * @category type ids */ export type TypeId = typeof TypeId /** * @since 1.0.0 * @category models */ export interface HttpClient extends HttpClient.With {} /** * @since 1.0.0 */ export declare namespace HttpClient { /** * @since 1.0.0 * @category models */ export interface With extends Pipeable, Inspectable { readonly [TypeId]: TypeId readonly execute: ( request: ClientRequest.HttpClientRequest ) => Effect.Effect readonly get: ( url: string | URL, options?: ClientRequest.Options.NoBody ) => Effect.Effect readonly head: ( url: string | URL, options?: ClientRequest.Options.NoBody ) => Effect.Effect readonly post: ( url: string | URL, options?: ClientRequest.Options.NoUrl ) => Effect.Effect readonly patch: ( url: string | URL, options?: ClientRequest.Options.NoUrl ) => Effect.Effect readonly put: ( url: string | URL, options?: ClientRequest.Options.NoUrl ) => Effect.Effect readonly del: ( url: string | URL, options?: ClientRequest.Options.NoUrl ) => Effect.Effect readonly options: ( url: string | URL, options?: ClientRequest.Options.NoUrl ) => Effect.Effect } /** * @since 1.0.0 * @category models */ export type Preprocess = ( request: ClientRequest.HttpClientRequest ) => Effect.Effect /** * @since 1.0.0 * @category models */ export type Postprocess = ( request: Effect.Effect ) => Effect.Effect } /** * @since 1.0.0 * @category tags */ export const HttpClient: Context.Tag = internal.tag /** * @since 1.0.0 * @category accessors */ export const execute: ( request: ClientRequest.HttpClientRequest ) => Effect.Effect = internal.execute /** * @since 1.0.0 * @category accessors */ export const get: ( url: string | URL, options?: ClientRequest.Options.NoBody | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.get /** * @since 1.0.0 * @category accessors */ export const head: ( url: string | URL, options?: ClientRequest.Options.NoBody | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.head /** * @since 1.0.0 * @category accessors */ export const post: ( url: string | URL, options?: ClientRequest.Options.NoUrl | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.post /** * @since 1.0.0 * @category accessors */ export const patch: ( url: string | URL, options?: ClientRequest.Options.NoUrl | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.patch /** * @since 1.0.0 * @category accessors */ export const put: ( url: string | URL, options?: ClientRequest.Options.NoUrl | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.put /** * @since 1.0.0 * @category accessors */ export const del: ( url: string | URL, options?: ClientRequest.Options.NoUrl | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.del /** * @since 1.0.0 * @category accessors */ export const options: ( url: string | URL, options?: ClientRequest.Options.NoUrl | undefined ) => Effect.Effect< ClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient > = internal.options /** * @since 1.0.0 * @category error handling */ export const catchAll: { /** * @since 1.0.0 * @category error handling */ (f: (e: E) => Effect.Effect): (self: HttpClient.With) => HttpClient.With /** * @since 1.0.0 * @category error handling */ (self: HttpClient.With, f: (e: E) => Effect.Effect): HttpClient.With } = internal.catchAll /** * @since 1.0.0 * @category error handling */ export const catchTag: { /** * @since 1.0.0 * @category error handling */ ( tag: K, f: (e: Extract) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With, R1 | R> /** * @since 1.0.0 * @category error handling */ ( self: HttpClient.With, tag: K, f: (e: Extract) => Effect.Effect ): HttpClient.With, R1 | R> } = internal.catchTag /** * @since 1.0.0 * @category error handling */ export const catchTags: { /** * @since 1.0.0 * @category error handling */ < E, Cases extends & { [K in Extract["_tag"]]+?: ( error: Extract ) => Effect.Effect } & (unknown extends E ? {} : { [K in Exclude["_tag"]>]: never }) >(cases: Cases): ( self: HttpClient.With ) => HttpClient.With< | Exclude | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? E : never }[keyof Cases], | R | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? R : never }[keyof Cases] > /** * @since 1.0.0 * @category error handling */ < E extends { _tag: string }, R, Cases extends & { [K in Extract["_tag"]]+?: ( error: Extract ) => Effect.Effect } & (unknown extends E ? {} : { [K in Exclude["_tag"]>]: never }) >(self: HttpClient.With, cases: Cases): HttpClient.With< | Exclude | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? E : never }[keyof Cases], | R | { [K in keyof Cases]: Cases[K] extends (...args: Array) => Effect.Effect ? R : never }[keyof Cases] > } = internal.catchTags /** * Filters the result of a response, or runs an alternative effect if the predicate fails. * * @since 1.0.0 * @category filters */ export const filterOrElse: { /** * Filters the result of a response, or runs an alternative effect if the predicate fails. * * @since 1.0.0 * @category filters */ ( predicate: Predicate.Predicate, orElse: (response: ClientResponse.HttpClientResponse) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With /** * Filters the result of a response, or runs an alternative effect if the predicate fails. * * @since 1.0.0 * @category filters */ ( self: HttpClient.With, predicate: Predicate.Predicate, orElse: (response: ClientResponse.HttpClientResponse) => Effect.Effect ): HttpClient.With } = internal.filterOrElse /** * Filters the result of a response, or throws an error if the predicate fails. * * @since 1.0.0 * @category filters */ export const filterOrFail: { /** * Filters the result of a response, or throws an error if the predicate fails. * * @since 1.0.0 * @category filters */ ( predicate: Predicate.Predicate, orFailWith: (response: ClientResponse.HttpClientResponse) => E2 ): (self: HttpClient.With) => HttpClient.With /** * Filters the result of a response, or throws an error if the predicate fails. * * @since 1.0.0 * @category filters */ ( self: HttpClient.With, predicate: Predicate.Predicate, orFailWith: (response: ClientResponse.HttpClientResponse) => E2 ): HttpClient.With } = internal.filterOrFail /** * Filters responses by HTTP status code. * * @since 1.0.0 * @category filters */ export const filterStatus: { /** * Filters responses by HTTP status code. * * @since 1.0.0 * @category filters */ (f: (status: number) => boolean): (self: HttpClient.With) => HttpClient.With /** * Filters responses by HTTP status code. * * @since 1.0.0 * @category filters */ (self: HttpClient.With, f: (status: number) => boolean): HttpClient.With } = internal.filterStatus /** * Filters responses that return a 2xx status code. * * @since 1.0.0 * @category filters */ export const filterStatusOk: (self: HttpClient.With) => HttpClient.With = internal.filterStatusOk /** * @since 1.0.0 * @category constructors */ export const makeWith: ( postprocess: ( request: Effect.Effect ) => Effect.Effect, preprocess: HttpClient.Preprocess ) => HttpClient.With = internal.makeWith /** * @since 1.0.0 * @category constructors */ export const make: ( f: ( request: ClientRequest.HttpClientRequest, url: URL, signal: AbortSignal, fiber: RuntimeFiber ) => Effect.Effect ) => HttpClient = internal.make /** * @since 1.0.0 * @category mapping & sequencing */ export const transform: { /** * @since 1.0.0 * @category mapping & sequencing */ ( f: ( effect: Effect.Effect, request: ClientRequest.HttpClientRequest ) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With /** * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: ( effect: Effect.Effect, request: ClientRequest.HttpClientRequest ) => Effect.Effect ): HttpClient.With } = internal.transform /** * @since 1.0.0 * @category mapping & sequencing */ export const transformResponse: { /** * @since 1.0.0 * @category mapping & sequencing */ ( f: ( effect: Effect.Effect ) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With /** * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: ( effect: Effect.Effect ) => Effect.Effect ): HttpClient.With } = internal.transformResponse /** * Appends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ export const mapRequest: { /** * Appends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ (f: (a: ClientRequest.HttpClientRequest) => ClientRequest.HttpClientRequest): (self: HttpClient.With) => HttpClient.With /** * Appends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (a: ClientRequest.HttpClientRequest) => ClientRequest.HttpClientRequest ): HttpClient.With } = internal.mapRequest /** * Appends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ export const mapRequestEffect: { /** * Appends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( f: (a: ClientRequest.HttpClientRequest) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With /** * Appends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (a: ClientRequest.HttpClientRequest) => Effect.Effect ): HttpClient.With } = internal.mapRequestEffect /** * Prepends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ export const mapRequestInput: { /** * Prepends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ (f: (a: ClientRequest.HttpClientRequest) => ClientRequest.HttpClientRequest): (self: HttpClient.With) => HttpClient.With /** * Prepends a transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (a: ClientRequest.HttpClientRequest) => ClientRequest.HttpClientRequest ): HttpClient.With } = internal.mapRequestInput /** * Prepends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ export const mapRequestInputEffect: { /** * Prepends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( f: (a: ClientRequest.HttpClientRequest) => Effect.Effect ): (self: HttpClient.With) => HttpClient.With /** * Prepends an effectful transformation of the request object before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (a: ClientRequest.HttpClientRequest) => Effect.Effect ): HttpClient.With } = internal.mapRequestInputEffect /** * @since 1.0.0 * @category error handling */ export declare namespace Retry { /** * @since 1.0.0 * @category error handling */ export type Return, O>> = HttpClient.With< | (O extends { schedule: Schedule.Schedule } ? E : O extends { until: Predicate.Refinement } ? E2 : E) | (O extends { while: (...args: Array) => Effect.Effect } ? E : never) | (O extends { until: (...args: Array) => Effect.Effect } ? E : never), | R | (O extends { schedule: Schedule.Schedule } ? R : never) | (O extends { while: (...args: Array) => Effect.Effect } ? R : never) | (O extends { until: (...args: Array) => Effect.Effect } ? R : never) > extends infer Z ? Z : never } /** * Retries the request based on a provided schedule or policy. * * @since 1.0.0 * @category error handling */ export const retry: { /** * Retries the request based on a provided schedule or policy. * * @since 1.0.0 * @category error handling */ , O>>(options: O): (self: HttpClient.With) => Retry.Return /** * Retries the request based on a provided schedule or policy. * * @since 1.0.0 * @category error handling */ (policy: Schedule.Schedule, R1>): (self: HttpClient.With) => HttpClient.With /** * Retries the request based on a provided schedule or policy. * * @since 1.0.0 * @category error handling */ , O>>(self: HttpClient.With, options: O): Retry.Return /** * Retries the request based on a provided schedule or policy. * * @since 1.0.0 * @category error handling */ (self: HttpClient.With, policy: Schedule.Schedule): HttpClient.With } = internal.retry /** * Retries common transient errors, such as rate limiting, timeouts or network issues. * * Specifying a `while` predicate allows you to consider other errors as * transient. * * @since 1.0.0 * @category error handling */ export const retryTransient: { /** * Retries common transient errors, such as rate limiting, timeouts or network issues. * * Specifying a `while` predicate allows you to consider other errors as * transient. * * @since 1.0.0 * @category error handling */ < B, E, R1 = never, const Mode extends "errors-only" | "response-only" | "both" = never, Input = "errors-only" extends Mode ? E : "response-only" extends Mode ? ClientResponse.HttpClientResponse : ClientResponse.HttpClientResponse | E >( options: { readonly mode?: Mode | undefined readonly while?: Predicate.Predicate> readonly schedule?: Schedule.Schedule, R1> readonly times?: number } | Schedule.Schedule, R1> ): (self: HttpClient.With) => HttpClient.With /** * Retries common transient errors, such as rate limiting, timeouts or network issues. * * Specifying a `while` predicate allows you to consider other errors as * transient. * * @since 1.0.0 * @category error handling */ < E, R, B, R1 = never, const Mode extends "errors-only" | "response-only" | "both" = never, Input = "errors-only" extends Mode ? E : "response-only" extends Mode ? ClientResponse.HttpClientResponse : ClientResponse.HttpClientResponse | E >( self: HttpClient.With, options: { readonly mode?: Mode | undefined readonly while?: Predicate.Predicate> readonly schedule?: Schedule.Schedule, R1> readonly times?: number } | Schedule.Schedule, R1> ): HttpClient.With } = internal.retryTransient /** * Performs an additional effect after a successful request. * * @since 1.0.0 * @category mapping & sequencing */ export const tap: { /** * Performs an additional effect after a successful request. * * @since 1.0.0 * @category mapping & sequencing */ <_, E2, R2>( f: (response: ClientResponse.HttpClientResponse) => Effect.Effect<_, E2, R2> ): (self: HttpClient.With) => HttpClient.With /** * Performs an additional effect after a successful request. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (response: ClientResponse.HttpClientResponse) => Effect.Effect<_, E2, R2> ): HttpClient.With } = internal.tap /** * Performs an additional effect after an unsuccessful request. * * @since 1.0.0 * @category mapping & sequencing */ export const tapError: { /** * Performs an additional effect after an unsuccessful request. * * @since 1.0.0 * @category mapping & sequencing */ <_, E, E2, R2>(f: (e: NoInfer) => Effect.Effect<_, E2, R2>): (self: HttpClient.With) => HttpClient.With /** * Performs an additional effect after an unsuccessful request. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (e: NoInfer) => Effect.Effect<_, E2, R2> ): HttpClient.With } = internal.tapError /** * Performs an additional effect on the request before sending it. * * @since 1.0.0 * @category mapping & sequencing */ export const tapRequest: { /** * Performs an additional effect on the request before sending it. * * @since 1.0.0 * @category mapping & sequencing */ <_, E2, R2>(f: (a: ClientRequest.HttpClientRequest) => Effect.Effect<_, E2, R2>): (self: HttpClient.With) => HttpClient.With /** * Performs an additional effect on the request before sending it. * * @since 1.0.0 * @category mapping & sequencing */ ( self: HttpClient.With, f: (a: ClientRequest.HttpClientRequest) => Effect.Effect<_, E2, R2> ): HttpClient.With } = internal.tapRequest /** * Associates a `Ref` of cookies with the client for handling cookies across requests. * * @since 1.0.0 * @category cookies */ export const withCookiesRef: { /** * Associates a `Ref` of cookies with the client for handling cookies across requests. * * @since 1.0.0 * @category cookies */ (ref: Ref): (self: HttpClient.With) => HttpClient.With /** * Associates a `Ref` of cookies with the client for handling cookies across requests. * * @since 1.0.0 * @category cookies */ (self: HttpClient.With, ref: Ref): HttpClient.With } = internal.withCookiesRef /** * Follows HTTP redirects up to a specified number of times. * * @since 1.0.0 * @category redirects */ export const followRedirects: { /** * Follows HTTP redirects up to a specified number of times. * * @since 1.0.0 * @category redirects */ (maxRedirects?: number | undefined): (self: HttpClient.With) => HttpClient.With /** * Follows HTTP redirects up to a specified number of times. * * @since 1.0.0 * @category redirects */ (self: HttpClient.With, maxRedirects?: number | undefined): HttpClient.With } = internal.followRedirects /** * @since 1.0.0 * @category Tracing */ export const currentTracerDisabledWhen: FiberRef.FiberRef> = internal.currentTracerDisabledWhen /** * Disables tracing for specific requests based on a provided predicate. * * @since 1.0.0 * @category Tracing */ export const withTracerDisabledWhen: { /** * Disables tracing for specific requests based on a provided predicate. * * @since 1.0.0 * @category Tracing */ (predicate: Predicate.Predicate): (self: HttpClient.With) => HttpClient.With /** * Disables tracing for specific requests based on a provided predicate. * * @since 1.0.0 * @category Tracing */ ( self: HttpClient.With, predicate: Predicate.Predicate ): HttpClient.With } = internal.withTracerDisabledWhen /** * @since 1.0.0 * @category Tracing */ export const currentTracerPropagation: FiberRef.FiberRef = internal.currentTracerPropagation /** * Enables or disables tracing propagation for the request. * * @since 1.0.0 * @category Tracing */ export const withTracerPropagation: { /** * Enables or disables tracing propagation for the request. * * @since 1.0.0 * @category Tracing */ (enabled: boolean): (self: HttpClient.With) => HttpClient.With /** * Enables or disables tracing propagation for the request. * * @since 1.0.0 * @category Tracing */ (self: HttpClient.With, enabled: boolean): HttpClient.With } = internal.withTracerPropagation /** * @since 1.0.0 */ export const layerMergedContext: ( effect: Effect.Effect ) => Layer = internal.layerMergedContext /** * @since 1.0.0 * @category Tracing */ export interface SpanNameGenerator { readonly _: unique symbol } /** * @since 1.0.0 * @category Tracing */ export const SpanNameGenerator: Context.Reference< SpanNameGenerator, (request: ClientRequest.HttpClientRequest) => string > = internal.SpanNameGenerator /** * Customizes the span names for tracing. * * ```ts * import { FetchHttpClient, HttpClient } from "@effect/platform" * import { NodeRuntime } from "@effect/platform-node" * import { Effect } from "effect" * * Effect.gen(function* () { * const client = (yield* HttpClient.HttpClient).pipe( * // Customize the span names for this HttpClient * HttpClient.withSpanNameGenerator( * (request) => `http.client ${request.method} ${request.url}` * ) * ) * * yield* client.get("https://jsonplaceholder.typicode.com/posts/1") * }).pipe(Effect.provide(FetchHttpClient.layer), NodeRuntime.runMain) * ``` * * @since 1.0.0 * @category Tracing */ export const withSpanNameGenerator: { /** * Customizes the span names for tracing. * * ```ts * import { FetchHttpClient, HttpClient } from "@effect/platform" * import { NodeRuntime } from "@effect/platform-node" * import { Effect } from "effect" * * Effect.gen(function* () { * const client = (yield* HttpClient.HttpClient).pipe( * // Customize the span names for this HttpClient * HttpClient.withSpanNameGenerator( * (request) => `http.client ${request.method} ${request.url}` * ) * ) * * yield* client.get("https://jsonplaceholder.typicode.com/posts/1") * }).pipe(Effect.provide(FetchHttpClient.layer), NodeRuntime.runMain) * ``` * * @since 1.0.0 * @category Tracing */ (f: (request: ClientRequest.HttpClientRequest) => string): (self: HttpClient.With) => HttpClient.With /** * Customizes the span names for tracing. * * ```ts * import { FetchHttpClient, HttpClient } from "@effect/platform" * import { NodeRuntime } from "@effect/platform-node" * import { Effect } from "effect" * * Effect.gen(function* () { * const client = (yield* HttpClient.HttpClient).pipe( * // Customize the span names for this HttpClient * HttpClient.withSpanNameGenerator( * (request) => `http.client ${request.method} ${request.url}` * ) * ) * * yield* client.get("https://jsonplaceholder.typicode.com/posts/1") * }).pipe(Effect.provide(FetchHttpClient.layer), NodeRuntime.runMain) * ``` * * @since 1.0.0 * @category Tracing */ ( self: HttpClient.With, f: (request: ClientRequest.HttpClientRequest) => string ): HttpClient.With } = internal.withSpanNameGenerator /** * Ties the lifetime of the `HttpClientRequest` to a `Scope`. * * @since 1.0.0 * @category Scope */ export const withScope: ( self: HttpClient.With ) => HttpClient.With = internal.withScope