Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,357 @@
'use strict';
const destr = require('destr');
const ufo = require('ufo');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const destr__default = /*#__PURE__*/_interopDefaultCompat(destr);
class FetchError extends Error {
constructor(message, opts) {
super(message, opts);
this.name = "FetchError";
if (opts?.cause && !this.cause) {
this.cause = opts.cause;
}
}
}
function createFetchError(ctx) {
const errorMessage = ctx.error?.message || ctx.error?.toString() || "";
const method = ctx.request?.method || ctx.options?.method || "GET";
const url = ctx.request?.url || String(ctx.request) || "/";
const requestStr = `[${method}] ${JSON.stringify(url)}`;
const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>";
const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`;
const fetchError = new FetchError(
message,
ctx.error ? { cause: ctx.error } : void 0
);
for (const key of ["request", "options", "response"]) {
Object.defineProperty(fetchError, key, {
get() {
return ctx[key];
}
});
}
for (const [key, refKey] of [
["data", "_data"],
["status", "status"],
["statusCode", "status"],
["statusText", "statusText"],
["statusMessage", "statusText"]
]) {
Object.defineProperty(fetchError, key, {
get() {
return ctx.response && ctx.response[refKey];
}
});
}
return fetchError;
}
const payloadMethods = new Set(
Object.freeze(["PATCH", "POST", "PUT", "DELETE"])
);
function isPayloadMethod(method = "GET") {
return payloadMethods.has(method.toUpperCase());
}
function isJSONSerializable(value) {
if (value === void 0) {
return false;
}
const t = typeof value;
if (t === "string" || t === "number" || t === "boolean" || t === null) {
return true;
}
if (t !== "object") {
return false;
}
if (Array.isArray(value)) {
return true;
}
if (value.buffer) {
return false;
}
if (value instanceof FormData || value instanceof URLSearchParams) {
return false;
}
return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
}
const textTypes = /* @__PURE__ */ new Set([
"image/svg",
"application/xml",
"application/xhtml",
"application/html"
]);
const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
function detectResponseType(_contentType = "") {
if (!_contentType) {
return "json";
}
const contentType = _contentType.split(";").shift() || "";
if (JSON_RE.test(contentType)) {
return "json";
}
if (contentType === "text/event-stream") {
return "stream";
}
if (textTypes.has(contentType) || contentType.startsWith("text/")) {
return "text";
}
return "blob";
}
function resolveFetchOptions(request, input, defaults, Headers) {
const headers = mergeHeaders(
input?.headers ?? request?.headers,
defaults?.headers,
Headers
);
let query;
if (defaults?.query || defaults?.params || input?.params || input?.query) {
query = {
...defaults?.params,
...defaults?.query,
...input?.params,
...input?.query
};
}
return {
...defaults,
...input,
query,
params: query,
headers
};
}
function mergeHeaders(input, defaults, Headers) {
if (!defaults) {
return new Headers(input);
}
const headers = new Headers(defaults);
if (input) {
for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) {
headers.set(key, value);
}
}
return headers;
}
async function callHooks(context, hooks) {
if (hooks) {
if (Array.isArray(hooks)) {
for (const hook of hooks) {
await hook(context);
}
} else {
await hooks(context);
}
}
}
const retryStatusCodes = /* @__PURE__ */ new Set([
408,
// Request Timeout
409,
// Conflict
425,
// Too Early (Experimental)
429,
// Too Many Requests
500,
// Internal Server Error
502,
// Bad Gateway
503,
// Service Unavailable
504
// Gateway Timeout
]);
const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]);
function createFetch(globalOptions = {}) {
const {
fetch = globalThis.fetch,
Headers = globalThis.Headers,
AbortController = globalThis.AbortController
} = globalOptions;
async function onError(context) {
const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false;
if (context.options.retry !== false && !isAbort) {
let retries;
if (typeof context.options.retry === "number") {
retries = context.options.retry;
} else {
retries = isPayloadMethod(context.options.method) ? 0 : 1;
}
const responseCode = context.response && context.response.status || 500;
if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
if (retryDelay > 0) {
await new Promise((resolve) => setTimeout(resolve, retryDelay));
}
return $fetchRaw(context.request, {
...context.options,
retry: retries - 1
});
}
}
const error = createFetchError(context);
if (Error.captureStackTrace) {
Error.captureStackTrace(error, $fetchRaw);
}
throw error;
}
const $fetchRaw = async function $fetchRaw2(_request, _options = {}) {
const context = {
request: _request,
options: resolveFetchOptions(
_request,
_options,
globalOptions.defaults,
Headers
),
response: void 0,
error: void 0
};
if (context.options.method) {
context.options.method = context.options.method.toUpperCase();
}
if (context.options.onRequest) {
await callHooks(context, context.options.onRequest);
if (!(context.options.headers instanceof Headers)) {
context.options.headers = new Headers(
context.options.headers || {}
/* compat */
);
}
}
if (typeof context.request === "string") {
if (context.options.baseURL) {
context.request = ufo.withBase(context.request, context.options.baseURL);
}
if (context.options.query) {
context.request = ufo.withQuery(context.request, context.options.query);
delete context.options.query;
}
if ("query" in context.options) {
delete context.options.query;
}
if ("params" in context.options) {
delete context.options.params;
}
}
if (context.options.body && isPayloadMethod(context.options.method)) {
if (isJSONSerializable(context.options.body)) {
const contentType = context.options.headers.get("content-type");
if (typeof context.options.body !== "string") {
context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams(
context.options.body
).toString() : JSON.stringify(context.options.body);
}
if (!contentType) {
context.options.headers.set("content-type", "application/json");
}
if (!context.options.headers.has("accept")) {
context.options.headers.set("accept", "application/json");
}
} else if (
// ReadableStream Body
"pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body
typeof context.options.body.pipe === "function"
) {
if (!("duplex" in context.options)) {
context.options.duplex = "half";
}
}
}
let abortTimeout;
if (!context.options.signal && context.options.timeout) {
const controller = new AbortController();
abortTimeout = setTimeout(() => {
const error = new Error(
"[TimeoutError]: The operation was aborted due to timeout"
);
error.name = "TimeoutError";
error.code = 23;
controller.abort(error);
}, context.options.timeout);
context.options.signal = controller.signal;
}
try {
context.response = await fetch(
context.request,
context.options
);
} catch (error) {
context.error = error;
if (context.options.onRequestError) {
await callHooks(
context,
context.options.onRequestError
);
}
return await onError(context);
} finally {
if (abortTimeout) {
clearTimeout(abortTimeout);
}
}
const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324
// https://github.com/unjs/ofetch/issues/294
// https://github.com/JakeChampion/fetch/issues/1454
context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD";
if (hasBody) {
const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || "");
switch (responseType) {
case "json": {
const data = await context.response.text();
const parseFunction = context.options.parseResponse || destr__default;
context.response._data = parseFunction(data);
break;
}
case "stream": {
context.response._data = context.response.body || context.response._bodyInit;
break;
}
default: {
context.response._data = await context.response[responseType]();
}
}
}
if (context.options.onResponse) {
await callHooks(
context,
context.options.onResponse
);
}
if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) {
if (context.options.onResponseError) {
await callHooks(
context,
context.options.onResponseError
);
}
return await onError(context);
}
return context.response;
};
const $fetch = async function $fetch2(request, options) {
const r = await $fetchRaw(request, options);
return r._data;
};
$fetch.raw = $fetchRaw;
$fetch.native = (...args) => fetch(...args);
$fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({
...globalOptions,
...customGlobalOptions,
defaults: {
...globalOptions.defaults,
...customGlobalOptions.defaults,
...defaultOptions
}
});
return $fetch;
}
exports.FetchError = FetchError;
exports.createFetch = createFetch;
exports.createFetchError = createFetchError;

View file

@ -0,0 +1,114 @@
import * as undici from 'undici';
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, globalOptions?: CreateFetchOptions): $Fetch;
}
interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> {
baseURL?: string;
body?: RequestInit["body"] | Record<string, any>;
ignoreResponseError?: boolean;
/**
* @deprecated use query instead.
*/
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.
* @see https://fetch.spec.whatwg.org/#enumdef-requestduplex
*/
duplex?: "half" | undefined;
/**
* Only supported in Node.js >= 18 using undici
*
* @see https://undici.nodejs.org/#/docs/api/Dispatcher
*/
dispatcher?: InstanceType<typeof undici.Dispatcher>;
/**
* Only supported older Node.js versions using node-fetch-native polyfill.
*/
agent?: unknown;
/** timeout in milliseconds */
timeout?: number;
retry?: number | false;
/** Delay between retries in milliseconds. */
retryDelay?: number | ((context: FetchContext<T, R>) => number);
/** Default is [408, 409, 425, 429, 500, 502, 503, 504] */
retryStatusCodes?: number[];
}
interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> {
headers: Headers;
}
interface CreateFetchOptions {
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}
type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">;
interface FetchContext<T = any, R extends ResponseType = ResponseType> {
request: FetchRequest;
options: ResolvedFetchOptions<R>;
response?: FetchResponse<T>;
error?: Error;
}
type MaybePromise<T> = T | Promise<T>;
type MaybeArray<T> = T | T[];
type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>;
interface FetchHooks<T = any, R extends ResponseType = ResponseType> {
onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>;
onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & {
error: Error;
}>>;
onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
}
interface ResponseMap {
blob: Blob;
text: string;
arrayBuffer: ArrayBuffer;
stream: ReadableStream<Uint8Array>;
}
type ResponseType = keyof ResponseMap | "json";
type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType;
interface FetchResponse<T> extends Response {
_data?: T;
}
interface IFetchError<T = any> extends Error {
request?: FetchRequest;
options?: FetchOptions;
response?: FetchResponse<T>;
data?: T;
status?: number;
statusText?: string;
statusCode?: number;
statusMessage?: string;
}
type Fetch = typeof globalThis.fetch;
type FetchRequest = RequestInfo;
interface SearchParameters {
[key: string]: any;
}
declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch;
declare class FetchError<T = any> extends Error implements IFetchError<T> {
constructor(message: string, opts?: {
cause: unknown;
});
}
interface FetchError<T = any> extends IFetchError<T> {
}
declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>;
export { FetchError as F, createFetchError as a, createFetch as c };
export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k };

View file

@ -0,0 +1,114 @@
import * as undici from 'undici';
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, globalOptions?: CreateFetchOptions): $Fetch;
}
interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> {
baseURL?: string;
body?: RequestInit["body"] | Record<string, any>;
ignoreResponseError?: boolean;
/**
* @deprecated use query instead.
*/
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.
* @see https://fetch.spec.whatwg.org/#enumdef-requestduplex
*/
duplex?: "half" | undefined;
/**
* Only supported in Node.js >= 18 using undici
*
* @see https://undici.nodejs.org/#/docs/api/Dispatcher
*/
dispatcher?: InstanceType<typeof undici.Dispatcher>;
/**
* Only supported older Node.js versions using node-fetch-native polyfill.
*/
agent?: unknown;
/** timeout in milliseconds */
timeout?: number;
retry?: number | false;
/** Delay between retries in milliseconds. */
retryDelay?: number | ((context: FetchContext<T, R>) => number);
/** Default is [408, 409, 425, 429, 500, 502, 503, 504] */
retryStatusCodes?: number[];
}
interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> {
headers: Headers;
}
interface CreateFetchOptions {
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}
type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">;
interface FetchContext<T = any, R extends ResponseType = ResponseType> {
request: FetchRequest;
options: ResolvedFetchOptions<R>;
response?: FetchResponse<T>;
error?: Error;
}
type MaybePromise<T> = T | Promise<T>;
type MaybeArray<T> = T | T[];
type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>;
interface FetchHooks<T = any, R extends ResponseType = ResponseType> {
onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>;
onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & {
error: Error;
}>>;
onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
}
interface ResponseMap {
blob: Blob;
text: string;
arrayBuffer: ArrayBuffer;
stream: ReadableStream<Uint8Array>;
}
type ResponseType = keyof ResponseMap | "json";
type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType;
interface FetchResponse<T> extends Response {
_data?: T;
}
interface IFetchError<T = any> extends Error {
request?: FetchRequest;
options?: FetchOptions;
response?: FetchResponse<T>;
data?: T;
status?: number;
statusText?: string;
statusCode?: number;
statusMessage?: string;
}
type Fetch = typeof globalThis.fetch;
type FetchRequest = RequestInfo;
interface SearchParameters {
[key: string]: any;
}
declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch;
declare class FetchError<T = any> extends Error implements IFetchError<T> {
constructor(message: string, opts?: {
cause: unknown;
});
}
interface FetchError<T = any> extends IFetchError<T> {
}
declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>;
export { FetchError as F, createFetchError as a, createFetch as c };
export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k };

View file

@ -0,0 +1,114 @@
import * as undici from 'undici';
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, globalOptions?: CreateFetchOptions): $Fetch;
}
interface FetchOptions<R extends ResponseType = ResponseType, T = any> extends Omit<RequestInit, "body">, FetchHooks<T, R> {
baseURL?: string;
body?: RequestInit["body"] | Record<string, any>;
ignoreResponseError?: boolean;
/**
* @deprecated use query instead.
*/
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.
* @see https://fetch.spec.whatwg.org/#enumdef-requestduplex
*/
duplex?: "half" | undefined;
/**
* Only supported in Node.js >= 18 using undici
*
* @see https://undici.nodejs.org/#/docs/api/Dispatcher
*/
dispatcher?: InstanceType<typeof undici.Dispatcher>;
/**
* Only supported older Node.js versions using node-fetch-native polyfill.
*/
agent?: unknown;
/** timeout in milliseconds */
timeout?: number;
retry?: number | false;
/** Delay between retries in milliseconds. */
retryDelay?: number | ((context: FetchContext<T, R>) => number);
/** Default is [408, 409, 425, 429, 500, 502, 503, 504] */
retryStatusCodes?: number[];
}
interface ResolvedFetchOptions<R extends ResponseType = ResponseType, T = any> extends FetchOptions<R, T> {
headers: Headers;
}
interface CreateFetchOptions {
defaults?: FetchOptions;
fetch?: Fetch;
Headers?: typeof Headers;
AbortController?: typeof AbortController;
}
type GlobalOptions = Pick<FetchOptions, "timeout" | "retry" | "retryDelay">;
interface FetchContext<T = any, R extends ResponseType = ResponseType> {
request: FetchRequest;
options: ResolvedFetchOptions<R>;
response?: FetchResponse<T>;
error?: Error;
}
type MaybePromise<T> = T | Promise<T>;
type MaybeArray<T> = T | T[];
type FetchHook<C extends FetchContext = FetchContext> = (context: C) => MaybePromise<void>;
interface FetchHooks<T = any, R extends ResponseType = ResponseType> {
onRequest?: MaybeArray<FetchHook<FetchContext<T, R>>>;
onRequestError?: MaybeArray<FetchHook<FetchContext<T, R> & {
error: Error;
}>>;
onResponse?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
onResponseError?: MaybeArray<FetchHook<FetchContext<T, R> & {
response: FetchResponse<T>;
}>>;
}
interface ResponseMap {
blob: Blob;
text: string;
arrayBuffer: ArrayBuffer;
stream: ReadableStream<Uint8Array>;
}
type ResponseType = keyof ResponseMap | "json";
type MappedResponseType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType;
interface FetchResponse<T> extends Response {
_data?: T;
}
interface IFetchError<T = any> extends Error {
request?: FetchRequest;
options?: FetchOptions;
response?: FetchResponse<T>;
data?: T;
status?: number;
statusText?: string;
statusCode?: number;
statusMessage?: string;
}
type Fetch = typeof globalThis.fetch;
type FetchRequest = RequestInfo;
interface SearchParameters {
[key: string]: any;
}
declare function createFetch(globalOptions?: CreateFetchOptions): $Fetch;
declare class FetchError<T = any> extends Error implements IFetchError<T> {
constructor(message: string, opts?: {
cause: unknown;
});
}
interface FetchError<T = any> extends IFetchError<T> {
}
declare function createFetchError<T = any>(ctx: FetchContext<T>): IFetchError<T>;
export { FetchError as F, createFetchError as a, createFetch as c };
export type { $Fetch as $, CreateFetchOptions as C, GlobalOptions as G, IFetchError as I, MappedResponseType as M, ResolvedFetchOptions as R, SearchParameters as S, FetchOptions as b, FetchContext as d, FetchHook as e, FetchHooks as f, ResponseMap as g, ResponseType as h, FetchResponse as i, Fetch as j, FetchRequest as k };

View file

@ -0,0 +1,349 @@
import destr from 'destr';
import { withBase, withQuery } from 'ufo';
class FetchError extends Error {
constructor(message, opts) {
super(message, opts);
this.name = "FetchError";
if (opts?.cause && !this.cause) {
this.cause = opts.cause;
}
}
}
function createFetchError(ctx) {
const errorMessage = ctx.error?.message || ctx.error?.toString() || "";
const method = ctx.request?.method || ctx.options?.method || "GET";
const url = ctx.request?.url || String(ctx.request) || "/";
const requestStr = `[${method}] ${JSON.stringify(url)}`;
const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>";
const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`;
const fetchError = new FetchError(
message,
ctx.error ? { cause: ctx.error } : void 0
);
for (const key of ["request", "options", "response"]) {
Object.defineProperty(fetchError, key, {
get() {
return ctx[key];
}
});
}
for (const [key, refKey] of [
["data", "_data"],
["status", "status"],
["statusCode", "status"],
["statusText", "statusText"],
["statusMessage", "statusText"]
]) {
Object.defineProperty(fetchError, key, {
get() {
return ctx.response && ctx.response[refKey];
}
});
}
return fetchError;
}
const payloadMethods = new Set(
Object.freeze(["PATCH", "POST", "PUT", "DELETE"])
);
function isPayloadMethod(method = "GET") {
return payloadMethods.has(method.toUpperCase());
}
function isJSONSerializable(value) {
if (value === void 0) {
return false;
}
const t = typeof value;
if (t === "string" || t === "number" || t === "boolean" || t === null) {
return true;
}
if (t !== "object") {
return false;
}
if (Array.isArray(value)) {
return true;
}
if (value.buffer) {
return false;
}
if (value instanceof FormData || value instanceof URLSearchParams) {
return false;
}
return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
}
const textTypes = /* @__PURE__ */ new Set([
"image/svg",
"application/xml",
"application/xhtml",
"application/html"
]);
const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
function detectResponseType(_contentType = "") {
if (!_contentType) {
return "json";
}
const contentType = _contentType.split(";").shift() || "";
if (JSON_RE.test(contentType)) {
return "json";
}
if (contentType === "text/event-stream") {
return "stream";
}
if (textTypes.has(contentType) || contentType.startsWith("text/")) {
return "text";
}
return "blob";
}
function resolveFetchOptions(request, input, defaults, Headers) {
const headers = mergeHeaders(
input?.headers ?? request?.headers,
defaults?.headers,
Headers
);
let query;
if (defaults?.query || defaults?.params || input?.params || input?.query) {
query = {
...defaults?.params,
...defaults?.query,
...input?.params,
...input?.query
};
}
return {
...defaults,
...input,
query,
params: query,
headers
};
}
function mergeHeaders(input, defaults, Headers) {
if (!defaults) {
return new Headers(input);
}
const headers = new Headers(defaults);
if (input) {
for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) {
headers.set(key, value);
}
}
return headers;
}
async function callHooks(context, hooks) {
if (hooks) {
if (Array.isArray(hooks)) {
for (const hook of hooks) {
await hook(context);
}
} else {
await hooks(context);
}
}
}
const retryStatusCodes = /* @__PURE__ */ new Set([
408,
// Request Timeout
409,
// Conflict
425,
// Too Early (Experimental)
429,
// Too Many Requests
500,
// Internal Server Error
502,
// Bad Gateway
503,
// Service Unavailable
504
// Gateway Timeout
]);
const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]);
function createFetch(globalOptions = {}) {
const {
fetch = globalThis.fetch,
Headers = globalThis.Headers,
AbortController = globalThis.AbortController
} = globalOptions;
async function onError(context) {
const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false;
if (context.options.retry !== false && !isAbort) {
let retries;
if (typeof context.options.retry === "number") {
retries = context.options.retry;
} else {
retries = isPayloadMethod(context.options.method) ? 0 : 1;
}
const responseCode = context.response && context.response.status || 500;
if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
if (retryDelay > 0) {
await new Promise((resolve) => setTimeout(resolve, retryDelay));
}
return $fetchRaw(context.request, {
...context.options,
retry: retries - 1
});
}
}
const error = createFetchError(context);
if (Error.captureStackTrace) {
Error.captureStackTrace(error, $fetchRaw);
}
throw error;
}
const $fetchRaw = async function $fetchRaw2(_request, _options = {}) {
const context = {
request: _request,
options: resolveFetchOptions(
_request,
_options,
globalOptions.defaults,
Headers
),
response: void 0,
error: void 0
};
if (context.options.method) {
context.options.method = context.options.method.toUpperCase();
}
if (context.options.onRequest) {
await callHooks(context, context.options.onRequest);
if (!(context.options.headers instanceof Headers)) {
context.options.headers = new Headers(
context.options.headers || {}
/* compat */
);
}
}
if (typeof context.request === "string") {
if (context.options.baseURL) {
context.request = withBase(context.request, context.options.baseURL);
}
if (context.options.query) {
context.request = withQuery(context.request, context.options.query);
delete context.options.query;
}
if ("query" in context.options) {
delete context.options.query;
}
if ("params" in context.options) {
delete context.options.params;
}
}
if (context.options.body && isPayloadMethod(context.options.method)) {
if (isJSONSerializable(context.options.body)) {
const contentType = context.options.headers.get("content-type");
if (typeof context.options.body !== "string") {
context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams(
context.options.body
).toString() : JSON.stringify(context.options.body);
}
if (!contentType) {
context.options.headers.set("content-type", "application/json");
}
if (!context.options.headers.has("accept")) {
context.options.headers.set("accept", "application/json");
}
} else if (
// ReadableStream Body
"pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body
typeof context.options.body.pipe === "function"
) {
if (!("duplex" in context.options)) {
context.options.duplex = "half";
}
}
}
let abortTimeout;
if (!context.options.signal && context.options.timeout) {
const controller = new AbortController();
abortTimeout = setTimeout(() => {
const error = new Error(
"[TimeoutError]: The operation was aborted due to timeout"
);
error.name = "TimeoutError";
error.code = 23;
controller.abort(error);
}, context.options.timeout);
context.options.signal = controller.signal;
}
try {
context.response = await fetch(
context.request,
context.options
);
} catch (error) {
context.error = error;
if (context.options.onRequestError) {
await callHooks(
context,
context.options.onRequestError
);
}
return await onError(context);
} finally {
if (abortTimeout) {
clearTimeout(abortTimeout);
}
}
const hasBody = (context.response.body || // https://github.com/unjs/ofetch/issues/324
// https://github.com/unjs/ofetch/issues/294
// https://github.com/JakeChampion/fetch/issues/1454
context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD";
if (hasBody) {
const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || "");
switch (responseType) {
case "json": {
const data = await context.response.text();
const parseFunction = context.options.parseResponse || destr;
context.response._data = parseFunction(data);
break;
}
case "stream": {
context.response._data = context.response.body || context.response._bodyInit;
break;
}
default: {
context.response._data = await context.response[responseType]();
}
}
}
if (context.options.onResponse) {
await callHooks(
context,
context.options.onResponse
);
}
if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) {
if (context.options.onResponseError) {
await callHooks(
context,
context.options.onResponseError
);
}
return await onError(context);
}
return context.response;
};
const $fetch = async function $fetch2(request, options) {
const r = await $fetchRaw(request, options);
return r._data;
};
$fetch.raw = $fetchRaw;
$fetch.native = (...args) => fetch(...args);
$fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({
...globalOptions,
...customGlobalOptions,
defaults: {
...globalOptions.defaults,
...customGlobalOptions.defaults,
...defaultOptions
}
});
return $fetch;
}
export { FetchError as F, createFetchError as a, createFetch as c };