@scirexs/fetchy 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/main.js CHANGED
@@ -1 +1 @@
1
- export{v as Fetchy,i as fetchy,h as HTTPStatusError,l as NO_RETRY_ERROR,b as RedirectError,s as sfetchy};const l="$$_NO_RETRY_$$",u={timeout:15,delay:0,interval:3,maxInterval:30,maxAttempts:3,retryAfter:!0,native:!1,redirect:"follow"};class h extends Error{static#t=80;status;body;constructor(t,r,n){super(t),this.name="HTTPStatusError",this.status=r,this.body=n}static async fromResponse(t){const r=await t.text(),n=r.length>this.#t?`${r.slice(0,this.#t)}... (more ${r.length-this.#t} chars)`:r||"(no response body)",a=`${t.status} ${t.statusText}: ${n}`;return new this(a,t.status,r)}}class b extends Error{status;constructor(t,r){super(t),this.name="RedirectError",this.status=r}static fromResponse(t){const r=`${t.status} ${t.statusText}`.trim();return new this(r,t.status)}}class v{url;body;timeout;retry;bearer;delay;native;constructor(t){Object.assign(this,t)}async fetch(t){return await i(t??null,this)}async text(t){return await i(t??null,this,"text")}async json(t){return await i(t??null,this,"json")}async bytes(t){return await i(t??null,this,"bytes")}async blob(t){return await i(t??null,this,"blob")}async buffer(t){return await i(t??null,this,"buffer")}async safe(t){return await s(t??null,this)}async stext(t){return await i(t??null,this,"text")}async sjson(t){return await i(t??null,this,"json")}async sbytes(t){return await i(t??null,this,"bytes")}async sblob(t){return await i(t??null,this,"blob")}async sbuffer(t){return await i(t??null,this,"buffer")}static async fetch(t,r){return await i(t,r)}static async text(t,r){return await i(t,r,"text")}static async json(t,r){return await i(t,r,"json")}static async bytes(t,r){return await i(t,r,"bytes")}static async blob(t,r){return await i(t,r,"blob")}static async buffer(t,r){return await i(t,r,"buffer")}static async safe(t,r){return await s(t,r)}static async stext(t,r){return await s(t,r,"text")}static async sjson(t,r){return await s(t,r,"json")}static async sbytes(t,r){return await s(t,r,"bytes")}static async sblob(t,r){return await s(t,r,"blob")}static async sbuffer(t,r){return await s(t,r,"buffer")}}async function s(e,t,r){try{return await m(e,t,r)}catch{return null}}async function i(e,t,r){try{return await m(e,t,r)}catch(n){throw n}}async function m(e,t,r){e||(e=t?.url??"");const n=N(t),a=await F(e,O(e,n,t),n);if(!a.ok&&!n.native)throw await h.fromResponse(a);return r?S(a,r):a}function j(e){return typeof e=="string"}function w(e){return typeof e=="number"}function d(e){return typeof e=="boolean"}function T(e){return!!(e&&typeof e=="object"&&Object.getPrototypeOf(e)===Object.prototype)}function y(e,t,r=!1){return t===void 0||t<0?e:r?Math.trunc(t):t}function f(e,t,r){return d(r)?t:r===void 0||r[e]===void 0?u[e]:w(r[e])?y(u[e],r[e],e==="maxAttempts"):r[e]}function N(e){return{timeout:y(u.timeout,e?.timeout),delay:y(u.delay,e?.delay),interval:f("interval",0,e?.retry),maxInterval:f("maxInterval",0,e?.retry),maxAttempts:f("maxAttempts",0,e?.retry),retryAfter:f("retryAfter",!1,e?.retry),native:e?.native??u.native,redirect:e?.redirect??u.redirect}}function O(e,t,r){const{method:n,body:a,timeout:c,retry:J,bearer:L,native:Y,delay:k,redirect:o,signal:G,...A}=r??{};return{headers:$(r),method:n||(e instanceof Request?e.method:a==null?"GET":"POST"),signal:M(e,t.timeout,r?.signal),...o&&{redirect:o=="error"?"manual":o},...a&&{body:E(a)},...A}}function E(e){return x(e)?JSON.stringify(e):e}function x(e){return!!(e===null||w(e)||d(e)||Array.isArray(e)||T(e))}function $(e){const t=new Headers(e?.headers);if(t.has("Accept")||t.set("Accept","application/json, text/plain"),!t.has("Content-Type")){const r=I(e?.body);r&&t.append("Content-Type",r)}return e?.bearer&&t.set("Authorization",`Bearer ${e.bearer}`),t}function I(e){if(!(e==null||j(e)||e instanceof FormData||e instanceof URLSearchParams)&&!(e instanceof Blob&&e.type))return x(e)?"application/json":"application/octet-stream"}function M(e,t,r){const n=[];return e instanceof Request&&e.signal&&n.push(e.signal),r&&n.push(r),t>0&&n.push(AbortSignal.timeout(t*1e3+1)),n.length?AbortSignal.any(n):void 0}async function S(e,t){switch(t){case"json":return await e.json();case"text":return await e.text();case"bytes":return await e.bytes();case"blob":return await e.blob();case"buffer":return await e.arrayBuffer()}}async function _(e,t=!0){if(e<=0)return;const r=Math.trunc((t?Math.random():1)*e*1e3);await new Promise(n=>setTimeout(n,r))}function B(e){return e.status<400&&e.status>=300}function q(e){return e.status<500&&e.status>=400}async function R(e,t,r,n){if(e>=r.maxAttempts-1||t.signal?.aborted)return!0;if(n){if(n.ok||q(n)||r.native)return!0;if(B(n)){if(r.redirect=="manual")return!0;if(r.redirect=="error")throw r.maxAttempts=0,b.fromResponse(n)}}const a=P(e,r,n);return a>r.maxInterval?!0:(await _(a,!1),!1)}function P(e,t,r){return t.retryAfter&&r?.headers.has("Retry-After")?Math.max(D(r.headers.get("Retry-After")?.trim()??""),t.interval):Math.min(Math.pow(Math.max(1,t.interval),e),t.maxInterval)}function D(e){if(!e)return 1/0;const t=Number.parseInt(e,10);if(!Number.isNaN(t))return t;const r=Math.ceil((new Date(e).getTime()-Date.now())/1e3);return Number.isNaN(r)?1/0:r}function C(e,t,r){return r.redirected?(r.status==303&&(t.method="GET"),e instanceof Request?new Request(r.url,e):r.url):e}function H(e,t){return e instanceof Request&&t?e.clone():e}async function F(e,t,r){for(let n=0;n<r.maxAttempts;n++)try{const a=H(e,n<r.maxAttempts-1),c=await g(a,t,r);if(await R(n,t,r,c))return c;e=C(e,t,c);continue}catch(a){if(a instanceof Error&&a.message==l||await R(n,t,r))throw a;continue}return await g(e,t,r)}async function g(e,t,r){return await _(r.delay),await fetch(e,t)}
1
+ export{M as Fetchy,o as fetchy,B as fy,O as HTTPStatusError,s as sfetchy};const d="GET",y="HEAD",h="POST",b="PUT",_="PATCH",g="DELETE",T="Accept",E="Content-Type",w="application/json",a={a:15,b:0,c:3,d:30,e:3,f:!0,g:!1,h:[500,502,503,504,408,429],i:["retry-after","ratelimit-reset","x-ratelimit-reset"],j:!1},v=[h,_,"CONNECT"],N=["text","json","bytes","blob","arrayBuffer","formData"];class O extends Error{status;response;constructor(e){super(`${e.status} ${e.url}`),this.name="HTTPStatusError",this.status=e.status,this.response=e}}class M{url;base;body;timeout;retry;bearer;jitter;native;cache;credentials;headers;integrity;keepalive;method;mode;redirect;referrer;referrerPolicy;signal;constructor(e){Object.assign(this,e)}fetch(e,n){return o(e,i(this,n))}get(e,n){return o(e,i(this,n,d))}head(e,n){return o(e,i(this,n,y))}post(e,n){return o(e,i(this,n,h))}put(e,n){return o(e,i(this,n,b))}patch(e,n){return o(e,i(this,n,_))}delete(e,n){return o(e,i(this,n,g))}safe(e,n){return s(e,i(this,n))}sget(e,n){return s(e,i(this,n,d))}shead(e,n){return s(e,i(this,n,y))}spost(e,n){return s(e,i(this,n,h))}sput(e,n){return s(e,i(this,n,b))}spatch(e,n){return s(e,i(this,n,_))}sdelete(e,n){return s(e,i(this,n,g))}}function B(t){return new M(t)}function s(t,e){try{return j(t,e,!0)}catch{return null}}function o(t,e){return j(t,e)}function j(t,e,n=!1){const r=L(F(t,e)),u=p(t,e),f=z(u,t,e);return Z(r,u,f,n)}function i(t,e,n){return{...t,...e,method:n}}function I(t){return typeof t=="string"}function U(t){return typeof t=="number"}function R(t){return typeof t=="boolean"}function P(t){return t instanceof ReadableStream}function l(t){return t instanceof Request}function k(t){return!!(t&&typeof t=="object"&&Object.getPrototypeOf(t)===Object.prototype)}function m(t,e){return(e??-1)>=0?e:t}function F(t,e){return l(t)||(t||(t=e?.url??""),l(t))?t:new Request(URL.parse(t,e?.base)??"")}function L(t,e){if(!P(e?.body))return t;const n=[d,y].includes(t.method)?h:t.method;return new Request(t,{method:n,body:e.body})}function p(t,e){const{method:n,body:r,timeout:u,retry:f,bearer:c,native:it,jitter:at,headers:ut,signal:ct,...D}=e??{};return{headers:J(e,l(t)?t.headers:null),method:n?n.toUpperCase():l(t)?t.method:r==null?d:h,...q(r),...D}}function q(t){return P(t)?null:{body:S(t)?JSON.stringify(t):t}}function S(t){return!!(U(t)||R(t)||Array.isArray(t)||k(t))}function J(t,e){const n=new Headers(t?.headers);if(H(T,n,e)&&n.set(T,`${w}, text/plain`),H(E,n,e)){const r=$(t?.body);r&&n.set(E,r)}return t?.bearer&&n.set("Authorization",`Bearer ${t.bearer}`),n}function H(t,e,n){return!e.has(t)&&!n?.has(t)}function $(t){return S(t)?w:G(t)?"":"application/octet-stream"}function G(t){return t==null||I(t)||t instanceof FormData||t instanceof URLSearchParams||!!(t instanceof Blob&&t.type)}function W(t,e){return R(e)?{...a,e:1}:{e:Math.max(m(a.e,e?.maxAttempts),1),c:Math.max(m(a.c,e?.interval),.01),d:Math.max(m(a.d,e?.maxInterval),1),f:e?.retryOnTimeout??a.f,g:e?.idempotentOnly?v.includes(t.method??""):!1,h:e?.statusCodes??a.h,i:e?.respectHeaders??a.i}}function z(t,e,n){return{...W(t,n?.retry),a:m(a.a,n?.timeout),b:m(a.b,n?.jitter),j:n?.native??a.j,k:x(l(e)?e.signal:null,n?.signal)}}function x(t,e){if(!(!t&&!e))return t&&e?AbortSignal.any([t,e]):t||(e??void 0)}function Y(t){return t.a<=0?t.k:x(AbortSignal.timeout(t.a*1e3),t.k)}async function A(t,e=!1){if(t<=0)return;const n=Math.trunc((e?Math.random():1)*t*1e3);await new Promise(r=>setTimeout(r,n))}function K(t){return t>=400||t<100}async function C(t,e,n){if(e.g||t>=e.e-1)return!1;if(n instanceof Response){if(e.j||!e.h.includes(n.status))return!1;const r=Q(t,e,n.headers);return r>e.d?!1:(await A(r),!0)}else return n instanceof Error&&n.name=="TimeoutError"&&e.f}function Q(t,e,n){return e.i.some(r=>n.has(r))?V(e,n)??e.c:Math.min(e.c*2**t,e.d)}function V(t,e){for(const n of t.i){const r=X(e.get(n)?.trim());if(!Number.isNaN(r))return Math.max(r,t.c)}}function X(t){if(!t)return NaN;const e=Number.parseInt(t,10);return Number.isNaN(e)?Math.ceil((new Date(t).getTime()-Date.now())/1e3):e}function Z(t,e,n,r=!1){const u=nt(t,e,n,r);return tt(u,r)}function tt(t,e){return Object.assign(t,Object.fromEntries([...e?N.map(n=>[n,()=>t.then(r=>r[n]()).catch(()=>null)]):N.map(n=>[n,()=>t.then(r=>r[n]())])]))}function et(t){let e;return async n=>{n&&await e?.body?.cancel();const r=e??t;return n||(e=e?e.clone():t.clone()),r}}async function nt(t,e,n,r){const u=et(t);for(let f=0;f<n.e;f++)try{const c=await rt(await u(),e,n);if(await C(f,n,c))continue;if(K(c.status)&&!n.j)throw new O(c);return c}catch(c){if(await C(f,n,c))continue;if(r)return null;throw c}finally{await u(!0)}throw new Error}async function rt(t,e,n){return await A(n.b,!0),await fetch(t,{...e,signal:Y(n)})}
package/esm/mod.js CHANGED
@@ -2,4 +2,4 @@
2
2
  * Exports main functions and types for external.
3
3
  * @module
4
4
  */
5
- export { Fetchy, fetchy, HTTPStatusError, NO_RETRY_ERROR, RedirectError, sfetchy } from "./main.js";
5
+ export { Fetchy, fetchy, fy, HTTPStatusError, sfetchy } from "./main.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scirexs/fetchy",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "A lightweight fetch wrapper.",
5
5
  "keywords": [
6
6
  "fetch",
package/types/main.d.ts CHANGED
@@ -1,106 +1,80 @@
1
- export { _cloneInput, _combineSignal, _correctNumber, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleRedirectResponse, _isBool, _isJSONObject, _isNumber, _isPlainObject, _isString, _main, _parseBody, _parseRetryAfter, _shouldCorrectRequest, _shouldNotRetry, _shouldRedirect, _wait, Fetchy, fetchy, HTTPStatusError, NO_RETRY_ERROR, RedirectError, sfetchy, };
2
- import type { FetchyBody, FetchyOptions, RetryOptions } from "./types.js";
3
- /** Error message to simulate immediate failures without retry for writing tests. */
4
- declare const NO_RETRY_ERROR = "$$_NO_RETRY_$$";
1
+ export { _assignToPromise, _buildOption, _cloneRequestF, _correctNumber, _createRequest, _DEFAULT, _fetchWithJitter, _fetchWithRetry, _findRetryHeader, _getBody, _getContentType, _getHeaders, _getNextInterval, _getOptions, _getRequestInit, _getRetryOption, _handleByNative, _includeStream, _isBool, _isHttpError, _isJSONObject, _isNoHeader, _isNumber, _isPlain, _isRequest, _isStream, _isString, _main, _makeFetchyResponse, _mergeSignals, _METHODS, _NO_IDEM, _parseRetryHeader, _shouldRetry, _wait, _withTimeout, Fetchy, fetchy, fy, HTTPStatusError, sfetchy, };
2
+ import type { FetchyBody, FetchyOptions, FetchyResponse, FetchySafeResponse, RetryOptions } from "./types.js";
5
3
  /** Default configuration values for fetchy. */
6
4
  declare const _DEFAULT: Options;
7
- /** Valid input types for fetch requests. */
8
- type Input = string | URL | Request;
9
- type FetchyReturn<T> = Response | string | Uint8Array<ArrayBuffer> | Blob | ArrayBuffer | T;
10
- /** Response body parsing method specification. */
11
- type ParseMethod = "text" | "json" | "bytes" | "blob" | "buffer";
5
+ /** HTTP methods that do not have idempotency. */
6
+ declare const _NO_IDEM: string[];
7
+ /** Additional methods for Promise-like interface. */
8
+ declare const _METHODS: readonly ["text", "json", "bytes", "blob", "arrayBuffer", "formData"];
12
9
  /** Internal normalized options used throughout the fetch process. */
13
10
  interface Options {
14
- timeout: number;
15
- delay: number;
16
- interval: number;
17
- maxInterval: number;
18
- maxAttempts: number;
19
- retryAfter: boolean;
20
- native: boolean;
21
- redirect: "follow" | "error" | "manual";
11
+ ztimeout: number;
12
+ zjitter: number;
13
+ zinterval: number;
14
+ zmaxInterval: number;
15
+ zmaxAttempts: number;
16
+ zonTimeout: boolean;
17
+ znoIdempotent: boolean;
18
+ zstatusCodes: number[];
19
+ zrespects: string[];
20
+ znative: boolean;
21
+ zsignal?: AbortSignal;
22
22
  }
23
+ /** URL argument type for fetchy functions. */
24
+ type InputArg = string | URL | Request | null;
25
+ /** Internal retry-related options extracted from RetryOptions. */
26
+ type InternalRetry = Pick<Options, "zinterval" | "zmaxInterval" | "zmaxAttempts" | "zonTimeout" | "znoIdempotent" | "zstatusCodes" | "zrespects">;
23
27
  /**
24
- * Error thrown when HTTP response has a non-OK status code (4xx, 5xx, ...).
25
- * Only thrown when throwError.onErrorStatus is set to true.
28
+ * Error thrown when HTTP response has a non-OK status code (4xx, 5xx).
29
+ * Only thrown when `native` option is set to false (default behavior).
26
30
  *
27
31
  * @example
28
32
  * ```ts
29
33
  * try {
30
- * await fetchy("https://api.example.com/data", {
31
- * throwError: { onErrorStatus: true }
32
- * });
34
+ * await fetchy("https://api.example.com/data");
33
35
  * } catch (error) {
34
36
  * if (error instanceof HTTPStatusError) {
35
- * console.error("HTTP error:", error.message); // e.g., "403 Forbidden: {success:false}"
37
+ * console.error(`HTTP ${error.status}:`, error.message);
38
+ * console.error("Response:", error.response);
36
39
  * }
37
40
  * }
38
41
  * ```
39
42
  */
40
43
  declare class HTTPStatusError extends Error {
41
- #private;
42
44
  status: number;
43
- body: string;
44
- constructor(msg: string, status: number, body: string);
45
- static fromResponse(resp: Response): Promise<HTTPStatusError>;
46
- }
47
- /**
48
- * Error thrown when a redirect response is received and redirect option is set to "error".
49
- *
50
- * @example
51
- * ```ts
52
- * try {
53
- * await fetchy("https://example.com/redirect", {
54
- * redirect: "error"
55
- * });
56
- * } catch (error) {
57
- * if (error instanceof RedirectError) {
58
- * console.error("Unexpected redirect:", error.message);
59
- * }
60
- * }
61
- * ```
62
- */
63
- declare class RedirectError extends Error {
64
- status: number;
65
- constructor(msg: string, status: number);
66
- static fromResponse(resp: Response): RedirectError;
45
+ response: Response;
46
+ constructor(resp: Response);
67
47
  }
68
48
  /**
69
49
  * A fluent HTTP client class that provides both instance and static methods for making HTTP requests.
70
50
  * Supports features like timeout, retry with exponential backoff, automatic header management, and response parsing.
71
51
  *
72
- * This class can be used in two ways:
73
- * - Instance methods: Create an instance with default options, then call methods with optional URL override
74
- * - Static methods: Call methods directly with URL and options
75
- *
76
52
  * @example
77
53
  * ```ts
78
54
  * // Instance usage - reuse configuration
79
55
  * const client = new Fetchy({
80
56
  * bearer: "token123",
81
57
  * timeout: 10,
82
- * retry: { max: 3 }
83
- * });
84
- * const user = await client.json<User>("https://api.example.com/user");
85
- * const posts = await client.json<Post[]>("https://api.example.com/posts");
86
- *
87
- * // Static usage - one-off requests
88
- * const data = await Fetchy.json("https://api.example.com/data");
89
- * const response = await Fetchy.fetch("https://api.example.com/endpoint", {
90
- * body: { key: "value" },
91
- * timeout: 5
58
+ * retry: { maxAttempts: 3 }
92
59
  * });
60
+ * const user = await client.get("https://api.example.com/user").json<User>();
61
+ * const posts = await client.get("https://api.example.com/posts").json<Post[]>();
93
62
  *
94
63
  * // Safe mode - returns null on error instead of throwing
95
- * const result = await Fetchy.sjson("https://api.example.com/data");
64
+ * const result = await client.safe("https://api.example.com/data").json<Data>();
96
65
  * if (result !== null) {
97
66
  * // Handle successful response
98
67
  * }
99
68
  * ```
100
69
  */
101
70
  declare class Fetchy implements FetchyOptions {
102
- /** Request URL. Used if call fetchy with null. */
103
- url?: string | URL;
71
+ /** Request URL. Used when calling methods with null as URL argument. */
72
+ url?: string | URL | Request;
73
+ /**
74
+ * Base URL prepended to the request URL.
75
+ * Only used when the URL argument is a string or URL (not when it's a Request object).
76
+ */
77
+ base?: string | URL;
104
78
  /** Request body content. Automatically serializes JSON objects. */
105
79
  body?: FetchyBody;
106
80
  /** Request timeout in seconds. Default is 15 seconds. */
@@ -109,63 +83,89 @@ declare class Fetchy implements FetchyOptions {
109
83
  retry?: false | RetryOptions;
110
84
  /** Bearer token for Authorization header. Automatically adds "Bearer " prefix. */
111
85
  bearer?: string;
112
- /** Initial jitter delay in seconds before sending the request. Adds randomness to prevent thundering herd. */
113
- delay?: number;
114
- /** If receive response, does not throw error same with native fetch. */
115
- native?: true;
86
+ /**
87
+ * Maximum jitter delay in seconds applied before each request (including retries).
88
+ * Adds randomness (0 to specified value) to prevent thundering herd.
89
+ */
90
+ jitter?: number;
91
+ /** If true, does not throw error on HTTP error status, behaving like native fetch. */
92
+ native?: boolean;
93
+ /** Property of RequestInit. */
94
+ cache?: RequestCache;
95
+ /** Property of RequestInit. */
96
+ credentials?: RequestCredentials;
97
+ /** Property of RequestInit. */
98
+ headers?: HeadersInit;
99
+ /** Property of RequestInit. */
100
+ integrity?: string;
101
+ /** Property of RequestInit. */
102
+ keepalive?: boolean;
103
+ /** Property of RequestInit. */
104
+ method?: string;
105
+ /** Property of RequestInit. */
106
+ mode?: RequestMode;
107
+ /** Property of RequestInit. */
108
+ redirect?: RequestRedirect;
109
+ /** Property of RequestInit. */
110
+ referrer?: string;
111
+ /** Property of RequestInit. */
112
+ referrerPolicy?: ReferrerPolicy;
113
+ /** Property of RequestInit. */
114
+ signal?: AbortSignal | null;
116
115
  constructor(options?: FetchyOptions);
117
- /** Call fetchy with instance options. */
118
- fetch(url?: Input | null): Promise<Response>;
119
- /** Call fetchy with instance options and parsing as text. */
120
- text(url?: Input | null): Promise<string>;
121
- /** Call fetchy with instance options and parsing as json. */
122
- json<T>(url?: Input | null): Promise<T>;
123
- /** Call fetchy with instance options and parsing as Uint8Array. */
124
- bytes(url?: Input | null): Promise<Uint8Array<ArrayBuffer>>;
125
- /** Call fetchy with instance options and parsing as Blob. */
126
- blob(url?: Input | null): Promise<Blob>;
127
- /** Call fetchy with instance options and parsing as ArrayBuffer. */
128
- buffer(url?: Input | null): Promise<ArrayBuffer>;
129
- /** Call sfetchy with instance options. */
130
- safe(url?: Input | null): Promise<Response | null>;
131
- /** Call sfetchy with instance options and parsing as text. */
132
- stext(url?: Input | null): Promise<string | null>;
133
- /** Call sfetchy with instance options and parsing as json. */
134
- sjson<T>(url?: Input | null): Promise<T | null>;
135
- /** Call sfetchy with instance options and parsing as Uint8Array. */
136
- sbytes(url?: Input | null): Promise<Uint8Array<ArrayBuffer> | null>;
137
- /** Call sfetchy with instance options and parsing as Blob. */
138
- sblob(url?: Input | null): Promise<Blob | null>;
139
- /** Call sfetchy with instance options and parsing as ArrayBuffer. */
140
- sbuffer(url?: Input | null): Promise<ArrayBuffer | null>;
141
- /** Call fetchy. */
142
- static fetch(url: Input | null, options?: FetchyOptions): Promise<Response>;
143
- /** Call fetchy with parsing as text. */
144
- static text(url: Input | null, options?: FetchyOptions): Promise<string>;
145
- /** Call fetchy with parsing as json. */
146
- static json<T>(url: Input | null, options?: FetchyOptions): Promise<T>;
147
- /** Call fetchy with parsing as Uint8Array. */
148
- static bytes(url: Input | null, options?: FetchyOptions): Promise<Uint8Array<ArrayBuffer>>;
149
- /** Call fetchy with parsing as Blob. */
150
- static blob(url: Input | null, options?: FetchyOptions): Promise<Blob>;
151
- /** Call fetchy with parsing as ArrayBuffer. */
152
- static buffer(url: Input | null, options?: FetchyOptions): Promise<ArrayBuffer>;
153
- /** Call sfetchy. */
154
- static safe(url: Input | null, options?: FetchyOptions): Promise<Response | null>;
155
- /** Call sfetchy with parsing as text. */
156
- static stext(url: Input | null, options?: FetchyOptions): Promise<string | null>;
157
- /** Call sfetchy with parsing as json. */
158
- static sjson<T>(url: Input | null, options?: FetchyOptions): Promise<T | null>;
159
- /** Call sfetchy with parsing as Uint8Array. */
160
- static sbytes(url: Input | null, options?: FetchyOptions): Promise<Uint8Array<ArrayBuffer> | null>;
161
- /** Call sfetchy with parsing as Blob. */
162
- static sblob(url: Input | null, options?: FetchyOptions): Promise<Blob | null>;
163
- /** Call sfetchy with parsing as ArrayBuffer. */
164
- static sbuffer(url: Input | null, options?: FetchyOptions): Promise<ArrayBuffer | null>;
116
+ /** Calls fetchy with instance options. */
117
+ fetch(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
118
+ /** Calls fetchy as GET request with instance options. */
119
+ get(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
120
+ /** Calls fetchy as HEAD request with instance options. */
121
+ head(url?: string | URL | Request | null, options?: FetchyOptions): Promise<Response>;
122
+ /** Calls fetchy as POST request with instance options. */
123
+ post(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
124
+ /** Calls fetchy as PUT request with instance options. */
125
+ put(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
126
+ /** Calls fetchy as PATCH request with instance options. */
127
+ patch(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
128
+ /** Calls fetchy as DELETE request with instance options. */
129
+ delete(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
130
+ /** Calls sfetchy with instance options. Returns null on error. */
131
+ safe(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
132
+ /** Calls sfetchy as GET request with instance options. Returns null on error. */
133
+ sget(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
134
+ /** Calls sfetchy as HEAD request with instance options. Returns null on error. */
135
+ shead(url?: string | URL | Request | null, options?: FetchyOptions): Promise<Response | null> | null;
136
+ /** Calls sfetchy as POST request with instance options. Returns null on error. */
137
+ spost(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
138
+ /** Calls sfetchy as PUT request with instance options. Returns null on error. */
139
+ sput(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
140
+ /** Calls sfetchy as PATCH request with instance options. Returns null on error. */
141
+ spatch(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
142
+ /** Calls sfetchy as DELETE request with instance options. Returns null on error. */
143
+ sdelete(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
165
144
  }
145
+ /**
146
+ * Creates a new Fetchy instance with the specified options.
147
+ * Shorthand for `new Fetchy(options)`.
148
+ *
149
+ * @param options - Configuration options to apply to all requests made with this instance.
150
+ * @returns A new Fetchy instance.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * import { fy } from "@scirexs/fetchy";
155
+ *
156
+ * const client = fy({
157
+ * bearer: "token123",
158
+ * timeout: 10,
159
+ * base: "https://api.example.com"
160
+ * });
161
+ *
162
+ * const user = await client.get("/user").json<User>();
163
+ * const posts = await client.get("/posts").json<Post[]>();
164
+ * ```
165
+ */
166
+ declare function fy(options?: FetchyOptions): Fetchy;
166
167
  /**
167
168
  * Performs an HTTP request with safe error handling that returns null on failure.
168
- * Automatically parses the response body based on the specified parse method.
169
169
  * Unlike `fetchy`, this function never throws errors - it returns null for any failure.
170
170
  *
171
171
  * This is useful when you want to handle errors gracefully without try-catch blocks,
@@ -173,59 +173,46 @@ declare class Fetchy implements FetchyOptions {
173
173
  *
174
174
  * @param url - The URL to fetch. Can be a string, URL object, Request object, or null (uses options.url).
175
175
  * @param options - Configuration options for the request (timeout, retry, headers, etc.).
176
- * @param parse - Optional response body parsing method. If omitted, returns Response object.
177
- * Supported values: "json", "text", "bytes", "blob", "buffer".
178
- * @returns Parsed response body, Response object, or null if request fails or response is not OK.
176
+ * @returns Promise that resolves to Response object or null if request fails.
179
177
  *
180
178
  * @example
181
179
  * ```ts
182
180
  * import { sfetchy } from "@scirexs/fetchy";
183
181
  *
184
182
  * // Returns null instead of throwing on error
185
- * const data = await sfetchy("https://api.example.com/user", {}, "json");
186
- * if (data === null) {
183
+ * const response = await sfetchy("https://api.example.com/user");
184
+ * if (response === null) {
187
185
  * console.log("Request failed, using default data");
188
186
  * // Handle failure case
187
+ * } else {
188
+ * const data = await response.json();
189
189
  * }
190
190
  *
191
- * // Explicit type assertion with JSON parsing
192
- * interface User { id: number; name: string; }
193
- * const user = await sfetchy<User>("https://api.example.com/user", {}, "json");
191
+ * // Using convenience methods
192
+ * const user = await sfetchy("https://api.example.com/user").json<User>();
193
+ * if (user !== null) {
194
+ * // Handle successful response
195
+ * }
194
196
  *
195
197
  * // Text response - returns null on any error
196
- * const text = await sfetchy("https://example.com/page", {}, "text");
198
+ * const text = await sfetchy("https://example.com/page").text();
197
199
  *
198
200
  * // Binary data with safe error handling
199
- * const bytes = await sfetchy("https://example.com/image.png", {}, "bytes");
201
+ * const bytes = await sfetchy("https://example.com/image.png").bytes();
200
202
  * if (bytes !== null) {
201
203
  * // Process binary data
202
204
  * }
203
- *
204
- * // Raw Response object (no parsing)
205
- * const response = await sfetchy("https://api.example.com/data");
206
- * if (response !== null && response.ok) {
207
- * // Handle response
208
- * }
209
205
  * ```
210
206
  */
211
- declare function sfetchy(url: Input | null, options?: FetchyOptions, parse?: undefined): Promise<Response | null>;
212
- declare function sfetchy<T>(url: Input | null, options: FetchyOptions | undefined, parse: "json"): Promise<T | null>;
213
- declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "text"): Promise<string | null>;
214
- declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "bytes"): Promise<Uint8Array<ArrayBuffer> | null>;
215
- declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "blob"): Promise<Blob | null>;
216
- declare function sfetchy(url: Input | null, options: FetchyOptions | undefined, parse: "buffer"): Promise<ArrayBuffer | null>;
207
+ declare function sfetchy(url?: string | URL | Request | null, options?: FetchyOptions): FetchySafeResponse | null;
217
208
  /**
218
209
  * Performs an HTTP request with enhanced features like timeout, retry, and automatic header management.
219
210
  * Throws errors on failure unless configured otherwise via the `native` option.
220
- * Automatically parses the response body based on the specified parse method.
221
211
  *
222
212
  * @param url - The URL to fetch. Can be a string, URL object, Request object, or null (uses options.url).
223
213
  * @param options - Configuration options for the request (timeout, retry, headers, body, etc.).
224
- * @param parse - Optional response body parsing method. If omitted, returns Response object.
225
- * Supported values: "json", "text", "bytes", "blob", "buffer".
226
- * @returns Parsed response body or Response object.
227
- * @throws {HTTPStatusError} When response status is not OK (4xx, 5xx) - default behavior.
228
- * @throws {RedirectError} When redirect is encountered and redirect option is set to "error".
214
+ * @returns Promise that resolves to Response object.
215
+ * @throws {HTTPStatusError} When response status is not OK (4xx, 5xx) and native mode is disabled.
229
216
  * @throws {TypeError} When network error occurs (e.g., DNS resolution failure, connection refused).
230
217
  * @throws {DOMException} When request is aborted via timeout or AbortSignal.
231
218
  *
@@ -233,95 +220,104 @@ declare function sfetchy(url: Input | null, options: FetchyOptions | undefined,
233
220
  * ```ts
234
221
  * import { fetchy } from "@scirexs/fetchy";
235
222
  *
236
- * // Simple GET request returning Response object
223
+ * // Simple GET request
237
224
  * const response = await fetchy("https://api.example.com/data");
238
- * if (response.ok) {
239
- * const data = await response.json();
240
- * }
225
+ * const data = await response.json();
241
226
  *
242
- * // Direct JSON parsing with type assertion
243
- * interface User { id: number; name: string; }
244
- * const user = await fetchy<User>("https://api.example.com/user", {}, "json");
227
+ * // Using convenience methods
228
+ * const user = await fetchy("https://api.example.com/user").json<User>();
245
229
  *
246
230
  * // POST request with JSON body and authentication
247
231
  * const result = await fetchy("https://api.example.com/create", {
232
+ * method: MPOST,
248
233
  * body: { name: "John", age: 30 },
249
234
  * bearer: "your-token-here"
250
- * }, "json");
235
+ * }).json();
251
236
  *
252
237
  * // With retry, timeout, and error handling
253
238
  * try {
254
239
  * const data = await fetchy("https://api.example.com/data", {
255
240
  * timeout: 10,
256
- * retry: { max: 5, interval: 2, maxInterval: 30 }
257
- * }, "json");
241
+ * retry: { maxAttempts: 5, interval: 2, maxInterval: 30 }
242
+ * }).json();
258
243
  * } catch (error) {
259
244
  * if (error instanceof HTTPStatusError) {
260
- * console.error(`HTTP ${error.status}: ${error.body}`);
245
+ * console.error(`HTTP ${error.status}:`, error.message);
261
246
  * }
262
247
  * }
263
248
  *
264
- * // Native error mode - throws native fetch errors without HTTPStatusError
249
+ * // Native error mode - does not throw HTTPStatusError
265
250
  * const response = await fetchy("https://api.example.com/data", {
266
251
  * native: true
267
252
  * });
268
253
  * ```
269
254
  */
270
- declare function fetchy(url: Input | null, options?: FetchyOptions, parse?: undefined): Promise<Response>;
271
- declare function fetchy<T>(url: Input | null, options: FetchyOptions | undefined, parse: "json"): Promise<T>;
272
- declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "text"): Promise<string>;
273
- declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "bytes"): Promise<Uint8Array<ArrayBuffer>>;
274
- declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "blob"): Promise<Blob>;
275
- declare function fetchy(url: Input | null, options: FetchyOptions | undefined, parse: "buffer"): Promise<ArrayBuffer>;
276
- /** Main procedure of fetchy and sfetchy. */
277
- declare function _main<T>(url: Input | null, options?: FetchyOptions, parse?: ParseMethod): Promise<FetchyReturn<T>>;
278
- /** Checks if a value is a string. */
255
+ declare function fetchy(url?: string | URL | Request | null, options?: FetchyOptions): FetchyResponse;
256
+ /** Main procedure for fetchy and sfetchy. @internal */
257
+ declare function _main(url: InputArg | undefined, options: FetchyOptions | undefined, safe?: undefined): FetchyResponse;
258
+ declare function _main(url: InputArg | undefined, options: FetchyOptions | undefined, safe: true): FetchySafeResponse;
259
+ /** Creates new options object with specified HTTP method and temporal options. @internal */
260
+ declare function _buildOption(options?: FetchyOptions, temp?: FetchyOptions, method?: string): FetchyOptions;
261
+ /** Type guard: checks if value is a string. @internal */
279
262
  declare function _isString(v: unknown): v is string;
280
- /** Checks if a value is a number. */
263
+ /** Type guard: checks if value is a number. @internal */
281
264
  declare function _isNumber(v: unknown): v is number;
282
- /** Checks if a value is a boolean. */
265
+ /** Type guard: checks if value is a boolean. @internal */
283
266
  declare function _isBool(v: unknown): v is boolean;
284
- /** Checks if a value is a plain object (not array, null, or other object types). */
285
- declare function _isPlainObject(v: unknown): v is object;
286
- /** Corrects a number to be non-negative, using default if invalid. */
287
- declare function _correctNumber(dflt: number, num?: number, integer?: boolean): number;
288
- /** Gets retry option value from configuration with fallback to default. */
289
- declare function _getRetryOption(prop: keyof RetryOptions, off: number, options?: RetryOptions | false): number;
290
- declare function _getRetryOption(prop: keyof RetryOptions, off: boolean, options?: RetryOptions | false): boolean;
291
- /** Converts FetchyOptions to internal Options format with validated values. */
292
- declare function _getOptions(options?: FetchyOptions): Options;
293
- /** Converts FetchyOptions to standard RequestInit format. */
294
- declare function _getRequestInit(url: Input, opts: Options, options?: FetchyOptions): RequestInit;
295
- /** Converts FetchyBody to standard BodyInit format. */
296
- declare function _getBody(body: FetchyBody): BodyInit | undefined;
297
- /** Checks if a value should be treated as JSON object for serialization. */
267
+ /** Type guard: checks if value is a ReadableStream. @internal */
268
+ declare function _isStream(v: unknown): v is ReadableStream;
269
+ /** Type guard: checks if value is a Request. @internal */
270
+ declare function _isRequest(v: unknown): v is Request;
271
+ /** Type guard: checks if value is a plain object (not array, null, or other object types). @internal */
272
+ declare function _isPlain(v: unknown): v is object;
273
+ /** Corrects a number to be non-negative, using default if invalid. @internal */
274
+ declare function _correctNumber(dflt: number, num?: number): number;
275
+ /** Creates Request object from various input types. @internal */
276
+ declare function _createRequest(url?: InputArg, options?: FetchyOptions): Request;
277
+ /** Creates new Request with ReadableStream body if present in options. @internal */
278
+ declare function _includeStream(req: Request, options?: FetchyOptions): Request;
279
+ /** Converts FetchyOptions to standard RequestInit format. @internal */
280
+ declare function _getRequestInit(url?: InputArg, options?: FetchyOptions): RequestInit;
281
+ /** Converts FetchyBody to standard BodyInit format. @internal */
282
+ declare function _getBody(body?: FetchyBody): Record<string, BodyInit> | null;
283
+ /** Checks if value should be treated as JSON for serialization. @internal */
298
284
  declare function _isJSONObject(arg?: FetchyBody): boolean;
299
- /** Constructs request headers with automatic Content-Type and Authorization. */
300
- declare function _getHeaders(options?: FetchyOptions): Headers;
301
- /** Determines Content-Type header based on body type. */
302
- declare function _getContentType(body?: FetchyBody): string | undefined;
303
- /** Combine abort signals. */
304
- declare function _combineSignal(url: Input, timeout: number, signal?: AbortSignal | null): AbortSignal | undefined;
305
- /** Parse response body. */
306
- declare function _parseBody<T>(resp: Response, method: ParseMethod): Promise<Exclude<FetchyReturn<T>, Response>>;
307
- /** Waits for specified seconds with optional randomization. */
285
+ /** Constructs request headers with automatic Content-Type and Authorization. @internal */
286
+ declare function _getHeaders(options?: FetchyOptions, reqHeaders?: Headers | null): Headers;
287
+ /** Checks if header is absent in both option headers and request headers. @internal */
288
+ declare function _isNoHeader(name: string, optionHeader: Headers, reqHeaders?: Headers | null): boolean;
289
+ /** Determines Content-Type header based on body type. @internal */
290
+ declare function _getContentType(body?: FetchyBody): string;
291
+ /** Checks if Content-Type should be handled by native fetch. @internal */
292
+ declare function _handleByNative(body?: FetchyBody): boolean;
293
+ /** Extracts retry-related options with defaults. @internal */
294
+ declare function _getRetryOption(init: RequestInit, options?: RetryOptions | false): InternalRetry;
295
+ /** Converts FetchyOptions to internal Options format with validated values. @internal */
296
+ declare function _getOptions(init: RequestInit, url?: InputArg, options?: FetchyOptions): Options;
297
+ /** Merges multiple AbortSignals into one. @internal */
298
+ declare function _mergeSignals(s1?: AbortSignal | null, s2?: AbortSignal | null): AbortSignal | undefined;
299
+ /** Creates timeout signal and merges with existing signal. @internal */
300
+ declare function _withTimeout(opts: Options): AbortSignal | undefined;
301
+ /** Waits for specified seconds with optional randomization. @internal */
308
302
  declare function _wait(sec: number, random?: boolean): Promise<void>;
309
- /** Checks if response is a redirect (3xx status). */
310
- declare function _shouldRedirect(resp: Response): boolean;
311
- /** Checks if response is a client error (4xx status). */
312
- declare function _shouldCorrectRequest(resp: Response): boolean;
313
- /** Determines if retry should stop based on conditions and waits if continuing. */
314
- declare function _shouldNotRetry(count: number, init: RequestInit, opts: Options, resp?: Response): Promise<boolean>;
315
- /** Calculates next retry interval using exponential backoff or Retry-After header. */
316
- declare function _getNextInterval(count: number, opts: Options, resp?: Response): number;
317
- /** Parses Retry-After header value to seconds. */
318
- declare function _parseRetryAfter(value: string): number;
319
- /** Updates URL and method for redirect responses. */
320
- declare function _handleRedirectResponse(url: Input, init: RequestInit, resp: Response): Input;
321
- /** Clone input if required. */
322
- declare function _cloneInput(url: Input, required: boolean): Input;
323
- /** Executes fetch with retry logic and exponential backoff. */
324
- declare function _fetchWithRetry(url: Input, init: RequestInit, opts: Options): Promise<Response>;
325
- /** Executes fetch with initial jitter delay. */
326
- declare function _fetchWithJitter(url: Input, init: RequestInit, opts: Options): Promise<Response>;
303
+ /** Checks if HTTP status code indicates an error. @internal */
304
+ declare function _isHttpError(stat: number): boolean;
305
+ /** Determines whether to retry based on conditions and waits before next attempt. @internal */
306
+ declare function _shouldRetry(count: number, opts: Options, r: Response | unknown): Promise<boolean>;
307
+ /** Calculates next retry interval using exponential backoff or response headers. @internal */
308
+ declare function _getNextInterval(count: number, opts: Options, headers: Headers): number;
309
+ /** Finds and parses retry timing from response headers. @internal */
310
+ declare function _findRetryHeader(opts: Options, headers: Headers): number | undefined;
311
+ /** Parses retry header value to seconds. @internal */
312
+ declare function _parseRetryHeader(value?: string | null): number;
313
+ /** Fetch with retry and creates promise-like object. @internal */
314
+ declare function _makeFetchyResponse(req: Request, init: RequestInit, opts: Options, safe?: boolean): FetchyResponse | FetchySafeResponse;
315
+ /** Creates promise-like object with convenience parsing methods. @internal */
316
+ declare function _assignToPromise(resp: Promise<Response | null>, safe: boolean): FetchyResponse | FetchySafeResponse;
317
+ /** Creates request cloning function with abort handling. @internal */
318
+ declare function _cloneRequestF(req: Request): (cancel?: boolean) => Promise<Request>;
319
+ /** Executes fetch with retry logic and exponential backoff. @internal */
320
+ declare function _fetchWithRetry(req: Request, init: RequestInit, opts: Options, safe: boolean): Promise<Response | null>;
321
+ /** Executes fetch with initial jitter delay. @internal */
322
+ declare function _fetchWithJitter(req: Request, init: RequestInit, opts: Options): Promise<Response>;
327
323
  //# sourceMappingURL=main.d.ts.map