@ahoo-wang/fetcher 0.8.2 → 0.8.3
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/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/fetchInterceptor.d.ts +4 -2
- package/dist/fetchInterceptor.d.ts.map +1 -1
- package/dist/index.es.js +3 -3
- package/dist/index.umd.js +1 -1
- package/dist/requestBodyInterceptor.d.ts +3 -2
- package/dist/requestBodyInterceptor.d.ts.map +1 -1
- package/dist/urlResolveInterceptor.d.ts +6 -0
- package/dist/urlResolveInterceptor.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,9 +121,9 @@ responses, and errors at different stages of the HTTP request lifecycle.
|
|
|
121
121
|
|
|
122
122
|
Fetcher comes with several built-in interceptors that are automatically registered:
|
|
123
123
|
|
|
124
|
-
1. **UrlResolveInterceptor**: Resolves URLs with path and query parameters (order: Number.MIN_SAFE_INTEGER)
|
|
125
|
-
2. **RequestBodyInterceptor**: Converts object bodies to JSON strings (order: Number.MIN_SAFE_INTEGER +
|
|
126
|
-
3. **FetchInterceptor**: Executes the actual HTTP request (order: Number.MAX_SAFE_INTEGER)
|
|
124
|
+
1. **UrlResolveInterceptor**: Resolves URLs with path and query parameters (order: Number.MIN_SAFE_INTEGER + 100)
|
|
125
|
+
2. **RequestBodyInterceptor**: Converts object bodies to JSON strings (order: Number.MIN_SAFE_INTEGER + 200)
|
|
126
|
+
3. **FetchInterceptor**: Executes the actual HTTP request (order: Number.MAX_SAFE_INTEGER - 100)
|
|
127
127
|
|
|
128
128
|
### Using Interceptors
|
|
129
129
|
|
package/README.zh-CN.md
CHANGED
|
@@ -119,9 +119,9 @@ Fetcher 中的拦截器系统遵循中间件模式,允许您在 HTTP 请求生
|
|
|
119
119
|
|
|
120
120
|
Fetcher 自带几个内置拦截器,它们会自动注册:
|
|
121
121
|
|
|
122
|
-
1. **UrlResolveInterceptor**:解析带路径和查询参数的 URL(顺序:Number.MIN_SAFE_INTEGER)
|
|
123
|
-
2. **RequestBodyInterceptor**:将对象体转换为 JSON 字符串(顺序:Number.MIN_SAFE_INTEGER +
|
|
124
|
-
3. **FetchInterceptor**:执行实际的 HTTP 请求(顺序:Number.MAX_SAFE_INTEGER)
|
|
122
|
+
1. **UrlResolveInterceptor**:解析带路径和查询参数的 URL(顺序:Number.MIN_SAFE_INTEGER + 100)
|
|
123
|
+
2. **RequestBodyInterceptor**:将对象体转换为 JSON 字符串(顺序:Number.MIN_SAFE_INTEGER + 200)
|
|
124
|
+
3. **FetchInterceptor**:执行实际的 HTTP 请求(顺序:Number.MAX_SAFE_INTEGER - 100)
|
|
125
125
|
|
|
126
126
|
### 使用拦截器
|
|
127
127
|
|
|
@@ -23,12 +23,14 @@ export declare class FetchInterceptor implements Interceptor {
|
|
|
23
23
|
*/
|
|
24
24
|
name: string;
|
|
25
25
|
/**
|
|
26
|
-
* Interceptor execution order, set to maximum safe integer to ensure last execution
|
|
26
|
+
* Interceptor execution order, set to near maximum safe integer to ensure last execution
|
|
27
27
|
*
|
|
28
28
|
* @remarks
|
|
29
29
|
* Since this is the interceptor that actually executes HTTP requests, it should
|
|
30
30
|
* execute after all other request interceptors, so its order is set to
|
|
31
|
-
* Number.MAX_SAFE_INTEGER
|
|
31
|
+
* Number.MAX_SAFE_INTEGER - 100. This ensures that all request preprocessing is
|
|
32
|
+
* completed before the actual network request is made, while still allowing
|
|
33
|
+
* other interceptors to run after it if needed.
|
|
32
34
|
*/
|
|
33
35
|
order: number;
|
|
34
36
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchInterceptor.d.ts","sourceRoot":"","sources":["../src/fetchInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD;;;;;;OAMG;IACH,IAAI,SAAsB;IAE1B
|
|
1
|
+
{"version":3,"file":"fetchInterceptor.d.ts","sourceRoot":"","sources":["../src/fetchInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD;;;;;;OAMG;IACH,IAAI,SAAsB;IAE1B;;;;;;;;;OASG;IACH,KAAK,SAAiC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAQjE"}
|
package/dist/index.es.js
CHANGED
|
@@ -113,7 +113,7 @@ function a(r, e) {
|
|
|
113
113
|
}
|
|
114
114
|
class O {
|
|
115
115
|
constructor() {
|
|
116
|
-
this.name = "RequestBodyInterceptor", this.order = Number.MIN_SAFE_INTEGER +
|
|
116
|
+
this.name = "RequestBodyInterceptor", this.order = Number.MIN_SAFE_INTEGER + 200;
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Attempts to convert request body to a valid fetch API body type
|
|
@@ -164,7 +164,7 @@ class O {
|
|
|
164
164
|
}
|
|
165
165
|
class P {
|
|
166
166
|
constructor() {
|
|
167
|
-
this.name = "FetchInterceptor", this.order = Number.MAX_SAFE_INTEGER;
|
|
167
|
+
this.name = "FetchInterceptor", this.order = Number.MAX_SAFE_INTEGER - 100;
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
170
|
* Intercept and process HTTP requests
|
|
@@ -200,7 +200,7 @@ class P {
|
|
|
200
200
|
}
|
|
201
201
|
class R {
|
|
202
202
|
constructor() {
|
|
203
|
-
this.name = "UrlResolveInterceptor", this.order = Number.MIN_SAFE_INTEGER;
|
|
203
|
+
this.name = "UrlResolveInterceptor", this.order = Number.MIN_SAFE_INTEGER + 100;
|
|
204
204
|
}
|
|
205
205
|
/**
|
|
206
206
|
* Resolves the final URL by combining the base URL, path parameters, and query parameters
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(n,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(n=typeof globalThis<"u"?globalThis:n||self,u(n.Fetcher={}))})(this,(function(n){"use strict";function u(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function E(r,e){return u(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class I{constructor(e){this.baseURL=e}build(e,t,s){const i=E(this.baseURL,e);let o=this.interpolateUrl(i,t);if(s){const a=new URLSearchParams(s).toString();a&&(o+="?"+a)}return o}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(s,i)=>{const o=t[i];if(o===void 0)throw new Error(`Missing required path parameter: ${i}`);return String(o)}):e}}function F(r,e){return typeof r<"u"?r:e}class h extends Error{constructor(e,t,s){const i=t.method||"GET",o=`Request timeout of ${s}ms exceeded for ${i} ${e}`;super(o),this.name="FetchTimeoutError",this.url=e,this.request=t,this.timeout=s,Object.setPrototypeOf(this,h.prototype)}}async function R(r,e,t){if(!t)return fetch(r,e);const s=new AbortController,i={...e,signal:s.signal};let o=null;const a=new Promise((_,b)=>{o=setTimeout(()=>{o&&clearTimeout(o);const L=new h(r,e,t);s.abort(L),b(L)},t)});try{return await Promise.race([fetch(r,i),a])}finally{o&&clearTimeout(o)}}var c=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(c||{}),w=(r=>(r.METHOD="method",r.BODY="body",r))(w||{});const d="Content-Type";var l=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(l||{});function m(r,e){return e?r.filter(e).sort((t,s)=>t.order-s.order):[...r].sort((t,s)=>t.order-s.order)}class A{constructor(){this.name="RequestBodyInterceptor",this.order=Number.MIN_SAFE_INTEGER+
|
|
1
|
+
(function(n,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(n=typeof globalThis<"u"?globalThis:n||self,u(n.Fetcher={}))})(this,(function(n){"use strict";function u(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function E(r,e){return u(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class I{constructor(e){this.baseURL=e}build(e,t,s){const i=E(this.baseURL,e);let o=this.interpolateUrl(i,t);if(s){const a=new URLSearchParams(s).toString();a&&(o+="?"+a)}return o}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(s,i)=>{const o=t[i];if(o===void 0)throw new Error(`Missing required path parameter: ${i}`);return String(o)}):e}}function F(r,e){return typeof r<"u"?r:e}class h extends Error{constructor(e,t,s){const i=t.method||"GET",o=`Request timeout of ${s}ms exceeded for ${i} ${e}`;super(o),this.name="FetchTimeoutError",this.url=e,this.request=t,this.timeout=s,Object.setPrototypeOf(this,h.prototype)}}async function R(r,e,t){if(!t)return fetch(r,e);const s=new AbortController,i={...e,signal:s.signal};let o=null;const a=new Promise((_,b)=>{o=setTimeout(()=>{o&&clearTimeout(o);const L=new h(r,e,t);s.abort(L),b(L)},t)});try{return await Promise.race([fetch(r,i),a])}finally{o&&clearTimeout(o)}}var c=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(c||{}),w=(r=>(r.METHOD="method",r.BODY="body",r))(w||{});const d="Content-Type";var l=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(l||{});function m(r,e){return e?r.filter(e).sort((t,s)=>t.order-s.order):[...r].sort((t,s)=>t.order-s.order)}class A{constructor(){this.name="RequestBodyInterceptor",this.order=Number.MIN_SAFE_INTEGER+200}intercept(e){const t=e.request;if(t.body===void 0||t.body===null||typeof t.body!="object"||t.body instanceof ArrayBuffer||ArrayBuffer.isView(t.body)||t.body instanceof Blob||t.body instanceof File||t.body instanceof URLSearchParams||t.body instanceof FormData||t.body instanceof ReadableStream)return e;const s={...t};s.body=JSON.stringify(t.body),s.headers||(s.headers={});const i=s.headers;return i[d]||(i[d]=l.APPLICATION_JSON),e.request=s,e}}class N{constructor(){this.name="FetchInterceptor",this.order=Number.MAX_SAFE_INTEGER-100}async intercept(e){return e.response=await R(e.url,e.request,e.request.timeout),e}}class O{constructor(){this.name="UrlResolveInterceptor",this.order=Number.MIN_SAFE_INTEGER+100}intercept(e){return e.url=e.fetcher.urlBuilder.build(e.url,e.request.path,e.request.query),e}}class f{constructor(e=[]){this.sortedInterceptors=[],this.sortedInterceptors=m(e)}get name(){return this.constructor.name}get order(){return Number.MIN_SAFE_INTEGER}use(e){return this.sortedInterceptors.some(t=>t.name===e.name)?!1:(this.sortedInterceptors=m([...this.sortedInterceptors,e]),!0)}eject(e){const t=this.sortedInterceptors;return this.sortedInterceptors=m(t,s=>s.name!==e),t.length!==this.sortedInterceptors.length}clear(){this.sortedInterceptors=[]}async intercept(e){let t=e;for(const s of this.sortedInterceptors)t=await s.intercept(t);return t}}class S{constructor(){this.request=new f([new O,new A,new N]),this.response=new f,this.error=new f}}const T={[d]:l.APPLICATION_JSON},p={baseURL:"",headers:T};class g{constructor(e=p){this.headers=T,this.urlBuilder=new I(e.baseURL),this.headers=e.headers??T,this.timeout=e.timeout,this.interceptors=e.interceptors??new S}async fetch(e,t={}){const s=await this.request(e,t);if(!s.response)throw new Error(`Request to ${s.url} failed with no response`);return s.response}async request(e,t={}){const s={...this.headers||{},...t.headers||{}},i={...t,headers:Object.keys(s).length>0?s:void 0,timeout:F(t.timeout,this.timeout)},o={fetcher:this,url:e,request:i,response:void 0,error:void 0,attributes:{}};return this.exchange(o)}async exchange(e){try{return e=await this.interceptors.request.intercept(e),e=await this.interceptors.response.intercept(e),e}catch(t){if(e.error=t,e=await this.interceptors.error.intercept(e),e.response)return e;throw e.error}}async methodFetch(e,t,s={}){return this.fetch(t,{...s,method:e})}async get(e,t={}){return this.methodFetch(c.GET,e,t)}async post(e,t={}){return this.methodFetch(c.POST,e,t)}async put(e,t={}){return this.methodFetch(c.PUT,e,t)}async delete(e,t={}){return this.methodFetch(c.DELETE,e,t)}async patch(e,t={}){return this.methodFetch(c.PATCH,e,t)}async head(e,t={}){return this.methodFetch(c.HEAD,e,t)}async options(e,t={}){return this.methodFetch(c.OPTIONS,e,t)}}const y="default";class P{constructor(){this.registrar=new Map}register(e,t){this.registrar.set(e,t)}unregister(e){return this.registrar.delete(e)}get(e){return this.registrar.get(e)}requiredGet(e){const t=this.get(e);if(!t)throw new Error(`Fetcher ${e} not found`);return t}get default(){return this.requiredGet(y)}set default(e){this.register(y,e)}get fetchers(){return new Map(this.registrar)}}const q=new P;function D(r,e){if(Object.keys(r).length===0)return e;if(Object.keys(e).length===0)return r;const t={...r.path,...e.path},s={...r.query,...e.query},i={...r.headers,...e.headers},o=e.method??r.method,a=e.body??r.body,_=e.timeout??r.timeout,b=e.signal??r.signal;return{...r,...e,method:o,path:t,query:s,headers:i,body:a,timeout:_,signal:b}}class U extends g{constructor(e,t=p){super(t),this.name=e,q.register(e,this)}}const v=new U(y);n.ContentTypeHeader=d,n.ContentTypeValues=l,n.DEFAULT_FETCHER_NAME=y,n.DEFAULT_OPTIONS=p,n.FetchInterceptor=N,n.FetchTimeoutError=h,n.Fetcher=g,n.FetcherInterceptors=S,n.FetcherRegistrar=P,n.HttpMethod=c,n.InterceptorManager=f,n.NamedFetcher=U,n.RequestBodyInterceptor=A,n.RequestField=w,n.UrlBuilder=I,n.UrlResolveInterceptor=O,n.combineURLs=E,n.fetcher=v,n.fetcherRegistrar=q,n.isAbsoluteURL=u,n.mergeRequest=D,n.resolveTimeout=F,n.timeoutFetch=R,n.toSorted=m,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -23,8 +23,9 @@ export declare class RequestBodyInterceptor implements Interceptor {
|
|
|
23
23
|
* @remarks
|
|
24
24
|
* This interceptor should run after URL resolution (UrlResolveInterceptor) but before
|
|
25
25
|
* the actual HTTP request is made (FetchInterceptor). The order is set to
|
|
26
|
-
* Number.MIN_SAFE_INTEGER +
|
|
27
|
-
* in the interceptor chain
|
|
26
|
+
* Number.MIN_SAFE_INTEGER + 200 to ensure it executes in the correct position
|
|
27
|
+
* in the interceptor chain, allowing for other interceptors to run between URL resolution
|
|
28
|
+
* and request body processing.
|
|
28
29
|
*/
|
|
29
30
|
order: number;
|
|
30
31
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestBodyInterceptor.d.ts","sourceRoot":"","sources":["../src/requestBodyInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IACxD;;OAEG;IACH,IAAI,SAA4B;IAEhC
|
|
1
|
+
{"version":3,"file":"requestBodyInterceptor.d.ts","sourceRoot":"","sources":["../src/requestBodyInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,qBAAa,sBAAuB,YAAW,WAAW;IACxD;;OAEG;IACH,IAAI,SAA4B;IAEhC;;;;;;;;;OASG;IACH,KAAK,SAAiC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CA2ClD"}
|
|
@@ -26,6 +26,12 @@ export declare class UrlResolveInterceptor implements Interceptor {
|
|
|
26
26
|
name: string;
|
|
27
27
|
/**
|
|
28
28
|
* The order of this interceptor (executed first)
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* This interceptor should run first in the request interceptor chain to ensure
|
|
32
|
+
* URL resolution happens before any other request processing. The order is set to
|
|
33
|
+
* Number.MIN_SAFE_INTEGER + 100 to allow for other interceptors that need to run
|
|
34
|
+
* even earlier while still maintaining a high priority.
|
|
29
35
|
*/
|
|
30
36
|
order: number;
|
|
31
37
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlResolveInterceptor.d.ts","sourceRoot":"","sources":["../src/urlResolveInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACvD;;OAEG;IACH,IAAI,SAA2B;IAE/B
|
|
1
|
+
{"version":3,"file":"urlResolveInterceptor.d.ts","sourceRoot":"","sources":["../src/urlResolveInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACvD;;OAEG;IACH,IAAI,SAA2B;IAE/B;;;;;;;;OAQG;IACH,KAAK,SAAiC;IAEtC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CAQlD"}
|