advanced-http-client
Version:
Universal HTTP client library using fetch for JS/TS projects (React, Next.js, Vue, Node.js, Bun, etc.)
2 lines • 6.59 kB
JavaScript
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.HttpClient=t():e.HttpClient=t()}("undefined"!=typeof self?self:this,()=>(()=>{"use strict";var e={d:(t,s)=>{for(var r in s)e.o(s,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:s[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>i});class s{constructor(){this._handlers=[],this.nextId=0}use(e,t){return this._handlers.push({_fulfilled:e,_rejected:t}),this.nextId++}eject(e){this._handlers[e]&&(this._handlers[e]={})}clear(){this._handlers=[]}get handlers(){return this._handlers}}class r{constructor(){this._handlers=[],this.nextId=0}use(e,t){return this._handlers.push({_fulfilled:e,_rejected:t}),this.nextId++}eject(e){this._handlers[e]&&(this._handlers[e]={})}clear(){this._handlers=[]}get handlers(){return this._handlers}}const n="application/json",o="__anonymous__";class a{constructor(e){this.controllers=new Map,this.baseURL=e?.baseURL,this.instanceHeaders={...e?.headers||{}};const{baseURL:t,headers:n,...o}=e||{};this.instanceOptions=o,this.interceptors={request:new s,response:new s,error:new r},a.allInstances.add(this)}static setHeader(e,t){this.globalHeaders[e]=t}static generateControlKey(){const e=new Uint8Array(20),t=globalThis.crypto;if(t&&"function"==typeof t.getRandomValues)t.getRandomValues(e);else{const t=globalThis.require?.("crypto");if(!t||"function"!=typeof t.randomBytes)throw new Error("Secure random number generation is not available in this environment. Please provide a controlKey manually.");t.randomBytes(20).forEach((t,s)=>e[s]=t)}let s="";return e.forEach(e=>{s+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[e%62]}),s}static create(e){return new a(e)}static async parseResponseBody(e){let t;const s=e.headers.get("content-type")??"";return t=s&&-1!==s.indexOf(n)?await e.json():s&&-1!==s.indexOf("text/")?await e.text():s&&-1!==s.indexOf("form")?await e.formData():s&&-1!==s.indexOf("blob")?await e.blob():s&&-1!==s.indexOf("arraybuffer")?await e.arrayBuffer():await e.text(),t}mergeConfig(e){if(e?.isolated){const t={};if(Array.isArray(e.includeHeaders)){const s=e.includeHeaders;for(const e of s)void 0!==this.instanceHeaders?.[e]?t[e]=this.instanceHeaders[e]:void 0!==a.globalHeaders[e]&&(t[e]=a.globalHeaders[e])}return e.headers&&(e.headers instanceof Headers?e.headers.forEach((e,s)=>t[s]=e):Array.isArray(e.headers)?e.headers.forEach(([e,s])=>t[e]=s):Object.assign(t,e.headers)),{...e,headers:t}}const t={...this.instanceHeaders,...e?.headers instanceof Headers?this.convertHeadersToObject(e.headers):e?.headers||{}};return Object.entries(a.globalHeaders).forEach(([e,s])=>{e in t||(t[e]=s)}),t.Accept||(t.Accept=n),{...this.instanceOptions,...e,headers:t}}convertHeadersToObject(e){const t={};return e.forEach((e,s)=>{t[s]=e}),t}buildURL(e){return this.baseURL&&!/^https?:\/\//i.test(e)?this.baseURL.replace(/\/$/,"")+"/"+e.replace(/^\//,""):e}async executeRequestInterceptors(e){let t=Promise.resolve(e);const s=this.interceptors.request.handlers;for(const{_fulfilled:e,_rejected:r}of s)t=t.then(e||(e=>e),r||(e=>Promise.reject(e)));return t}async executeResponseInterceptors(e){let t=Promise.resolve(e);const s=this.interceptors.response.handlers;for(const{_fulfilled:e,_rejected:r}of s)t=t.then(e||(e=>e),r||(e=>Promise.reject(e)));return t}async executeErrorInterceptors(e){let t=e;for(const e of this.interceptors.error.handlers)if(e._fulfilled)try{const s=await e._fulfilled(t);if(s&&"object"==typeof s&&"data"in s&&"status"in s)return s;s&&"object"==typeof s&&"message"in s&&(t=s)}catch(e){t=e}throw t}async request(e,t){if("undefined"==typeof fetch)throw new Error("fetch is not available in this environment. For Node.js <18, install a fetch polyfill.");const s=this.mergeConfig(t),r=this.buildURL(e),n=await this.executeRequestInterceptors(s),i=!n.signal||"number"==typeof n.timeout&&n.timeout>0||n.controlKey;let l,c,h=n.controlKey;if(i&&(n.signal||(c=new AbortController,n.signal=c.signal)),"number"==typeof n.timeout&&n.timeout>0&&(l=globalThis.setTimeout(()=>{c?.abort()},n.timeout),delete n.timeout),h){const e=h;let t;if(delete n.controlKey,t=this._isStaticInstance?a.globalControllers:this.controllers,t.has(e))throw new Error(`controlKey '${e}' is already in use.`);c||(c=new AbortController,n.signal=c.signal),t.set(e,c)}if(!h){const e=this._isStaticInstance?a.globalControllers:this.controllers,t=e.get(o);t?(n.signal=t.signal,c=t):(c||(c=new AbortController,n.signal=c.signal),e.set(o,c))}try{const e=await fetch(r,n);l&&globalThis.clearTimeout(l),h&&(this.controllers.has(h)?this.controllers:a.globalControllers).delete(h);const t=await a.parseResponseBody(e),s={};e.headers.forEach((e,t)=>{s[t]=e});const o={data:t,status:e.status,statusText:e.statusText,headers:s,config:{url:r,options:n,method:n?.method??"GET",body:n?.body},request:e};if(!e.ok){const t=new Error(`Request failed with status code ${e.status}`);throw t.response=o,t}return await this.executeResponseInterceptors(o)}catch(e){return h&&(this.controllers.has(h)?this.controllers:a.globalControllers).delete(h),await this.executeErrorInterceptors(e)}}async get(e,t){return this.request(e,{...t,method:"GET"})}async requestWithBody(e,t,s,r){const o=this.mergeConfig(r);return o.method=e,void 0!==s&&(o.body=JSON.stringify(s),o.headers["Content-Type"]||(o.headers["Content-Type"]=n)),this.request(t,o)}async post(e,t,s){return this.requestWithBody("POST",e,t,s)}async patch(e,t,s){return this.requestWithBody("PATCH",e,t,s)}async delete(e,t,s){return this.requestWithBody("DELETE",e,t,s)}_abortAllControllers(){this.controllers.forEach(e=>e.abort()),this.controllers.clear()}static async get(e,t){const s=new a;return s._isStaticInstance=!0,s.get(e,t)}static async post(e,t,s){const r=new a;return r._isStaticInstance=!0,r.post(e,t,s)}static async patch(e,t,s){const r=new a;return r._isStaticInstance=!0,r.patch(e,t,s)}static async delete(e,t,s){const r=new a;return r._isStaticInstance=!0,r.delete(e,t,s)}static cancelRequest(e){const t=a.globalControllers.get(e);if(t)return t.abort(),void a.globalControllers.delete(e);for(const t of a.allInstances){const s=t.controllers.get(e);if(s){s.abort(),t.controllers.delete(e);break}}}static cancelAllRequests(){a.globalControllers.forEach(e=>e.abort()),a.globalControllers.clear();for(const e of a.allInstances)e._abortAllControllers()}}a.globalHeaders={},a.globalControllers=new Map,a.allInstances=new Set;const i=a;return t.default})());
//# sourceMappingURL=http-client.js.map