@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
3 lines (2 loc) • 6.8 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var p=Object.defineProperty,g=(o,e,t)=>e in o?p(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,d=(o,e,t)=>g(o,typeof e!="symbol"?e+"":e,t);class h{constructor(e){d(this,"config"),d(this,"requestInterceptors",[]),d(this,"responseInterceptors",[]),d(this,"errorHandlers",[]),this.config=e}setConfig(e){this.config={...this.config,...e}}setOrganizationContext(e){this.config.organizationId=e}clearOrganizationContext(){delete this.config.organizationId}addRequestInterceptor(e){this.requestInterceptors.push(e)}addResponseInterceptor(e){this.responseInterceptors.push(e)}addErrorHandler(e){this.errorHandlers.push(e)}async request(e,t={}){const s=this.buildUrl(e,t.params);let r=this.buildRequestConfig(t);for(const n of this.requestInterceptors)r=await n(r);try{let i=await this.executeRequest(s,r);for(const a of this.responseInterceptors)i=await a(i);return await this.parseResponse(i)}catch(n){const i=this.createAPIError(n);for(const a of this.errorHandlers)a(i);throw i}}async get(e,t){return this.request(e,{...t,method:"GET"})}async post(e,t,s){return this.request(e,{...s,method:"POST",body:t})}async put(e,t,s){return this.request(e,{...s,method:"PUT",body:t})}async patch(e,t,s){return this.request(e,{...s,method:"PATCH",body:t})}async delete(e,t){return this.request(e,{...t,method:"DELETE"})}buildUrl(e,t){const s=new URL(e,this.config.baseUrl);if(t)for(const[r,n]of Object.entries(t))n!=null&&s.searchParams.set(r,String(n));return s.toString()}buildRequestConfig(e){const t={"Content-Type":"application/json",...this.config.headers,...e.headers};return this.config.apiKey?t.Authorization=`Bearer ${this.config.apiKey}`:this.config.publishableKey&&(t["X-Publishable-Key"]=this.config.publishableKey),(e.organizationId||this.config.organizationId)&&(t["X-Organization-Id"]=e.organizationId||this.config.organizationId),{method:"GET",timeout:this.config.timeout||3e4,retries:this.config.retries||3,...e,headers:t}}async executeRequest(e,t){const s=new AbortController,r=t.timeout?setTimeout(()=>s.abort(),t.timeout):null;try{const n={method:t.method,headers:t.headers,signal:s.signal};t.body&&t.method!=="GET"&&(n.body=typeof t.body=="string"?t.body:JSON.stringify(t.body));const i=await fetch(e,n);return r&&clearTimeout(r),i}catch(n){throw r&&clearTimeout(r),n}}async parseResponse(e){const t=e.headers.get("Content-Type")||"";let s;if(t.includes("application/json")?s=await e.json():s=await e.text(),!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`,{cause:{status:e.status,data:s}});return s&&typeof s=="object"&&"success"in s?s:{success:!0,data:s}}createAPIError(e){if(e.cause&&typeof e.cause=="object"){const{status:t,data:s}=e.cause;if(s&&typeof s=="object"&&"errors"in s)return{code:s.code||`HTTP_${t}`,message:s.message||e.message,details:s.details}}return{code:"UNKNOWN_ERROR",message:e.message||"An unknown error occurred",details:{originalError:e}}}}const w=o=>new h(o),u=o=>o&&typeof o=="object"&&"code"in o&&"message"in o,m=o=>u(o)?o:{code:"UNKNOWN_ERROR",message:o?.message||"An unknown error occurred",details:{originalError:o}},b=async(o,e=3,t=1e3)=>{let s;for(let r=1;r<=e;r++)try{return await o()}catch(n){if(s=n,r===e)break;const i=t*Math.pow(2,r-1);await new Promise(a=>setTimeout(a,i))}throw s},y=(o,e,t=3e5)=>{const s=new Map;return(async()=>{const r=s.get(e);if(r&&r.expires>Date.now())return r.data;const n=await o();return s.set(e,{data:n,expires:Date.now()+t}),n})()},P=async(o,e=5,t=100)=>{const s=[];for(let r=0;r<o.length;r+=e){const n=o.slice(r,r+e),i=await Promise.all(n.map(a=>a()));s.push(...i),r+e<o.length&&t>0&&await new Promise(a=>setTimeout(a,t))}return s},R=async(o,e,t,s={})=>{const r=new FormData;if(r.append("file",t),s.additionalData)for(const[n,i]of Object.entries(s.additionalData))r.append(n,String(i));return new Promise((n,i)=>{const a=new XMLHttpRequest;s.onProgress&&a.upload.addEventListener("progress",c=>{if(c.lengthComputable){const l=c.loaded/c.total*100;s.onProgress(l)}}),s.abortSignal&&s.abortSignal.addEventListener("abort",()=>{a.abort(),i(new Error("Upload aborted"))}),a.addEventListener("load",async()=>{try{const c=JSON.parse(a.responseText);a.status>=200&&a.status<300?n(c):i(new Error(`Upload failed: ${c.message||a.statusText}`))}catch{i(new Error("Failed to parse upload response"))}}),a.addEventListener("error",()=>{i(new Error("Upload failed"))}),a.open("POST",`${o.config.baseUrl}${e}`);const f=o.buildRequestConfig({}).headers||{};for(const[c,l]of Object.entries(f))c.toLowerCase()!=="content-type"&&a.setRequestHeader(c,l);a.send(r)})},E=async(o,e,t,s={})=>{const r=await fetch(`${o.config.baseUrl}${e}`,{headers:o.buildRequestConfig({}).headers,signal:s.abortSignal});if(!r.ok)throw new Error(`Download failed: ${r.statusText}`);const n=await r.blob(),i=window.URL.createObjectURL(n),a=document.createElement("a");a.style.display="none",a.href=i,a.download=t||"download",document.body.appendChild(a),a.click(),window.URL.revokeObjectURL(i),document.body.removeChild(a)};class I{constructor(e,t={}){this.url=e,this.config=t,d(this,"ws",null),d(this,"reconnectAttempts",0),d(this,"maxReconnectAttempts",5),d(this,"reconnectDelay",1e3),d(this,"messageQueue",[]),d(this,"eventHandlers",new Map)}connect(){return new Promise((e,t)=>{try{const s=new URL(this.url);this.config.token&&s.searchParams.set("token",this.config.token),this.config.organizationId&&s.searchParams.set("organizationId",this.config.organizationId),this.ws=new WebSocket(s.toString()),this.ws.onopen=()=>{for(this.reconnectAttempts=0;this.messageQueue.length>0;){const r=this.messageQueue.shift();this.ws.send(JSON.stringify(r))}e()},this.ws.onmessage=r=>{try{const n=JSON.parse(r.data);this.handleMessage(n)}catch(n){console.error("Failed to parse WebSocket message:",n)}},this.ws.onclose=()=>{this.ws=null,this.config.autoReconnect!==!1&&this.reconnectAttempts<this.maxReconnectAttempts&&setTimeout(()=>{this.reconnectAttempts++,this.connect()},this.reconnectDelay*Math.pow(2,this.reconnectAttempts))},this.ws.onerror=r=>{t(r)}}catch(s){t(s)}})}disconnect(){this.ws&&(this.ws.close(),this.ws=null)}send(e){this.ws&&this.ws.readyState===WebSocket.OPEN?this.ws.send(JSON.stringify(e)):this.messageQueue.push(e)}on(e,t){return this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set),this.eventHandlers.get(e).add(t),()=>{this.eventHandlers.get(e)?.delete(t)}}handleMessage(e){const{type:t,payload:s}=e;if(this.eventHandlers.has(t))for(const r of this.eventHandlers.get(t))r(s)}}exports.APIClient=h;exports.APIWebSocket=I;exports.batchRequests=P;exports.createAPIClient=w;exports.downloadFile=E;exports.handleAPIError=m;exports.isAPIError=u;exports.retryRequest=b;exports.uploadFile=R;exports.withCache=y;
//# sourceMappingURL=api.cjs.map