Comparing version 1.5.0 to 1.6.0
@@ -10,3 +10,3 @@ /** | ||
baseConfigs: Partial<FexiosConfigs>; | ||
hooks: Record<FexiosEvents, FexiosHook[]>; | ||
protected hooks: FexiosHookStore[]; | ||
readonly DEFAULT_CONFIGS: FexiosConfigs; | ||
@@ -18,4 +18,4 @@ private METHODS_WITHOUT_BODY; | ||
mergeHeaders(base: Record<string, any> | Headers | undefined, ...income: (Record<string, any> | Headers | undefined)[]): Record<string, any>; | ||
emit<C = FexiosContext>(event: FexiosEvents, ctx: C): Promise<C>; | ||
on<C = FexiosContext>(event: FexiosEvents, hook: FexiosHook<C>, prepend?: boolean): this; | ||
emit<C = FexiosContext>(event: FexiosLifecycleEvents, ctx: C): Promise<C>; | ||
on<C = FexiosContext>(event: FexiosLifecycleEvents, action: FexiosHook<C>, prepend?: boolean): this; | ||
private createInterceptor; | ||
@@ -98,5 +98,16 @@ readonly interceptors: FexiosInterceptors; | ||
export type FexiosHook<C = unknown> = (context: C) => AwaitAble<C | false>; | ||
export type FexiosEvents = 'beforeInit' | 'beforeRequest' | 'afterBodyTransformed' | 'beforeActualFetch' | 'afterResponse'; | ||
export interface FexiosHookStore { | ||
event: FexiosLifecycleEvents; | ||
action: FexiosHook; | ||
} | ||
export type FexiosLifecycleEvents = 'beforeInit' | 'beforeRequest' | 'afterBodyTransformed' | 'beforeActualFetch' | 'afterResponse'; | ||
export interface FexiosHooksNameMap { | ||
beforeInit: FexiosContext; | ||
beforeRequest: FexiosContext; | ||
afterBodyTransformed: FexiosContext; | ||
beforeActualFetch: FexiosContext; | ||
afterResponse: FexiosFinalContext; | ||
} | ||
export interface FexiosInterceptor { | ||
handlers: FexiosHook[]; | ||
handlers: () => FexiosHook[]; | ||
use: <C = FexiosContext>(hook: FexiosHook<C>, prepend?: boolean) => Fexios; | ||
@@ -103,0 +114,0 @@ clear: () => void; |
@@ -7,3 +7,3 @@ var Fexios=function(u){"use strict";/** | ||
* @author dragon-fish <dragon-fish@qq.com> | ||
*/class d{constructor(o={}){this.baseConfigs=o,this.hooks={beforeInit:[],beforeRequest:[],afterBodyTransformed:[],beforeActualFetch:[],afterResponse:[]},this.DEFAULT_CONFIGS={baseURL:"",timeout:6e4,credentials:"same-origin",headers:{},query:{},responseType:"json"},this.METHODS_WITHOUT_BODY=["get","head","options","trace"],this.interceptors={request:this.createInterceptor("beforeRequest"),response:this.createInterceptor("afterResponse")},this.create=d.create,this.createMethodShortcut("get").createMethodShortcut("post").createMethodShortcut("put").createMethodShortcut("patch").createMethodShortcut("delete").createMethodShortcut("head").createMethodShortcut("options").createMethodShortcut("trace")}async request(o,t){var _,T,g,R;let e=t=t||{};e.url=o.toString(),e=await this.emit("beforeInit",e);const s=t.baseURL||this.baseConfigs.baseURL||((_=globalThis.location)==null?void 0:_.href),c=s?new URL(s,(T=globalThis.location)==null?void 0:T.href):void 0,i=new URL(e.url.toString(),c);if(e.url=i.href,e.baseURL=c?c.href:i.origin,e.headers=this.mergeHeaders(this.baseConfigs.headers,t.headers),e.query=this.mergeQuery(this.baseConfigs.query,i.searchParams,t.query),i.search=new URLSearchParams(e.query).toString(),e.url=i.toString(),this.METHODS_WITHOUT_BODY.includes((g=e.method)==null?void 0:g.toLocaleLowerCase())&&e.body)throw new h("BODY_NOT_ALLOWED",`Request method "${e.method}" does not allow body`);e=await this.emit("beforeRequest",e);let r;typeof e.body<"u"&&e.body!==null&&(e.body instanceof Blob||e.body instanceof FormData||e.body instanceof URLSearchParams?r=e.body:typeof e.body=="object"?(r=JSON.stringify(e.body),e.headers["content-type"]="application/json; charset=UTF-8"):r=e.body),!((R=t.headers)!=null&&R["content-type"])&&r&&(r instanceof FormData||r instanceof URLSearchParams?typeof r=="string"&&typeof e.body=="object"?e.headers["content-type"]="application/json; charset=UTF-8":r instanceof Blob&&(e.headers["content-type"]=r.type):delete e.headers["content-type"]),e.body=r,e=await this.emit("afterBodyTransformed",e);const n=e.abortController||globalThis.AbortController?new AbortController:void 0,y=new Request(e.url,{method:e.method||"GET",credentials:e.credentials,headers:e.headers,body:e.body,signal:n==null?void 0:n.signal});e.rawRequest=y,e=await this.emit("beforeActualFetch",e);const f=e.timeout||this.baseConfigs.timeout||60*1e3,p=setTimeout(()=>{if(n==null||n.abort(),!n)throw new h("TIMEOUT",`Request timed out after ${f}ms`,e)},f),w=await fetch(e.rawRequest).catch(S=>{throw new h("NETWORK_ERROR",S.message,e)}).finally(()=>{clearTimeout(p)});return e.rawResponse=w,e.response=await m(w,e.responseType),e.data=e.response.data,e.headers=e.response.headers,this.emit("afterResponse",e)}mergeQuery(o,...t){const e=new URLSearchParams(o);for(const s of t)new URLSearchParams(s).forEach((i,r)=>{e.set(r,i)});return Object.fromEntries(e)}mergeHeaders(o,...t){const e={},s=new Headers(o);for(const c of t)new Headers(c).forEach((r,n)=>{s.set(n,r)});return s.forEach((c,i)=>{e[i]=c}),e}async emit(o,t){const e=this.hooks[o]||[];try{for(const[s,c]of e.entries()){const i=`${o}#${c.name||s}`,r=Symbol("FexiosHookContext");t.__hook_symbol__=r;const n=await c(t);if(t.__hook_symbol__!==r)throw new h("HOOK_CONTEXT_CHANGED",`Hook "${i}" should not override the original FexiosContext object.`);if(n===!1)throw new h("ABORTED_BY_HOOK",`Request aborted by hook "${i}"`,t);if(typeof n=="object"&&n.__hook_symbol__===r)t=n;else{const y=globalThis["".concat("console")];try{throw new h("UNEXPECTED_HOOK_RETURN",`Hook "${i}" should return the original FexiosContext or return false to abort the request, but got "${n}".`)}catch(f){y.warn(f.stack||f)}}delete t.__hook_symbol__}}catch(s){return Promise.reject(s)}return t}on(o,t,e=!1){var s;if(typeof t!="function")throw new h("INVALID_HOOK_CALLBACK",`Hook "${t}" should be a function, but got "${typeof t}"`);return(s=this.hooks)[o]??(s[o]=[]),this.hooks[o][e?"unshift":"push"](t),this}createInterceptor(o){return{handlers:this.hooks[o],use:(t,e=!1)=>this.on(o,t,e),clear:()=>{this.hooks[o]=[]}}}createMethodShortcut(o){return Object.defineProperty(this,o,{value:(t,e,s)=>(this.METHODS_WITHOUT_BODY.includes(o.toLocaleLowerCase())?s=e:(s=s||{},s.body=e),this.request(t,{...s,method:o}))}),this}extends(o){const t=new d({...this.baseConfigs,...o});return t.hooks={...this.hooks},t}static create(o){return new d(o)}}class h extends Error{constructor(o,t,e){super(t),this.code=o,this.context=e,this.name="FexiosError"}}class l extends h{constructor(o,t){super(t.statusText,o),this.response=t,this.name="FexiosResponseError"}}const O=a=>!(a instanceof l)&&a instanceof h;async function m(a,o="json"){let t;o==="blob"&&(t=await a.clone().blob().catch(()=>{})),t||(t=await a.clone().json().catch(()=>a.clone().text()));const e={rawResponse:a,data:t,ok:a.ok,status:a.status,statusText:a.statusText,headers:a.headers};if(!a.ok)throw new l(`Request failed with status code ${a.status}`,e);return e}const E=b();function b(a){return d.create(a)}return typeof window<"u"&&(window.fexios=b()),u.Fexios=d,u.FexiosError=h,u.FexiosResponseError=l,u.createFexios=b,u.createFexiosResponse=m,u.default=E,u.isFexiosError=O,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),u}({}); | ||
*/class d{constructor(o={}){this.baseConfigs=o,this.hooks=[],this.DEFAULT_CONFIGS={baseURL:"",timeout:6e4,credentials:"same-origin",headers:{},query:{},responseType:"json"},this.METHODS_WITHOUT_BODY=["get","head","options","trace"],this.interceptors={request:this.createInterceptor("beforeRequest"),response:this.createInterceptor("afterResponse")},this.create=d.create,this.createMethodShortcut("get").createMethodShortcut("post").createMethodShortcut("put").createMethodShortcut("patch").createMethodShortcut("delete").createMethodShortcut("head").createMethodShortcut("options").createMethodShortcut("trace")}async request(o,t){var _,T,g,O;let e=t=t||{};e.url=o.toString(),e=await this.emit("beforeInit",e);const s=t.baseURL||this.baseConfigs.baseURL||((_=globalThis.location)==null?void 0:_.href),c=s?new URL(s,(T=globalThis.location)==null?void 0:T.href):void 0,i=new URL(e.url.toString(),c);if(e.url=i.href,e.baseURL=c?c.href:i.origin,e.headers=this.mergeHeaders(this.baseConfigs.headers,t.headers),e.query=this.mergeQuery(this.baseConfigs.query,i.searchParams,t.query),i.search=new URLSearchParams(e.query).toString(),e.url=i.toString(),this.METHODS_WITHOUT_BODY.includes((g=e.method)==null?void 0:g.toLocaleLowerCase())&&e.body)throw new h("BODY_NOT_ALLOWED",`Request method "${e.method}" does not allow body`);e=await this.emit("beforeRequest",e);let r;typeof e.body<"u"&&e.body!==null&&(e.body instanceof Blob||e.body instanceof FormData||e.body instanceof URLSearchParams?r=e.body:typeof e.body=="object"?(r=JSON.stringify(e.body),e.headers["content-type"]="application/json; charset=UTF-8"):r=e.body),!((O=t.headers)!=null&&O["content-type"])&&r&&(r instanceof FormData||r instanceof URLSearchParams?typeof r=="string"&&typeof e.body=="object"?e.headers["content-type"]="application/json; charset=UTF-8":r instanceof Blob&&(e.headers["content-type"]=r.type):delete e.headers["content-type"]),e.body=r,e=await this.emit("afterBodyTransformed",e);const n=e.abortController||globalThis.AbortController?new AbortController:void 0,y=new Request(e.url,{method:e.method||"GET",credentials:e.credentials,headers:e.headers,body:e.body,signal:n==null?void 0:n.signal});e.rawRequest=y,e=await this.emit("beforeActualFetch",e);const l=e.timeout||this.baseConfigs.timeout||60*1e3,p=setTimeout(()=>{if(n==null||n.abort(),!n)throw new h("TIMEOUT",`Request timed out after ${l}ms`,e)},l),w=await fetch(e.rawRequest).catch(S=>{throw new h("NETWORK_ERROR",S.message,e)}).finally(()=>{clearTimeout(p)});return e.rawResponse=w,e.response=await m(w,e.responseType),e.data=e.response.data,e.headers=e.response.headers,this.emit("afterResponse",e)}mergeQuery(o,...t){const e=new URLSearchParams(o);for(const s of t)new URLSearchParams(s).forEach((i,r)=>{e.set(r,i)});return Object.fromEntries(e)}mergeHeaders(o,...t){const e={},s=new Headers(o);for(const c of t)new Headers(c).forEach((r,n)=>{s.set(n,r)});return s.forEach((c,i)=>{e[i]=c}),e}async emit(o,t){const e=this.hooks.filter(s=>s.event===o);try{let s=0;for(const c of e){const i=`${o}#${c.action.name||s}`,r=Symbol("FexiosHookContext");t.__hook_symbol__=r;const n=await c.action.bind(this)(t);if(t.__hook_symbol__!==r)throw new h("HOOK_CONTEXT_CHANGED",`Hook "${i}" should not override the original FexiosContext object.`);if(n===!1)throw new h("ABORTED_BY_HOOK",`Request aborted by hook "${i}"`,t);if(typeof n=="object"&&n.__hook_symbol__===r)t=n;else{const y=globalThis["".concat("console")];try{throw new h("UNEXPECTED_HOOK_RETURN",`Hook "${i}" should return the original FexiosContext or return false to abort the request, but got "${n}".`)}catch(l){y.warn(l.stack||l)}}delete t.__hook_symbol__,s++}}catch(s){return Promise.reject(s)}return t}on(o,t,e=!1){if(typeof t!="function")throw new h("INVALID_HOOK_CALLBACK",`Hook "${t}" should be a function, but got "${typeof t}"`);return this.hooks[e?"unshift":"push"]({event:o,action:t}),this}createInterceptor(o){return{handlers:()=>this.hooks.filter(t=>t.event===o).map(t=>t.action),use:(t,e=!1)=>this.on(o,t,e),clear:()=>{this.hooks=this.hooks.filter(t=>t.event!==o)}}}createMethodShortcut(o){return Object.defineProperty(this,o,{value:(t,e,s)=>(this.METHODS_WITHOUT_BODY.includes(o.toLocaleLowerCase())?s=e:(s=s||{},s.body=e),this.request(t,{...s,method:o}))}),this}extends(o){const t=new d({...this.baseConfigs,...o});return t.hooks=[...this.hooks],t}static create(o){return new d(o)}}class h extends Error{constructor(o,t,e){super(t),this.code=o,this.context=e,this.name="FexiosError"}}class f extends h{constructor(o,t){super(t.statusText,o),this.response=t,this.name="FexiosResponseError"}}const R=a=>!(a instanceof f)&&a instanceof h;async function m(a,o="json"){let t;o==="blob"&&(t=await a.clone().blob().catch(()=>{})),t||(t=await a.clone().json().catch(()=>a.clone().text()));const e={rawResponse:a,data:t,ok:a.ok,status:a.status,statusText:a.statusText,headers:a.headers};if(!a.ok)throw new f(`Request failed with status code ${a.status}`,e);return e}const E=b();function b(a){return d.create(a)}return typeof window<"u"&&(window.fexios=b()),u.Fexios=d,u.FexiosError=h,u.FexiosResponseError=f,u.createFexios=b,u.createFexiosResponse=m,u.default=E,u.isFexiosError=R,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),u}({}); | ||
//# sourceMappingURL=index.iife.js.map |
@@ -10,3 +10,3 @@ /** | ||
baseConfigs: Partial<FexiosConfigs>; | ||
hooks: Record<FexiosEvents, FexiosHook[]>; | ||
protected hooks: FexiosHookStore[]; | ||
readonly DEFAULT_CONFIGS: FexiosConfigs; | ||
@@ -18,4 +18,4 @@ private METHODS_WITHOUT_BODY; | ||
mergeHeaders(base: Record<string, any> | Headers | undefined, ...income: (Record<string, any> | Headers | undefined)[]): Record<string, any>; | ||
emit<C = FexiosContext>(event: FexiosEvents, ctx: C): Promise<C>; | ||
on<C = FexiosContext>(event: FexiosEvents, hook: FexiosHook<C>, prepend?: boolean): this; | ||
emit<C = FexiosContext>(event: FexiosLifecycleEvents, ctx: C): Promise<C>; | ||
on<C = FexiosContext>(event: FexiosLifecycleEvents, action: FexiosHook<C>, prepend?: boolean): this; | ||
private createInterceptor; | ||
@@ -98,5 +98,16 @@ readonly interceptors: FexiosInterceptors; | ||
export type FexiosHook<C = unknown> = (context: C) => AwaitAble<C | false>; | ||
export type FexiosEvents = 'beforeInit' | 'beforeRequest' | 'afterBodyTransformed' | 'beforeActualFetch' | 'afterResponse'; | ||
export interface FexiosHookStore { | ||
event: FexiosLifecycleEvents; | ||
action: FexiosHook; | ||
} | ||
export type FexiosLifecycleEvents = 'beforeInit' | 'beforeRequest' | 'afterBodyTransformed' | 'beforeActualFetch' | 'afterResponse'; | ||
export interface FexiosHooksNameMap { | ||
beforeInit: FexiosContext; | ||
beforeRequest: FexiosContext; | ||
afterBodyTransformed: FexiosContext; | ||
beforeActualFetch: FexiosContext; | ||
afterResponse: FexiosFinalContext; | ||
} | ||
export interface FexiosInterceptor { | ||
handlers: FexiosHook[]; | ||
handlers: () => FexiosHook[]; | ||
use: <C = FexiosContext>(hook: FexiosHook<C>, prepend?: boolean) => Fexios; | ||
@@ -103,0 +114,0 @@ clear: () => void; |
@@ -14,9 +14,3 @@ "use strict"; | ||
this.baseConfigs = baseConfigs; | ||
this.hooks = { | ||
beforeInit: [], | ||
beforeRequest: [], | ||
afterBodyTransformed: [], | ||
beforeActualFetch: [], | ||
afterResponse: [], | ||
}; | ||
this.hooks = []; | ||
this.DEFAULT_CONFIGS = { | ||
@@ -165,10 +159,11 @@ baseURL: '', | ||
async emit(event, ctx) { | ||
const hooks = this.hooks[event] || []; | ||
const hooks = this.hooks.filter((hook) => hook.event === event); | ||
try { | ||
for (const [index, hook] of hooks.entries()) { | ||
const hookName = `${event}#${hook.name || index}`; | ||
let index = 0; | ||
for (const hook of hooks) { | ||
const hookName = `${event}#${hook.action.name || index}`; | ||
// Set a symbol to check if the hook overrides the original context | ||
const symbol = Symbol('FexiosHookContext'); | ||
ctx.__hook_symbol__ = symbol; | ||
const newCtx = await hook(ctx); | ||
const newCtx = await hook.action.bind(this)(ctx); | ||
// Check if the hook overrides the original context | ||
@@ -200,2 +195,3 @@ if (ctx.__hook_symbol__ !== symbol) { | ||
delete ctx.__hook_symbol__; | ||
index++; | ||
} | ||
@@ -208,10 +204,10 @@ } | ||
} | ||
on(event, hook, prepend = false) { | ||
var _a; | ||
var _b; | ||
if (typeof hook !== 'function') { | ||
throw new FexiosError('INVALID_HOOK_CALLBACK', `Hook "${hook}" should be a function, but got "${typeof hook}"`); | ||
on(event, action, prepend = false) { | ||
if (typeof action !== 'function') { | ||
throw new FexiosError('INVALID_HOOK_CALLBACK', `Hook "${action}" should be a function, but got "${typeof action}"`); | ||
} | ||
(_a = (_b = this.hooks)[event]) !== null && _a !== void 0 ? _a : (_b[event] = []); | ||
this.hooks[event][prepend ? 'unshift' : 'push'](hook); | ||
this.hooks[prepend ? 'unshift' : 'push']({ | ||
event, | ||
action: action, | ||
}); | ||
return this; | ||
@@ -221,3 +217,5 @@ } | ||
return { | ||
handlers: this.hooks[event], | ||
handlers: () => this.hooks | ||
.filter((hook) => hook.event === event) | ||
.map((hook) => hook.action), | ||
use: (hook, prepend = false) => { | ||
@@ -227,3 +225,3 @@ return this.on(event, hook, prepend); | ||
clear: () => { | ||
this.hooks[event] = []; | ||
this.hooks = this.hooks.filter((hook) => hook.event !== event); | ||
}, | ||
@@ -252,3 +250,3 @@ }; | ||
const fexios = new Fexios({ ...this.baseConfigs, ...configs }); | ||
fexios.hooks = { ...this.hooks }; | ||
fexios.hooks = [...this.hooks]; | ||
return fexios; | ||
@@ -255,0 +253,0 @@ } |
{ | ||
"name": "fexios", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Fetch based HTTP client with similar API to axios for browser and Node.js", | ||
@@ -9,2 +9,3 @@ "main": "./lib/index.js", | ||
"module": "./dist/index.mjs", | ||
"type": "module", | ||
"files": [ | ||
@@ -41,28 +42,26 @@ "dist", | ||
"devDependencies": { | ||
"@types/chai": "^4.3.5", | ||
"@types/chai-as-promised": "^7.1.5", | ||
"@types/formidable": "^3.4.1", | ||
"@types/mocha": "^10.0.1", | ||
"@types/node": "^18", | ||
"@web-std/file": "^3.0.2", | ||
"chai": "^4.3.7", | ||
"chai-as-promised": "^7.1.1", | ||
"dotenv": "^16.3.1", | ||
"esbuild-register": "^3.4.2", | ||
"mocha": "^10.2.0", | ||
"rimraf": "^5.0.1", | ||
"tsx": "^3.12.7", | ||
"typescript": "^5.1.6", | ||
"vite": "^4.4.9", | ||
"vite-plugin-dts": "^3.5.2" | ||
"@types/formidable": "^3.4.5", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "^20.11.19", | ||
"@vitest/coverage-v8": "^1.3.0", | ||
"@vitest/ui": "^1.3.0", | ||
"@web-std/file": "^3.0.3", | ||
"dotenv": "^16.4.4", | ||
"rimraf": "^5.0.5", | ||
"tsx": "^4.7.1", | ||
"typescript": "^5.3.3", | ||
"vite": "^5.1.3", | ||
"vite-plugin-dts": "^3.7.2", | ||
"vitest": "^1.3.0" | ||
}, | ||
"dependencies": { | ||
"tslib": "^2.6.1" | ||
"tslib": "^2.6.2" | ||
}, | ||
"scripts": { | ||
"test": "mocha test/**/*.spec.ts", | ||
"prepublish": "npm run build", | ||
"build": "npm run clean && tsc --module commonjs && vite build", | ||
"clean": "rimraf dist lib", | ||
"build": "npm run clean && tsc --module commonjs && vite build", | ||
"prepublish": "npm run build" | ||
"test": "vitest run ./test", | ||
"review": "vite preview --outDir ./.test_reports" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
13
5
Yes
124154
13
828
Updatedtslib@^2.6.2