feat: export all types by bounoable · Pull Request #280 · unjs/ofetch · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 1 addition & 17 deletions src/error.ts
84 changes: 6 additions & 78 deletions src/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,19 @@
import type { Readable } from "node:stream";
import destr from "destr";
import { withBase, withQuery } from "ufo";
import type { Fetch, RequestInfo, RequestInit, Response } from "./types";
import { createFetchError } from "./error";
import {
isPayloadMethod,
isJSONSerializable,
detectResponseType,
ResponseType,
MappedType,
mergeFetchOptions,
} from "./utils";

export interface CreateFetchOptions {
// eslint-disable-next-line no-use-before-define
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}

export type FetchRequest = RequestInfo;
export interface FetchResponse<T> extends Response {
_data?: T;
}
export interface SearchParameters {
[key: string]: any;
}

export interface FetchContext<T = any, R extends ResponseType = ResponseType> {
request: FetchRequest;
// eslint-disable-next-line no-use-before-define
options: FetchOptions<R>;
response?: FetchResponse<T>;
error?: Error;
}

export interface FetchOptions<R extends ResponseType = ResponseType>
extends Omit<RequestInit, "body"> {
baseURL?: string;
body?: RequestInit["body"] | Record<string, any>;
ignoreResponseError?: boolean;
params?: SearchParameters;
query?: SearchParameters;
parseResponse?: (responseText: string) => any;
responseType?: R;

/**
* @experimental Set to "half" to enable duplex streaming.
* Will be automatically set to "half" when using a ReadableStream as body.
* https://fetch.spec.whatwg.org/#enumdef-requestduplex
*/
duplex?: "half" | undefined;

/** timeout in milliseconds */
timeout?: number;

retry?: number | false;
/** Delay between retries in milliseconds. */
retryDelay?: number;
/** Default is [408, 409, 425, 429, 500, 502, 503, 504] */
retryStatusCodes?: number[];

onRequest?(context: FetchContext): Promise<void> | void;
onRequestError?(
context: FetchContext & { error: Error }
): Promise<void> | void;
onResponse?(
context: FetchContext & { response: FetchResponse<R> }
): Promise<void> | void;
onResponseError?(
context: FetchContext & { response: FetchResponse<R> }
): Promise<void> | void;
}

export interface $Fetch {
<T = any, R extends ResponseType = "json">(
request: FetchRequest,
options?: FetchOptions<R>
): Promise<MappedType<R, T>>;
raw<T = any, R extends ResponseType = "json">(
request: FetchRequest,
options?: FetchOptions<R>
): Promise<FetchResponse<MappedType<R, T>>>;
native: Fetch;
create(defaults: FetchOptions): $Fetch;
}
import type {
CreateFetchOptions,
FetchResponse,
FetchContext,
$Fetch,
} from "./types";

// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
const retryStatusCodes = new Set([
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { createFetch } from "./base";

export * from "./base";

export type * from "./types";

// ref: https://github.com/tc39/proposal-global
const _globalThis = (function () {
if (typeof globalThis !== "undefined") {
Expand Down
129 changes: 126 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,127 @@
// --------------------------
// $fetch API
// --------------------------

export interface $Fetch {
<T = any, R extends ResponseType = "json">(
request: FetchRequest,
options?: FetchOptions<R>
): Promise<MappedResponseType<R, T>>;
raw<T = any, R extends ResponseType = "json">(
request: FetchRequest,
options?: FetchOptions<R>
): Promise<FetchResponse<MappedResponseType<R, T>>>;
native: Fetch;
create(defaults: FetchOptions): $Fetch;
}

// --------------------------
// Context
// --------------------------

export interface FetchContext<T = any, R extends ResponseType = ResponseType> {
request: FetchRequest;
// eslint-disable-next-line no-use-before-define
options: FetchOptions<R>;
response?: FetchResponse<T>;
error?: Error;
}

// --------------------------
// Options
// --------------------------

export interface FetchOptions<R extends ResponseType = ResponseType>
extends Omit<RequestInit, "body"> {
baseURL?: string;
body?: RequestInit["body"] | Record<string, any>;
ignoreResponseError?: boolean;
params?: Record<string, any>;
query?: Record<string, any>;
parseResponse?: (responseText: string) => any;
responseType?: R;

/**
* @experimental Set to "half" to enable duplex streaming.
* Will be automatically set to "half" when using a ReadableStream as body.
* https://fetch.spec.whatwg.org/#enumdef-requestduplex
*/
duplex?: "half" | undefined;

/** timeout in milliseconds */
timeout?: number;

retry?: number | false;
/** Delay between retries in milliseconds. */
retryDelay?: number;
/** Default is [408, 409, 425, 429, 500, 502, 503, 504] */
retryStatusCodes?: number[];

onRequest?(context: FetchContext): Promise<void> | void;
onRequestError?(
context: FetchContext & { error: Error }
): Promise<void> | void;
onResponse?(
context: FetchContext & { response: FetchResponse<R> }
): Promise<void> | void;
onResponseError?(
context: FetchContext & { response: FetchResponse<R> }
): Promise<void> | void;
}

export interface CreateFetchOptions {
// eslint-disable-next-line no-use-before-define
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}

// --------------------------
// Response Types
// --------------------------

export interface ResponseMap {
blob: Blob;
text: string;
arrayBuffer: ArrayBuffer;
stream: ReadableStream<Uint8Array>;
}

export type ResponseType = keyof ResponseMap | "json";

export type MappedResponseType<
R extends ResponseType,
JsonType = any,
> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType;

export interface FetchResponse<T> extends Response {
_data?: T;
}

// --------------------------
// Error
// --------------------------

export interface IFetchError<T = any> extends Error {
request?: FetchRequest;
options?: FetchOptions;
response?: FetchResponse<T>;
data?: T;
status?: number;
statusText?: string;
statusCode?: number;
statusMessage?: string;
}

// --------------------------
// Other types
// --------------------------

export type Fetch = typeof globalThis.fetch;
export type RequestInfo = globalThis.RequestInfo;
export type RequestInit = globalThis.RequestInit;
export type Response = globalThis.Response;

export type FetchRequest = RequestInfo;

export interface SearchParameters {
[key: string]: any;
}
15 changes: 1 addition & 14 deletions src/utils.ts