soon-fetch 3.0.0-beta.3 → 3.0.0-beta.4

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 CHANGED
@@ -10,7 +10,7 @@
10
10
  > - ⭐ rapid define a request api
11
11
  > - ⌛ timeout disconnect
12
12
  > - 🔤 automatic parse or serialization of JSON
13
- > - 📏 .min size less than **3K**, smaller after zip
13
+ > - 📏 .min size less than **5K**, smaller after zip
14
14
  > - 💡 smart type tips with Typescript
15
15
 
16
16
  - [Example](#example)
@@ -150,7 +150,8 @@ export default function App() {
150
150
 
151
151
  ```typescript
152
152
  //can be GET POST PATCH PUT DELETE
153
-
153
+ soon.GET(url:string).Query<Query>().Send<Response>()
154
+ soon.POST(url:string).Body<Body>().Send<Response>()
154
155
  //define an api
155
156
  export const getUserInfo = soon.GET("/user/:id").Send();
156
157
  //then use in any where
@@ -347,19 +348,22 @@ export default function App() {
347
348
 
348
349
  ##### 快速定义 API
349
350
 
350
- ```typescript
351
+ ```ts
351
352
  //可以是 GET POST PATCH PUT DELETE
352
353
  //GET 请求数据传递至query,其他方法请求数据传递至body
353
- soon.API(url:string).POST<RequestType,ResponseType>()
354
+ soon.GET(url:string).Query<Query>().Send<Response>()
355
+ soon.POST(url:string).Body<Body>().Send<Response>()
354
356
 
355
357
  //定义一个api
356
- export const getUserInfo=soon.API('/user/:id').GET()
358
+ export const getUserInfo=soon.GET('/user/:id').Send()
357
359
  //使用
358
360
  getUserInfo({id:2}).then(res=>console.log(res))
359
361
 
360
362
  //用typescript,
361
- export const login=soon.API('/user/login')
362
- .POST<{username:string,password:string},{token:string}>()
363
+ export const login=soon
364
+ .POST('/user/login')
365
+ .Body<{username:string,password:string}>()
366
+ .Send<{token:string}>()
363
367
  //开发工具会有请求和响应的智能提醒
364
368
  login({username:'admin',password:'123'}).then(res=>{
365
369
  localStorage.setItem('token', res.token);
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";const e=e=>{const t=[],n=e.match(/:([^:/\d]+)\/?/g);return n&&n.forEach((e=>{t.push(e.replace(/\//g,"").replace(/:/g,""))})),t},t=(e="")=>e.endsWith("/")?e.slice(0,-1):e,n=(e="")=>e.startsWith("/")?e:"/"+e,r=(e="")=>e.startsWith("http"),o=e=>{if(!e)return[];if(e instanceof URLSearchParams||"string"==typeof e||Array.isArray(e))return Array.from(new URLSearchParams(e).entries());const t=[];return Object.keys(e).forEach((n=>{const r=e[n];(Array.isArray(r)?r:[r]).forEach((e=>{t.push([n,e??""])}))})),t},s=(s,a)=>{const{query:i,params:c,baseURL:f}=a;let p=s.trim();e(s).forEach((e=>{c&&(p=p.replace(":"+e,""+c[e]))}));const[u,l]=p.split("?"),h=new URLSearchParams([...o(l),...o(i)]);let y=((e,o)=>{if(r(e))return e;const s=r(o)?o:n(o);return t(s)+t(n(e))})(u,f);return h.size&&(y=y+"?"+h),y},a=(...e)=>{const t=new Headers;return e.forEach((e=>{e&&new Headers(e).forEach(((e,n)=>{t.set(n,e)}))})),t};function i(e,t){const n=(e??[]).filter((e=>!!e));return t&&n.push(AbortSignal.timeout(t)),n.length?AbortSignal.any(n):void 0}function c(e){return!(!e||"object"!=typeof e||(e instanceof Blob||e instanceof ArrayBuffer||e instanceof FormData||e instanceof File||e instanceof DataView||e instanceof URLSearchParams||e instanceof ReadableStream||(t=e,t instanceof Int8Array||t instanceof Uint8Array||t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array||t instanceof BigInt64Array||t instanceof BigUint64Array)));var t}function f(...e){const t=Object.assign({},...e),n=a(...e.map((e=>e?.headers)));return t.headers=n,t.signal=i(e.map((e=>e?.signal)),t.timeout),t}function p(e){const{url:t,options:n,baseURL:r,baseOptions:o}=e,a=f(o,n),p=s(t,{...a,baseURL:r}),u=a?.body,l=c(u);return a.body=l?JSON.stringify(u):u,l&&a.headers.append("Content-Type","application/json"),a.signal=i([a.signal]),[p,a]}const u=["get","post","put","delete","patch"];function l(e,t){const n={};return e.forEach((e=>{n[e]=t(e)})),n}function h(t){const n=(n,r,o)=>{const s=!!e(n).length;return(...e)=>{const a=[...e],{hasBody:i,hasQuery:c}=o||{},f=s?a.shift():void 0,p=c?a.shift():void 0,u=i?a.shift():void 0,l=a.shift();return t(n,r,f,p,u,l,o?.options)}},r={};return u.forEach((e=>{const t=e.toUpperCase();r[t]=t=>({Send:r=>n(t,e,{options:r}),Body:()=>({Send:r=>n(t,e,{hasBody:!0,options:r})}),Query:()=>({Send:r=>n(t,e,{hasQuery:!0,options:r}),Body:()=>({Send:r=>n(t,e,{hasBody:!0,hasQuery:!0,options:r})})})})})),r}function y(e,t){t&&(t.pop()?.abort("soon-fetch race abort"),t.push(e))}function d(e){if(Array.isArray(e))return e.map(d);if("object"==typeof e&&null!==e){const t={};return Object.keys(e).sort().forEach((n=>{t[n]=d(e[n])})),t}return e}function g(e){const{url:t,headers:n,method:r,body:o,query:s,params:a}=e,i=d(Object.fromEntries(n?.entries()??[]));return(r??"get").toLowerCase()+t+JSON.stringify(d(s)??"")+JSON.stringify(d(a)??"")+JSON.stringify(i)+("object"==typeof o&&null!=o?JSON.stringify(d(o)):o)}function m(){const e={},t=[];setInterval((()=>{const n=Date.now();for(let r=t.length-1;r>=0;r--)t[r].expiredTime<n&&(delete e[t[r].key],t.splice(r,1))}),6e4);const n=e=>e instanceof Response?e.clone():"function"==typeof e||e instanceof Promise?e:structuredClone(e);function r(n){delete e[n];for(let e=t.length-1;e>=0;e--)if(t[e].key===n){t.splice(e,1);break}}return{get:function(t){const o=e[t];if(void 0!==o)return o.expiredTime>Date.now()?n(o.data):void r(t)},set:function(r,o,s){e[r]={data:n(o),expiredTime:s},t.push({key:r,expiredTime:s})},remove:r}}function b(){const e={},t=t=>e[t]=void 0;return{get:t=>e[t],set:(n,r)=>{e[n]=r,r.finally((()=>t(n)))}}}exports.createCache=m,exports.createShare=b,exports.createShortApi=h,exports.createShortMethods=l,exports.createSilentRefresh=function(e){let t=[],n=!1;return(r,o)=>{t.push({success:r,fail:o}),n||(n=!0,e().then((()=>{t.forEach((e=>e.success()))})).catch((e=>{t.forEach((e=>e.fail()))})).finally((()=>{n=!1,t=[]})))}},exports.createSoon=function(e,t){const n=m(),r=b(),o=(o,s)=>new Promise(((a,c)=>{const f=new AbortController,u=e(o,s),[l,h]=p(u);console.log("[init]",l,h,u),h.signal=i([f.signal,h.signal]);const d={url:l,options:h},m=t({parsed:d}),b=g({url:d.url,...d.options,headers:new Headers(d.options?.headers)});if(d.options?.share){const e=r.get(b);if(e)return a(e)}if(d.options?.staleTime){const e=n.get(b);if(void 0!==e)return a(e)}console.log("abort",b,d.options),y(f,d.options?.aborts);const A=m(o,s);d.options?.share&&r.set(b,A),A.then((e=>{a(e),d.options?.staleTime&&n.set(b,e,(new Date).getTime()+d.options.staleTime)})).catch((e=>c(e)))})),s=h(((e,t,n,r,s,a,i)=>o(e,{...i,...a,method:t,params:n,query:r,body:s}))),a=l([...u,"head","options"],(e=>(t,n)=>o(t,{...n,method:e})));return{request:o,...s,...a}},exports.deepSort=d,exports.genRequestKey=g,exports.isBodyJson=c,exports.mergeHeaders=a,exports.mergeOptions=f,exports.mergeSignals=i,exports.mergeUrl=s,exports.parseUrlOptions=p,exports.raceAbort=y;
1
+ "use strict";const e=e=>{const t=[],r=e.match(/:([^:/\d]+)\/?/g);return r&&r.forEach((e=>{t.push(e.replace(/\//g,"").replace(/:/g,""))})),t},t=(e="")=>e.endsWith("/")?e.slice(0,-1):e,r=(e="")=>e.startsWith("/")?e:"/"+e,n=(e="")=>e.startsWith("http"),o=e=>{if(!e)return[];if(e instanceof URLSearchParams||"string"==typeof e||Array.isArray(e))return Array.from(new URLSearchParams(e).entries());const t=[];return Object.keys(e).forEach((r=>{const n=e[r];(Array.isArray(n)?n:[n]).forEach((e=>{t.push([r,e??""])}))})),t},s=(s,a)=>{const{query:i,params:c,baseURL:f}=a;let p=s.trim();e(s).forEach((e=>{c&&(p=p.replace(":"+e,""+c[e]))}));const[u,l]=p.split("?"),h=new URLSearchParams([...o(l),...o(i)]);let y=((e,o)=>{if(n(e))return e;const s=n(o)?o:r(o);return t(s)+t(r(e))})(u,f);return h.size&&(y=y+"?"+h),y},a=(...e)=>{const t=new Headers;return e.forEach((e=>{e&&new Headers(e).forEach(((e,r)=>{t.set(r,e)}))})),t};function i(e,t){const r=(e??[]).filter((e=>!!e));return t&&r.push(AbortSignal.timeout(t)),r.length?AbortSignal.any(r):void 0}function c(e){return!(!e||"object"!=typeof e||(e instanceof Blob||e instanceof ArrayBuffer||e instanceof FormData||e instanceof File||e instanceof DataView||e instanceof URLSearchParams||e instanceof ReadableStream||(t=e,t instanceof Int8Array||t instanceof Uint8Array||t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array||t instanceof BigInt64Array||t instanceof BigUint64Array)));var t}function f(...e){const t=Object.assign({},...e),r=a(...e.map((e=>e?.headers)));return t.headers=r,t.signal=i(e.map((e=>e?.signal)),t.timeout),t}function p(e){const{url:t,options:r,baseURL:n,baseOptions:o}=e,a=f(o,r),p=s(t,{...a,baseURL:n}),u=a?.body,l=c(u);a.body=l?JSON.stringify(u):u,l&&a.headers.append("Content-Type","application/json");const h=new AbortController;return a.signal=i([a.signal,h.signal]),{url:p,options:a,is_body_json:l,abortController:h}}const u=["get","post","put","delete","patch"];function l(e,t){const r={};return e.forEach((e=>{r[e]=t(e)})),r}function h(t){const r=(r,n,o)=>{const s=!!e(r).length;return(...e)=>{const a=[...e],{hasBody:i,hasQuery:c}=o||{},f=s?a.shift():void 0,p=c?a.shift():void 0,u=i?a.shift():void 0,l=a.shift();return t(r,n,f,p,u,l,o?.options)}},n={};return u.forEach((e=>{const t=e.toUpperCase();n[t]=t=>({Send:n=>r(t,e,{options:n}),Body:()=>({Send:n=>r(t,e,{hasBody:!0,options:n})}),Query:()=>({Send:n=>r(t,e,{hasQuery:!0,options:n}),Body:()=>({Send:n=>r(t,e,{hasBody:!0,hasQuery:!0,options:n})})})})})),n}function y(e,t){t&&(t.pop()?.abort("race abort"),t.push(e))}function d(e){if(Array.isArray(e))return e.map(d);if("object"==typeof e&&null!==e){const t={};return Object.keys(e).sort().forEach((r=>{t[r]=d(e[r])})),t}return e}function g(e){const{url:t,options:r}=e,{headers:n,method:o,body:s,query:a,params:i}=r??{},c=d(Object.fromEntries(new Headers(n).entries()??[]));return(o??"get").toLowerCase()+t+JSON.stringify(d(a)??"")+JSON.stringify(d(i)??"")+JSON.stringify(c)+("object"==typeof s&&null!=s?JSON.stringify(d(s)):s??"")}function m(){const e={},t=[];setInterval((()=>{const r=Date.now();for(let n=t.length-1;n>=0;n--)t[n].expiredTime<r&&(delete e[t[n].key],t.splice(n,1))}),6e4);const r=e=>e instanceof Response?e.clone():"function"==typeof e||e instanceof Promise?e:structuredClone(e);function n(r){delete e[r];for(let e=t.length-1;e>=0;e--)if(t[e].key===r){t.splice(e,1);break}}return{get:function(t){const o=e[t];if(void 0!==o)return o.expiredTime>Date.now()?r(o.data):void n(t)},set:function(n,o,s){e[n]={data:r(o),expiredTime:s},t.push({key:n,expiredTime:s})},remove:n}}function b(){const e={},t=t=>e[t]=void 0;return{get:t=>e[t],set:(r,n)=>{e[r]=n,n.finally((()=>t(r)))}}}exports.createCache=m,exports.createShare=b,exports.createShortApi=h,exports.createShortMethods=l,exports.createSilentRefresh=function(e){let t=[],r=!1;return(n,o)=>{t.push({success:n,fail:o}),r||(r=!0,e().then((()=>{t.forEach((e=>e.success()))})).catch((e=>{t.forEach((e=>e.fail()))})).finally((()=>{r=!1,t=[]})))}},exports.createSoon=function(e,t){const r=m(),n=b(),o=(o,s)=>new Promise(((a,i)=>{const c=p(e(o,s)),f=g(c),{abortController:u}=c,l=new AbortController;l.signal.addEventListener("abort",(()=>{i(l.signal.reason)}));const h=t({parsed:{...c,requestKey:f}});if(c.options?.share){const e=n.get(f);if(e)return a(e)}if(y(c.options.share?l:u,c.options?.aborts),c.options?.staleTime){const e=r.get(f);if(void 0!==e)return a(e)}const d=h(o,s);c.options?.share&&n.set(f,d),d.then((e=>{a(e),c.options?.staleTime&&r.set(f,e,(new Date).getTime()+c.options.staleTime)})).catch((e=>i(e)))})),s=h(((e,t,r,n,s,a,i)=>o(e,{...i,...a,method:t,params:r,query:n,body:s}))),a=l([...u,"head","options"],(e=>(t,r)=>o(t,{...r,method:e})));return{request:o,...s,...a}},exports.deepSort=d,exports.genRequestKey=g,exports.isBodyJson=c,exports.mergeHeaders=a,exports.mergeOptions=f,exports.mergeSignals=i,exports.mergeUrl=s,exports.parseUrlOptions=function(e){const{url:t,options:r}=p(e);return[t,r]},exports.parseWithBase=p,exports.raceAbort=y;
package/dist/index.d.ts CHANGED
@@ -24,6 +24,20 @@ declare function isBodyJson(body: any): boolean;
24
24
  declare function mergeOptions<Options extends SoonOptions>(...optionsList: (Options | undefined)[]): Options & {
25
25
  headers: Headers;
26
26
  };
27
+ declare function parseWithBase<Options extends SoonOptions>(urlOptions: {
28
+ url: string;
29
+ options?: Options;
30
+ baseURL?: string;
31
+ baseOptions?: Options;
32
+ }): {
33
+ url: string;
34
+ options: Options & {
35
+ headers: Headers;
36
+ body?: RequestInit["body"];
37
+ };
38
+ is_body_json: boolean;
39
+ abortController: AbortController;
40
+ };
27
41
  declare function parseUrlOptions<Options extends SoonOptions>(urlOptions: {
28
42
  url: string;
29
43
  options?: Options;
@@ -58,11 +72,13 @@ declare function raceAbort(abortController: AbortController, controllers?: Abort
58
72
  declare function deepSort(obj: unknown): unknown;
59
73
  declare function genRequestKey(req: {
60
74
  url: string;
61
- method?: string;
62
- headers?: Headers;
63
- body?: RequestInit["body"] | object;
64
- query?: Record<string, string | number | boolean | null | undefined | (string | number | boolean | null | undefined)[]> | URLSearchParams;
65
- params?: Record<string, string | number>;
75
+ options?: {
76
+ method?: string;
77
+ headers?: RequestInit["headers"];
78
+ body?: RequestInit["body"] | object;
79
+ query?: Record<string, string | number | boolean | null | undefined | (string | number | boolean | null | undefined)[]> | URLSearchParams;
80
+ params?: Record<string, string | number>;
81
+ };
66
82
  }): string;
67
83
  declare function createCache(): {
68
84
  get: (key: string) => unknown;
@@ -77,15 +93,18 @@ declare function createSilentRefresh(refresh_token_fn: () => Promise<void>): (su
77
93
  declare function createSoon<Options extends SoonOptions>(getConfig: (url: string, options?: Options) => {
78
94
  url: string;
79
95
  options?: Options;
80
- baseURL: string;
96
+ baseURL?: string;
81
97
  baseOptions?: Options;
82
98
  }, wrapper: (instance: {
83
99
  parsed: {
84
100
  url: string;
85
101
  options: Options & {
86
102
  headers: Headers;
87
- body?: BodyInit | null;
103
+ body?: RequestInit["body"];
88
104
  };
105
+ is_body_json: boolean;
106
+ abortController: AbortController;
107
+ requestKey: string;
89
108
  };
90
109
  }) => <T>(url: string, options?: Options) => Promise<T>): {
91
110
  options: <T>(url: string, options?: Options) => Promise<T>;
@@ -152,4 +171,4 @@ declare function createSoon<Options extends SoonOptions>(getConfig: (url: string
152
171
  request: <T>(url: string, options?: Options) => Promise<T>;
153
172
  };
154
173
 
155
- export { type SoonOptions, createCache, createShare, createShortApi, createShortMethods, createSilentRefresh, createSoon, deepSort, genRequestKey, isBodyJson, mergeHeaders, mergeOptions, mergeSignals, mergeUrl, parseUrlOptions, raceAbort };
174
+ export { type SoonOptions, createCache, createShare, createShortApi, createShortMethods, createSilentRefresh, createSoon, deepSort, genRequestKey, isBodyJson, mergeHeaders, mergeOptions, mergeSignals, mergeUrl, parseUrlOptions, parseWithBase, raceAbort };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- const t=t=>{const e=[],n=t.match(/:([^:/\d]+)\/?/g);return n&&n.forEach((t=>{e.push(t.replace(/\//g,"").replace(/:/g,""))})),e},e=(t="")=>t.endsWith("/")?t.slice(0,-1):t,n=(t="")=>t.startsWith("/")?t:"/"+t,r=(t="")=>t.startsWith("http"),o=t=>{if(!t)return[];if(t instanceof URLSearchParams||"string"==typeof t||Array.isArray(t))return Array.from(new URLSearchParams(t).entries());const e=[];return Object.keys(t).forEach((n=>{const r=t[n];(Array.isArray(r)?r:[r]).forEach((t=>{e.push([n,t??""])}))})),e},s=(s,a)=>{const{query:i,params:c,baseURL:f}=a;let u=s.trim();t(s).forEach((t=>{c&&(u=u.replace(":"+t,""+c[t]))}));const[l,p]=u.split("?"),h=new URLSearchParams([...o(p),...o(i)]);let y=((t,o)=>{if(r(t))return t;const s=r(o)?o:n(o);return e(s)+e(n(t))})(l,f);return h.size&&(y=y+"?"+h),y},a=(...t)=>{const e=new Headers;return t.forEach((t=>{t&&new Headers(t).forEach(((t,n)=>{e.set(n,t)}))})),e};function i(t,e){const n=(t??[]).filter((t=>!!t));return e&&n.push(AbortSignal.timeout(e)),n.length?AbortSignal.any(n):void 0}function c(t){return!(!t||"object"!=typeof t||(t instanceof Blob||t instanceof ArrayBuffer||t instanceof FormData||t instanceof File||t instanceof DataView||t instanceof URLSearchParams||t instanceof ReadableStream||(e=t,e instanceof Int8Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array||e instanceof BigInt64Array||e instanceof BigUint64Array)));var e}function f(...t){const e=Object.assign({},...t),n=a(...t.map((t=>t?.headers)));return e.headers=n,e.signal=i(t.map((t=>t?.signal)),e.timeout),e}function u(t){const{url:e,options:n,baseURL:r,baseOptions:o}=t,a=f(o,n),u=s(e,{...a,baseURL:r}),l=a?.body,p=c(l);return a.body=p?JSON.stringify(l):l,p&&a.headers.append("Content-Type","application/json"),a.signal=i([a.signal]),[u,a]}const l=["get","post","put","delete","patch"];function p(t,e){const n={};return t.forEach((t=>{n[t]=e(t)})),n}function h(e){const n=(n,r,o)=>{const s=!!t(n).length;return(...t)=>{const a=[...t],{hasBody:i,hasQuery:c}=o||{},f=s?a.shift():void 0,u=c?a.shift():void 0,l=i?a.shift():void 0,p=a.shift();return e(n,r,f,u,l,p,o?.options)}},r={};return l.forEach((t=>{const e=t.toUpperCase();r[e]=e=>({Send:r=>n(e,t,{options:r}),Body:()=>({Send:r=>n(e,t,{hasBody:!0,options:r})}),Query:()=>({Send:r=>n(e,t,{hasQuery:!0,options:r}),Body:()=>({Send:r=>n(e,t,{hasBody:!0,hasQuery:!0,options:r})})})})})),r}function y(t,e){e&&(e.pop()?.abort("soon-fetch race abort"),e.push(t))}function d(t){if(Array.isArray(t))return t.map(d);if("object"==typeof t&&null!==t){const e={};return Object.keys(t).sort().forEach((n=>{e[n]=d(t[n])})),e}return t}function g(t){const{url:e,headers:n,method:r,body:o,query:s,params:a}=t,i=d(Object.fromEntries(n?.entries()??[]));return(r??"get").toLowerCase()+e+JSON.stringify(d(s)??"")+JSON.stringify(d(a)??"")+JSON.stringify(i)+("object"==typeof o&&null!=o?JSON.stringify(d(o)):o)}function m(){const t={},e=[];setInterval((()=>{const n=Date.now();for(let r=e.length-1;r>=0;r--)e[r].expiredTime<n&&(delete t[e[r].key],e.splice(r,1))}),6e4);const n=t=>t instanceof Response?t.clone():"function"==typeof t||t instanceof Promise?t:structuredClone(t);function r(n){delete t[n];for(let t=e.length-1;t>=0;t--)if(e[t].key===n){e.splice(t,1);break}}return{get:function(e){const o=t[e];if(void 0!==o)return o.expiredTime>Date.now()?n(o.data):void r(e)},set:function(r,o,s){t[r]={data:n(o),expiredTime:s},e.push({key:r,expiredTime:s})},remove:r}}function b(){const t={},e=e=>t[e]=void 0;return{get:e=>t[e],set:(n,r)=>{t[n]=r,r.finally((()=>e(n)))}}}function A(t){let e=[],n=!1;return(r,o)=>{e.push({success:r,fail:o}),n||(n=!0,t().then((()=>{e.forEach((t=>t.success()))})).catch((t=>{e.forEach((t=>t.fail()))})).finally((()=>{n=!1,e=[]})))}}function S(t,e){const n=m(),r=b(),o=(o,s)=>new Promise(((a,c)=>{const f=new AbortController,l=t(o,s),[p,h]=u(l);console.log("[init]",p,h,l),h.signal=i([f.signal,h.signal]);const d={url:p,options:h},m=e({parsed:d}),b=g({url:d.url,...d.options,headers:new Headers(d.options?.headers)});if(d.options?.share){const t=r.get(b);if(t)return a(t)}if(d.options?.staleTime){const t=n.get(b);if(void 0!==t)return a(t)}console.log("abort",b,d.options),y(f,d.options?.aborts);const A=m(o,s);d.options?.share&&r.set(b,A),A.then((t=>{a(t),d.options?.staleTime&&n.set(b,t,(new Date).getTime()+d.options.staleTime)})).catch((t=>c(t)))})),s=h(((t,e,n,r,s,a,i)=>o(t,{...i,...a,method:e,params:n,query:r,body:s}))),a=p([...l,"head","options"],(t=>(e,n)=>o(e,{...n,method:t})));return{request:o,...s,...a}}export{m as createCache,b as createShare,h as createShortApi,p as createShortMethods,A as createSilentRefresh,S as createSoon,d as deepSort,g as genRequestKey,c as isBodyJson,a as mergeHeaders,f as mergeOptions,i as mergeSignals,s as mergeUrl,u as parseUrlOptions,y as raceAbort};
1
+ const t=t=>{const e=[],n=t.match(/:([^:/\d]+)\/?/g);return n&&n.forEach((t=>{e.push(t.replace(/\//g,"").replace(/:/g,""))})),e},e=(t="")=>t.endsWith("/")?t.slice(0,-1):t,n=(t="")=>t.startsWith("/")?t:"/"+t,r=(t="")=>t.startsWith("http"),o=t=>{if(!t)return[];if(t instanceof URLSearchParams||"string"==typeof t||Array.isArray(t))return Array.from(new URLSearchParams(t).entries());const e=[];return Object.keys(t).forEach((n=>{const r=t[n];(Array.isArray(r)?r:[r]).forEach((t=>{e.push([n,t??""])}))})),e},s=(s,a)=>{const{query:i,params:c,baseURL:f}=a;let u=s.trim();t(s).forEach((t=>{c&&(u=u.replace(":"+t,""+c[t]))}));const[l,p]=u.split("?"),h=new URLSearchParams([...o(p),...o(i)]);let y=((t,o)=>{if(r(t))return t;const s=r(o)?o:n(o);return e(s)+e(n(t))})(l,f);return h.size&&(y=y+"?"+h),y},a=(...t)=>{const e=new Headers;return t.forEach((t=>{t&&new Headers(t).forEach(((t,n)=>{e.set(n,t)}))})),e};function i(t,e){const n=(t??[]).filter((t=>!!t));return e&&n.push(AbortSignal.timeout(e)),n.length?AbortSignal.any(n):void 0}function c(t){return!(!t||"object"!=typeof t||(t instanceof Blob||t instanceof ArrayBuffer||t instanceof FormData||t instanceof File||t instanceof DataView||t instanceof URLSearchParams||t instanceof ReadableStream||(e=t,e instanceof Int8Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array||e instanceof BigInt64Array||e instanceof BigUint64Array)));var e}function f(...t){const e=Object.assign({},...t),n=a(...t.map((t=>t?.headers)));return e.headers=n,e.signal=i(t.map((t=>t?.signal)),e.timeout),e}function u(t){const{url:e,options:n,baseURL:r,baseOptions:o}=t,a=f(o,n),u=s(e,{...a,baseURL:r}),l=a?.body,p=c(l);a.body=p?JSON.stringify(l):l,p&&a.headers.append("Content-Type","application/json");const h=new AbortController;return a.signal=i([a.signal,h.signal]),{url:u,options:a,is_body_json:p,abortController:h}}function l(t){const{url:e,options:n}=u(t);return[e,n]}const p=["get","post","put","delete","patch"];function h(t,e){const n={};return t.forEach((t=>{n[t]=e(t)})),n}function y(e){const n=(n,r,o)=>{const s=!!t(n).length;return(...t)=>{const a=[...t],{hasBody:i,hasQuery:c}=o||{},f=s?a.shift():void 0,u=c?a.shift():void 0,l=i?a.shift():void 0,p=a.shift();return e(n,r,f,u,l,p,o?.options)}},r={};return p.forEach((t=>{const e=t.toUpperCase();r[e]=e=>({Send:r=>n(e,t,{options:r}),Body:()=>({Send:r=>n(e,t,{hasBody:!0,options:r})}),Query:()=>({Send:r=>n(e,t,{hasQuery:!0,options:r}),Body:()=>({Send:r=>n(e,t,{hasBody:!0,hasQuery:!0,options:r})})})})})),r}function d(t,e){e&&(e.pop()?.abort("race abort"),e.push(t))}function m(t){if(Array.isArray(t))return t.map(m);if("object"==typeof t&&null!==t){const e={};return Object.keys(t).sort().forEach((n=>{e[n]=m(t[n])})),e}return t}function g(t){const{url:e,options:n}=t,{headers:r,method:o,body:s,query:a,params:i}=n??{},c=m(Object.fromEntries(new Headers(r).entries()??[]));return(o??"get").toLowerCase()+e+JSON.stringify(m(a)??"")+JSON.stringify(m(i)??"")+JSON.stringify(c)+("object"==typeof s&&null!=s?JSON.stringify(m(s)):s??"")}function b(){const t={},e=[];setInterval((()=>{const n=Date.now();for(let r=e.length-1;r>=0;r--)e[r].expiredTime<n&&(delete t[e[r].key],e.splice(r,1))}),6e4);const n=t=>t instanceof Response?t.clone():"function"==typeof t||t instanceof Promise?t:structuredClone(t);function r(n){delete t[n];for(let t=e.length-1;t>=0;t--)if(e[t].key===n){e.splice(t,1);break}}return{get:function(e){const o=t[e];if(void 0!==o)return o.expiredTime>Date.now()?n(o.data):void r(e)},set:function(r,o,s){t[r]={data:n(o),expiredTime:s},e.push({key:r,expiredTime:s})},remove:r}}function A(){const t={},e=e=>t[e]=void 0;return{get:e=>t[e],set:(n,r)=>{t[n]=r,r.finally((()=>e(n)))}}}function S(t){let e=[],n=!1;return(r,o)=>{e.push({success:r,fail:o}),n||(n=!0,t().then((()=>{e.forEach((t=>t.success()))})).catch((t=>{e.forEach((t=>t.fail()))})).finally((()=>{n=!1,e=[]})))}}function w(t,e){const n=b(),r=A(),o=(o,s)=>new Promise(((a,i)=>{const c=u(t(o,s)),f=g(c),{abortController:l}=c,p=new AbortController;p.signal.addEventListener("abort",(()=>{i(p.signal.reason)}));const h=e({parsed:{...c,requestKey:f}});if(c.options?.share){const t=r.get(f);if(t)return a(t)}if(d(c.options.share?p:l,c.options?.aborts),c.options?.staleTime){const t=n.get(f);if(void 0!==t)return a(t)}const y=h(o,s);c.options?.share&&r.set(f,y),y.then((t=>{a(t),c.options?.staleTime&&n.set(f,t,(new Date).getTime()+c.options.staleTime)})).catch((t=>i(t)))})),s=y(((t,e,n,r,s,a,i)=>o(t,{...i,...a,method:e,params:n,query:r,body:s}))),a=h([...p,"head","options"],(t=>(e,n)=>o(e,{...n,method:t})));return{request:o,...s,...a}}export{b as createCache,A as createShare,y as createShortApi,h as createShortMethods,S as createSilentRefresh,w as createSoon,m as deepSort,g as genRequestKey,c as isBodyJson,a as mergeHeaders,f as mergeOptions,i as mergeSignals,s as mergeUrl,l as parseUrlOptions,u as parseWithBase,d as raceAbort};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "soon-fetch",
3
- "version": "3.0.0-beta.3",
4
- "description": "a 5Kb request lib alternative to axios",
3
+ "version": "3.0.0-beta.4",
4
+ "description": "a 5Kb request lib alternative to axios with timeout, request reusing ,cache ,race ...",
5
5
  "homepage": "https://github.com/leafio/soon-fetch",
6
6
  "main": "./dist/index.cjs.js",
7
7
  "module": "/dist/index.js",