@jetlinks-web/core 2.3.0 → 2.3.1

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/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ interface Options {
28
28
  * @param status 错误code
29
29
  * @param error 错误实例
30
30
  */
31
- handleError?: (msg: string, status: string | number, error: AxiosError<any>) => void;
31
+ handleError?: (msg: string, status: string | number, error: AxiosError<any>) => void | Promise<any>;
32
32
  requestOptions?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Record<string, any>;
33
33
  isCreateTokenRefresh?: boolean;
34
34
  }
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{TOKEN_KEY as l,BASE_API as q,LOCAL_BASE_API as E}from"@jetlinks-web/constants";import{getToken as x,randomString as O}from"@jetlinks-web/utils";import b from"axios";import{isFunction as g,isObject as k}from"lodash-es";var h=class{instance=null;options;failedQueue=[];isRefreshing=!1;pendingRequests=new Map;isApp=window.__MICRO_APP_ENVIRONMENT__;constructor(e){this.options={filter_url:[],code:200,codeKey:"status",timeout:1e3*15,handleRequest:void 0,handleResponse:void 0,handleError:void 0,langKey:"lang",requestOptions:t=>({}),tokenExpiration:()=>{},handleReconnect:()=>Promise.resolve(),isCreateTokenRefresh:!1,cancelDuplicateRequests:!1,...e},window.JetlinksCore?.instance&&(this.instance=window.JetlinksCore.instance)}initialize(e){e&&(this.options={...this.options,...e}),this.instance=b.create({withCredentials:!1,timeout:this.options.timeout,baseURL:q}),this.instance.interceptors.request.use(t=>this.handleRequest(t),t=>this.errorHandler(t)),this.instance.interceptors.response.use(t=>this.handleResponse(t),t=>this.errorHandler(t))}getInstance(){return this.instance||this.initialize(),this.instance}generateRequestKey(e){let t=e.method?.toUpperCase()||"GET",s=e.url||"",n=e.params||{},i=e.data||{},r=t==="GET"?n:i,a="";try{a=JSON.stringify(r,Object.keys(r).sort())}catch{a=O(16)}return`${t}:${s}:${a}`}requestRecords(e){if(!this.options.cancelDuplicateRequests)return;let t=this.generateRequestKey(e);this.pendingRequests.has(t)&&(this.pendingRequests.get(t)?.abort(),this.pendingRequests.delete(t));let s=new AbortController;e.signal=s.signal,e.__requestKey=t,this.pendingRequests.set(t,s)}handleRequest(e){this.requestRecords(e);let t=x(),s=localStorage.getItem(this.options.langKey),n=localStorage.getItem(E);if(s&&(e.headers[this.options.langKey]=s),n&&!e.baseURL){let i=e.url.startsWith("/")?e.url:`/${e.url}`;e.url=n+i}if(!t&&!this.options.filter_url?.some(i=>e.url?.includes(i)))return this.options.tokenExpiration?.(),e;if(e.headers[l]||(e.headers[l]=t),this.options.requestOptions&&g(this.options.requestOptions)){let i=this.options.requestOptions(e);if(i&&k(i))for(let r in i)e[r]=i[r]}return e}handleResponse(e){let t=e.config?.__requestKey;if(t&&this.pendingRequests.delete(t),this.options.handleResponse&&g(this.options.handleResponse))return this.options.handleResponse(e);if(e.data instanceof ArrayBuffer)return e;let s=e.data[this.options.codeKey||"status"];return typeof e.data=="object"&&typeof e.data.success>"u"&&(e.data.success=s===this.options.code),e.data}async createTokenRefreshHandler(e){let t=e.config;if(this.isRefreshing)return new Promise((s,n)=>{this.failedQueue.push({resolve:s,reject:n})}).then(s=>t.signal?.aborted?Promise.reject(new b.Cancel("Request aborted")):(t.headers[l]=s,this.instance(t))).catch(s=>Promise.reject(s));t._retry=!0,this.isRefreshing=!0;try{if(await this.options.handleReconnect?.()){let n=x();return t.headers[l]=n,this.failedQueue.forEach(i=>i.resolve(n)),this.instance(t)}}catch(s){throw this.failedQueue.forEach(n=>n.reject(s)),s}finally{this.failedQueue=[],this.isRefreshing=!1}}async errorHandler(e){let t=e.config?.__requestKey;if(t&&this.pendingRequests.delete(t),b.isCancel(e))return Promise.reject(e);let s=e.response?.message||"Error",n=0,i=e.response;if(i){let{data:r,status:a}=i;switch(n=a,a){case 400:case 403:case 500:s=`${r?.message}`.substring(0,90);break;case 401:if(s=r?.result?.text||"\u7528\u6237\u672A\u767B\u5F55",this.options.tokenExpiration?.(e),this.options.isCreateTokenRefresh)return this.createTokenRefreshHandler(e);break;case 404:s=r?.message||`${r?.error} ${r?.path}`;break;default:break}}else{let r=e;r.message&&(s=r.message.includes("timeout")?"\u63A5\u53E3\u54CD\u5E94\u8D85\u65F6":r.message,n="timeout")}return this.options.handleError&&g(this.options.handleError)&&this.options.handleError(s,n,e),Promise.reject(e)}abortAllRequests(){this.pendingRequests.forEach(e=>e.abort()),this.pendingRequests.clear()}abortRequest(e){let t=this.pendingRequests.get(e);t&&(t.abort(),this.pendingRequests.delete(e))}getPendingRequestsCount(){return this.pendingRequests.size}post(e,t={},s){return this.getInstance()({method:"POST",url:e,data:t,...s})}get(e,t=void 0,s){return this.getInstance()({method:"GET",url:e,params:t,...s})}put(e,t={},s){return this.getInstance()({method:"PUT",url:e,data:t,...s})}patch(e,t={},s){return this.getInstance()({method:"PATCH",url:e,data:t,...s})}remove(e,t=void 0,s){return this.getInstance()({method:"DELETE",url:e,params:t,...s})}getStream(e,t,s){return this.get(e,t,{responseType:"arraybuffer",...s})}postStream(e,t,s){return this.post(e,t,{responseType:"arraybuffer",...s})}},o=new h,Y=p=>{let e=new h(p);return e.initialize(),e},w=class{constructor(e,t){this.basePath=e;this.basePath=e.startsWith("/")?e:`/${e}`,this._instance=t}_instance;get instance(){return this._instance||o.getInstance()}requestWrapper(e,t,s={},n={}){let{url:i=e,method:r=t,...a}=n;return this[r].call(this,i,s,a)}page(e={},t={url:void 0,method:void 0}){return this.requestWrapper("/_query","post",e,t)}noPage(e={},t={url:void 0,method:void 0}){return this.requestWrapper("/_query/no-paging","post",{paging:!1,...e},t)}detail(e,t,s={url:void 0,method:void 0}){return this.requestWrapper(`/${e}/detail`,"get",t,s)}save(e={},t={url:void 0,method:void 0}){return this.requestWrapper("","post",e,t)}update(e={},t={url:void 0,method:void 0}){return this.requestWrapper("","patch",e,t)}delete(e,t,s={url:void 0,method:void 0}){return this.requestWrapper(`/${e}`,"remove",t,s)}batch(e={},t,s){let n=`/_batch${t?"/"+t:""}`;return this.requestWrapper(n,"post",e,s)}post(e,t,s){return this.instance({method:"POST",url:`${this.basePath}${e}`,data:t,...s})}get(e,t,s){return this.instance({method:"GET",url:`${this.basePath}${e}`,params:t,...s})}put(e,t,s){return this.instance({method:"PUT",url:`${this.basePath}${e}`,data:t,...s})}patch(e,t,s){return this.instance({method:"PATCH",url:`${this.basePath}${e}`,data:t,...s})}remove(e,t,s){return this.instance({method:"DELETE",url:`${this.basePath}${e}`,params:t,...s})}getStream(e,t,s){return this.get(`${e}`,t,{responseType:"arraybuffer",...s})}postStream(e,t,s){return this.post(`${e}`,t,{responseType:"arraybuffer",...s})}},F={post:o.post.bind(o),get:o.get.bind(o),put:o.put.bind(o),patch:o.patch.bind(o),remove:o.remove.bind(o),getStream:o.getStream.bind(o),postStream:o.postStream.bind(o)},V=o.post.bind(o),X=o.get.bind(o),Z=o.put.bind(o),ee=o.patch.bind(o),te=o.remove.bind(o),se=o.getStream.bind(o),ne=o.postStream.bind(o),ie=()=>o.abortAllRequests(),re=()=>o.getInstance(),C,oe=p=>{o.initialize(p),C=o.getInstance()};import{getToken as P}from"@jetlinks-web/utils";import{BASE_API as _,TOKEN_KEY as W}from"@jetlinks-web/constants";import{isFunction as T,isObject as S}from"lodash-es";import{Observable as I}from"rxjs";var d=class{options={code:200,codeKey:"status"};activeRequests=new Set;constructor(e){e&&(this.options={...this.options,...e})}create(e){this.options={...this.options,...e}}getUrl(e){return(this.options.baseURL??_)+e}processStream(e,t,s){let n=new TextDecoder,i="",r=()=>{if(!s.isActive){e.cancel(),t.complete();return}e.read().then(({done:a,value:u})=>{if(a){this.flushBuffer(i,t),t.complete();return}i+=n.decode(u,{stream:!0}),i=this.parseLines(i,t),r()}).catch(a=>{a.name!=="AbortError"&&t.error(a)})};r()}parseLines(e,t){let s=e.split(`
2
- `);for(let n=0;n<s.length-1;n++){let i=s[n].trim();if(i.length>0)try{let r=i.startsWith("data:")?i.slice(5):i;t.next(JSON.parse(r))}catch(r){return t.error(r),""}}return s[s.length-1]}flushBuffer(e,t){let s=e.trim();if(s.length>0)try{t.next(JSON.parse(s))}catch(n){t.error(n)}}request(e,t,s,n={}){let i=this.getUrl(t);return new I(r=>{let a=new AbortController,u={controller:a,isActive:!0};this.activeRequests.add(u);let m={method:e,signal:a.signal,keepalive:!0,...n,...this.handleRequest(i,e)};return e==="POST"&&s!==void 0&&(m.body=S(s)?JSON.stringify(s):s),fetch(i,m).then(f=>{let y=f.body?.getReader();if(!y){r.error(new Error("No readable stream available"));return}u.isActive=!0,this.processStream(y,r,u)}).catch(f=>{r.error(f)}),()=>{u.isActive=!1,a.abort(),this.activeRequests.delete(u)}})}get(e,t="{}",s={}){return this.request("GET",e,void 0,s)}post(e,t={},s={}){return this.request("POST",e,t,s)}handleRequest(e,t){let s={};t==="POST"&&(s["Content-Type"]="application/x-ndjson");let n={headers:s},i=P();if(!i&&this.options.filter_url?.some(r=>e.includes(r)))return this.options.tokenExpiration?.(),n;if(i&&(s[W]=i),this.options.requestOptions&&T(this.options.requestOptions)){let r=this.options.requestOptions(n);r&&S(r)&&Object.assign(n,r)}return n}handleResponse(e){return this.options.handleResponse&&T(this.options.handleResponse)?this.options.handleResponse(e):e}cancelAll(){this.activeRequests.forEach(e=>{e.isActive=!1,e.controller.abort()}),this.activeRequests.clear()}},v=new d,de=p=>new d(p),fe=p=>{v.create(p)},be=v;import{webSocket as M}from"rxjs/webSocket";import{Observable as N,Subject as $,timer as A,EMPTY as j}from"rxjs";import{retry as H,catchError as L}from"rxjs/operators";import{notification as J}from"ant-design-vue";var c=window.__MICRO_APP_ENVIRONMENT__,R=class{ws=null;subscriptions=new Map;pendingSubscriptions=new Map;heartbeatSubscription=null;reconnectAttempts=0;maxReconnectAttempts=2;isConnected=!1;tempQueue=[];url="";options={};wsClient;constructor(e){this.setOptions(e),this.setupConnectionMonitor(),c&&window.microApp.addGlobalDataListener(t=>{this.wsClient=t.wsClient})}setOptions(e){this.options=e||{}}initWebSocket(e){this.url=e}setupConnectionMonitor(){c||(window.addEventListener("online",()=>{console.log("Network is online, attempting to reconnect..."),this.reconnect()}),window.addEventListener("offline",()=>{console.log("Network is offline, caching subscriptions..."),this.cacheSubscriptions()}),window.addEventListener("beforeunload",()=>{this.disconnect()}))}getReconnectDelay(){return this.reconnectAttempts<=10?5e3:this.reconnectAttempts<=20?15e3:6e4}setupWebSocket(){if(c&&this.wsClient){this.wsClient.setupWebSocket();return}this.ws||!this.url||(this.ws=M({url:this.url,openObserver:{next:()=>{console.log("WebSocket connected"),this.isConnected=!0,this.reconnectAttempts=0,this.startHeartbeat(),this.restoreSubscriptions(),this.processTempQueue()}},closeObserver:{next:()=>{console.log("WebSocket disconnected"),this.isConnected=!1;let e=this.getReconnectDelay();setTimeout(()=>{this.reconnectAttempts+=1,!(this.reconnectAttempts>this.maxReconnectAttempts)&&(this.cacheSubscriptions(),this.stopHeartbeat(),this.reconnect())},e)}}}),this.ws.pipe(L(e=>(console.error("WebSocket error:",e),j)),H({delay:(e,t)=>{if(this.reconnectAttempts=t,t>this.maxReconnectAttempts)throw new Error("Max reconnection attempts reached");return A(this.getReconnectDelay())}})).subscribe(e=>this.handleMessage(e),e=>console.error("WebSocket error:",e)))}startHeartbeat(){if(c&&this.wsClient){this.wsClient.startHeartbeat();return}this.stopHeartbeat(),this.heartbeatSubscription=A(0,2e3).subscribe(()=>{this.send({type:"ping"})})}stopHeartbeat(){if(c&&this.wsClient){this.wsClient.stopHeartbeat();return}this.heartbeatSubscription&&(this.heartbeatSubscription.unsubscribe(),this.heartbeatSubscription=null)}handleMessage(e){if(c&&this.wsClient){this.wsClient.handleMessage(e);return}if(e.type==="pong")return;if(e.type==="error"){this.options.onError?this.options.onError(e):J.error({key:"error",message:e.message});return}let t=this.subscriptions.get(e.requestId||"");t&&(e.type==="complete"?(t.complete(),this.subscriptions.delete(e.requestId||"")):e.type==="result"&&t.next(e))}processTempQueue(){if(c&&this.wsClient){this.wsClient.processTempQueue();return}for(;this.tempQueue.length>0;){let e=this.tempQueue.shift();e&&this.send(e)}}cacheSubscriptions(){if(c&&this.wsClient){this.wsClient.cacheSubscriptions();return}this.pendingSubscriptions=new Map(this.subscriptions),this.subscriptions.clear()}restoreSubscriptions(){if(c&&this.wsClient){this.wsClient.restoreSubscriptions();return}this.pendingSubscriptions.forEach((e,t)=>{this.subscriptions.set(t,e)}),this.pendingSubscriptions.clear()}reconnect(){if(c&&this.wsClient){this.wsClient.reconnect();return}!this.isConnected&&navigator.onLine&&(this.ws=null,this.setupWebSocket())}connect(){if(c&&this.wsClient){this.wsClient.connect();return}this.setupWebSocket()}disconnect(){if(c&&this.wsClient){this.wsClient.disconnect();return}this.ws&&(this.ws.complete(),this.ws=null),this.stopHeartbeat(),this.subscriptions.clear(),this.pendingSubscriptions.clear(),this.tempQueue=[]}send(e){if(c&&this.wsClient){this.wsClient.send(e);return}this.ws&&this.isConnected?this.ws.next(e):this.tempQueue.push(e)}getWebSocket(e,t,s={}){if(console.log("getWebSocket",this.wsClient,e),c&&this.wsClient)return this.wsClient.getWebSocket(e,t,s);let n=new $;this.subscriptions.set(e,n);let i={id:e,topic:t,parameter:s,type:"sub"};return this.send(i),new N(r=>{let a=n.subscribe(r);return()=>{a.unsubscribe(),this.send({id:e,type:"unsub"}),this.subscriptions.delete(e)}})}},Te=new R;var K,ve=p=>{K=p};var U={},qe=(p={})=>{U=p};var Q,Oe=p=>{Q=p};export{h as AxiosService,d as NdJson,w as Request,R as WebSocketClient,ie as abortAllRequests,oe as crateAxios,Y as createAxiosService,de as createNdJson,fe as createNdJsonService,X as get,re as getInstance,se as getStream,Oe as installLocales,ve as installRouter,qe as installStores,C as instance,Q as locales,be as ndJson,ee as patch,V as post,ne as postStream,Z as put,te as remove,F as request,K as router,U as stores,Te as wsClient};
1
+ import{TOKEN_KEY as l,BASE_API as q,LOCAL_BASE_API as E}from"@jetlinks-web/constants";import{getToken as x,randomString as O}from"@jetlinks-web/utils";import b from"axios";import{isFunction as g,isObject as k}from"lodash-es";var h=class{instance=null;options;failedQueue=[];isRefreshing=!1;pendingRequests=new Map;isApp=window.__MICRO_APP_ENVIRONMENT__;constructor(e){this.options={filter_url:[],code:200,codeKey:"status",timeout:1e3*15,handleRequest:void 0,handleResponse:void 0,handleError:void 0,langKey:"lang",requestOptions:t=>({}),tokenExpiration:()=>{},handleReconnect:()=>Promise.resolve(),isCreateTokenRefresh:!1,cancelDuplicateRequests:!1,...e},window.JetlinksCore?.instance&&(this.instance=window.JetlinksCore.instance)}initialize(e){e&&(this.options={...this.options,...e}),this.instance=b.create({withCredentials:!1,timeout:this.options.timeout,baseURL:q}),this.instance.interceptors.request.use(t=>this.handleRequest(t),t=>this.errorHandler(t)),this.instance.interceptors.response.use(t=>this.handleResponse(t),t=>this.errorHandler(t))}getInstance(){return this.instance||this.initialize(),this.instance}generateRequestKey(e){let t=e.method?.toUpperCase()||"GET",s=e.url||"",i=e.params||{},r=e.data||{},n=t==="GET"?i:r,a="";try{a=JSON.stringify(n,Object.keys(n).sort())}catch{a=O(16)}return`${t}:${s}:${a}`}requestRecords(e){if(!this.options.cancelDuplicateRequests)return;let t=this.generateRequestKey(e);this.pendingRequests.has(t)&&(this.pendingRequests.get(t)?.abort(),this.pendingRequests.delete(t));let s=new AbortController;e.signal=s.signal,e.__requestKey=t,this.pendingRequests.set(t,s)}handleRequest(e){this.requestRecords(e);let t=x(),s=localStorage.getItem(this.options.langKey),i=localStorage.getItem(E);if(s&&(e.headers[this.options.langKey]=s),i&&!e.baseURL){let r=e.url.startsWith("/")?e.url:`/${e.url}`;e.url=i+r}if(!t&&!this.options.filter_url?.some(r=>e.url?.includes(r)))return this.options.tokenExpiration?.(),e;if(e.headers[l]||(e.headers[l]=t),this.options.requestOptions&&g(this.options.requestOptions)){let r=this.options.requestOptions(e);if(r&&k(r))for(let n in r)e[n]=r[n]}return e}handleResponse(e){let t=e.config?.__requestKey;if(t&&this.pendingRequests.delete(t),this.options.handleResponse&&g(this.options.handleResponse))return this.options.handleResponse(e);if(e.data instanceof ArrayBuffer)return e;let s=e.data[this.options.codeKey||"status"];return typeof e.data=="object"&&typeof e.data.success>"u"&&(e.data.success=s===this.options.code),e.data}async createTokenRefreshHandler(e){let t=e.config;if(this.isRefreshing)return new Promise((s,i)=>{this.failedQueue.push({resolve:s,reject:i})}).then(s=>t.signal?.aborted?Promise.reject(new b.Cancel("Request aborted")):(t.headers[l]=s,this.instance(t))).catch(s=>Promise.reject(s));t._retry=!0,this.isRefreshing=!0;try{if(await this.options.handleReconnect?.()){let i=x();return t.headers[l]=i,this.failedQueue.forEach(r=>r.resolve(i)),this.instance(t)}}catch(s){throw this.failedQueue.forEach(i=>i.reject(s)),s}finally{this.failedQueue=[],this.isRefreshing=!1}}async errorHandler(e){let t=e.config?.__requestKey;if(t&&this.pendingRequests.delete(t),b.isCancel(e))return Promise.reject(e);let s=e.response?.message||"Error",i=0,r=e.response;if(r){let{data:n,status:a}=r;switch(i=a,a){case 400:case 403:case 500:s=`${n?.message}`.substring(0,90);break;case 401:if(s=n?.result?.text||"\u7528\u6237\u672A\u767B\u5F55",this.options.tokenExpiration?.(e),this.options.isCreateTokenRefresh)return this.createTokenRefreshHandler(e);break;case 404:s=n?.message||`${n?.error} ${n?.path}`;break;default:break}}else{let n=e;n.message&&(s=n.message.includes("timeout")?"\u63A5\u53E3\u54CD\u5E94\u8D85\u65F6":n.message,i="timeout")}if(this.options.handleError&&g(this.options.handleError)){let n=this.options.handleError(s,i,e);if(n&&typeof n.then=="function")return n}return Promise.reject(e)}abortAllRequests(){this.pendingRequests.forEach(e=>e.abort()),this.pendingRequests.clear()}abortRequest(e){let t=this.pendingRequests.get(e);t&&(t.abort(),this.pendingRequests.delete(e))}getPendingRequestsCount(){return this.pendingRequests.size}post(e,t={},s){return this.getInstance()({method:"POST",url:e,data:t,...s})}get(e,t=void 0,s){return this.getInstance()({method:"GET",url:e,params:t,...s})}put(e,t={},s){return this.getInstance()({method:"PUT",url:e,data:t,...s})}patch(e,t={},s){return this.getInstance()({method:"PATCH",url:e,data:t,...s})}remove(e,t=void 0,s){return this.getInstance()({method:"DELETE",url:e,params:t,...s})}getStream(e,t,s){return this.get(e,t,{responseType:"arraybuffer",...s})}postStream(e,t,s){return this.post(e,t,{responseType:"arraybuffer",...s})}},o=new h,Y=p=>{let e=new h(p);return e.initialize(),e},w=class{constructor(e,t){this.basePath=e;this.basePath=e.startsWith("/")?e:`/${e}`,this._instance=t}_instance;get instance(){return this._instance||o.getInstance()}requestWrapper(e,t,s={},i={}){let{url:r=e,method:n=t,...a}=i;return this[n].call(this,r,s,a)}page(e={},t={url:void 0,method:void 0}){return this.requestWrapper("/_query","post",e,t)}noPage(e={},t={url:void 0,method:void 0}){return this.requestWrapper("/_query/no-paging","post",{paging:!1,...e},t)}detail(e,t,s={url:void 0,method:void 0}){return this.requestWrapper(`/${e}/detail`,"get",t,s)}save(e={},t={url:void 0,method:void 0}){return this.requestWrapper("","post",e,t)}update(e={},t={url:void 0,method:void 0}){return this.requestWrapper("","patch",e,t)}delete(e,t,s={url:void 0,method:void 0}){return this.requestWrapper(`/${e}`,"remove",t,s)}batch(e={},t,s){let i=`/_batch${t?"/"+t:""}`;return this.requestWrapper(i,"post",e,s)}post(e,t,s){return this.instance({method:"POST",url:`${this.basePath}${e}`,data:t,...s})}get(e,t,s){return this.instance({method:"GET",url:`${this.basePath}${e}`,params:t,...s})}put(e,t,s){return this.instance({method:"PUT",url:`${this.basePath}${e}`,data:t,...s})}patch(e,t,s){return this.instance({method:"PATCH",url:`${this.basePath}${e}`,data:t,...s})}remove(e,t,s){return this.instance({method:"DELETE",url:`${this.basePath}${e}`,params:t,...s})}getStream(e,t,s){return this.get(`${e}`,t,{responseType:"arraybuffer",...s})}postStream(e,t,s){return this.post(`${e}`,t,{responseType:"arraybuffer",...s})}},F={post:o.post.bind(o),get:o.get.bind(o),put:o.put.bind(o),patch:o.patch.bind(o),remove:o.remove.bind(o),getStream:o.getStream.bind(o),postStream:o.postStream.bind(o)},V=o.post.bind(o),X=o.get.bind(o),Z=o.put.bind(o),ee=o.patch.bind(o),te=o.remove.bind(o),se=o.getStream.bind(o),ne=o.postStream.bind(o),ie=()=>o.abortAllRequests(),re=()=>o.getInstance(),C,oe=p=>{o.initialize(p),C=o.getInstance()};import{getToken as P}from"@jetlinks-web/utils";import{BASE_API as _,TOKEN_KEY as W}from"@jetlinks-web/constants";import{isFunction as T,isObject as S}from"lodash-es";import{Observable as I}from"rxjs";var d=class{options={code:200,codeKey:"status"};activeRequests=new Set;constructor(e){e&&(this.options={...this.options,...e})}create(e){this.options={...this.options,...e}}getUrl(e){return(this.options.baseURL??_)+e}processStream(e,t,s){let i=new TextDecoder,r="",n=()=>{if(!s.isActive){e.cancel(),t.complete();return}e.read().then(({done:a,value:u})=>{if(a){this.flushBuffer(r,t),t.complete();return}r+=i.decode(u,{stream:!0}),r=this.parseLines(r,t),n()}).catch(a=>{a.name!=="AbortError"&&t.error(a)})};n()}parseLines(e,t){let s=e.split(`
2
+ `);for(let i=0;i<s.length-1;i++){let r=s[i].trim();if(r.length>0)try{let n=r.startsWith("data:")?r.slice(5):r;t.next(JSON.parse(n))}catch(n){return t.error(n),""}}return s[s.length-1]}flushBuffer(e,t){let s=e.trim();if(s.length>0)try{t.next(JSON.parse(s))}catch(i){t.error(i)}}request(e,t,s,i={}){let r=this.getUrl(t);return new I(n=>{let a=new AbortController,u={controller:a,isActive:!0};this.activeRequests.add(u);let m={method:e,signal:a.signal,keepalive:!0,...i,...this.handleRequest(r,e)};return e==="POST"&&s!==void 0&&(m.body=S(s)?JSON.stringify(s):s),fetch(r,m).then(f=>{let y=f.body?.getReader();if(!y){n.error(new Error("No readable stream available"));return}u.isActive=!0,this.processStream(y,n,u)}).catch(f=>{n.error(f)}),()=>{u.isActive=!1,a.abort(),this.activeRequests.delete(u)}})}get(e,t="{}",s={}){return this.request("GET",e,void 0,s)}post(e,t={},s={}){return this.request("POST",e,t,s)}handleRequest(e,t){let s={};t==="POST"&&(s["Content-Type"]="application/x-ndjson");let i={headers:s},r=P();if(!r&&this.options.filter_url?.some(n=>e.includes(n)))return this.options.tokenExpiration?.(),i;if(r&&(s[W]=r),this.options.requestOptions&&T(this.options.requestOptions)){let n=this.options.requestOptions(i);n&&S(n)&&Object.assign(i,n)}return i}handleResponse(e){return this.options.handleResponse&&T(this.options.handleResponse)?this.options.handleResponse(e):e}cancelAll(){this.activeRequests.forEach(e=>{e.isActive=!1,e.controller.abort()}),this.activeRequests.clear()}},v=new d,de=p=>new d(p),fe=p=>{v.create(p)},be=v;import{webSocket as M}from"rxjs/webSocket";import{Observable as N,Subject as $,timer as A,EMPTY as j}from"rxjs";import{retry as H,catchError as L}from"rxjs/operators";import{notification as J}from"ant-design-vue";var c=window.__MICRO_APP_ENVIRONMENT__,R=class{ws=null;subscriptions=new Map;pendingSubscriptions=new Map;heartbeatSubscription=null;reconnectAttempts=0;maxReconnectAttempts=2;isConnected=!1;tempQueue=[];url="";options={};wsClient;constructor(e){this.setOptions(e),this.setupConnectionMonitor(),c&&window.microApp.addGlobalDataListener(t=>{this.wsClient=t.wsClient})}setOptions(e){this.options=e||{}}initWebSocket(e){this.url=e}setupConnectionMonitor(){c||(window.addEventListener("online",()=>{console.log("Network is online, attempting to reconnect..."),this.reconnect()}),window.addEventListener("offline",()=>{console.log("Network is offline, caching subscriptions..."),this.cacheSubscriptions()}),window.addEventListener("beforeunload",()=>{this.disconnect()}))}getReconnectDelay(){return this.reconnectAttempts<=10?5e3:this.reconnectAttempts<=20?15e3:6e4}setupWebSocket(){if(c&&this.wsClient){this.wsClient.setupWebSocket();return}this.ws||!this.url||(this.ws=M({url:this.url,openObserver:{next:()=>{console.log("WebSocket connected"),this.isConnected=!0,this.reconnectAttempts=0,this.startHeartbeat(),this.restoreSubscriptions(),this.processTempQueue()}},closeObserver:{next:()=>{console.log("WebSocket disconnected"),this.isConnected=!1;let e=this.getReconnectDelay();setTimeout(()=>{this.reconnectAttempts+=1,!(this.reconnectAttempts>this.maxReconnectAttempts)&&(this.cacheSubscriptions(),this.stopHeartbeat(),this.reconnect())},e)}}}),this.ws.pipe(L(e=>(console.error("WebSocket error:",e),j)),H({delay:(e,t)=>{if(this.reconnectAttempts=t,t>this.maxReconnectAttempts)throw new Error("Max reconnection attempts reached");return A(this.getReconnectDelay())}})).subscribe(e=>this.handleMessage(e),e=>console.error("WebSocket error:",e)))}startHeartbeat(){if(c&&this.wsClient){this.wsClient.startHeartbeat();return}this.stopHeartbeat(),this.heartbeatSubscription=A(0,2e3).subscribe(()=>{this.send({type:"ping"})})}stopHeartbeat(){if(c&&this.wsClient){this.wsClient.stopHeartbeat();return}this.heartbeatSubscription&&(this.heartbeatSubscription.unsubscribe(),this.heartbeatSubscription=null)}handleMessage(e){if(c&&this.wsClient){this.wsClient.handleMessage(e);return}if(e.type==="pong")return;if(e.type==="error"){this.options.onError?this.options.onError(e):J.error({key:"error",message:e.message});return}let t=this.subscriptions.get(e.requestId||"");t&&(e.type==="complete"?(t.complete(),this.subscriptions.delete(e.requestId||"")):e.type==="result"&&t.next(e))}processTempQueue(){if(c&&this.wsClient){this.wsClient.processTempQueue();return}for(;this.tempQueue.length>0;){let e=this.tempQueue.shift();e&&this.send(e)}}cacheSubscriptions(){if(c&&this.wsClient){this.wsClient.cacheSubscriptions();return}this.pendingSubscriptions=new Map(this.subscriptions),this.subscriptions.clear()}restoreSubscriptions(){if(c&&this.wsClient){this.wsClient.restoreSubscriptions();return}this.pendingSubscriptions.forEach((e,t)=>{this.subscriptions.set(t,e)}),this.pendingSubscriptions.clear()}reconnect(){if(c&&this.wsClient){this.wsClient.reconnect();return}!this.isConnected&&navigator.onLine&&(this.ws=null,this.setupWebSocket())}connect(){if(c&&this.wsClient){this.wsClient.connect();return}this.setupWebSocket()}disconnect(){if(c&&this.wsClient){this.wsClient.disconnect();return}this.ws&&(this.ws.complete(),this.ws=null),this.stopHeartbeat(),this.subscriptions.clear(),this.pendingSubscriptions.clear(),this.tempQueue=[]}send(e){if(c&&this.wsClient){this.wsClient.send(e);return}this.ws&&this.isConnected?this.ws.next(e):this.tempQueue.push(e)}getWebSocket(e,t,s={}){if(console.log("getWebSocket",this.wsClient,e),c&&this.wsClient)return this.wsClient.getWebSocket(e,t,s);let i=new $;this.subscriptions.set(e,i);let r={id:e,topic:t,parameter:s,type:"sub"};return this.send(r),new N(n=>{let a=i.subscribe(n);return()=>{a.unsubscribe(),this.send({id:e,type:"unsub"}),this.subscriptions.delete(e)}})}},Te=new R;var K,ve=p=>{K=p};var U={},qe=(p={})=>{U=p};var Q,Oe=p=>{Q=p};export{h as AxiosService,d as NdJson,w as Request,R as WebSocketClient,ie as abortAllRequests,oe as crateAxios,Y as createAxiosService,de as createNdJson,fe as createNdJsonService,X as get,re as getInstance,se as getStream,Oe as installLocales,ve as installRouter,qe as installStores,C as instance,Q as locales,be as ndJson,ee as patch,V as post,ne as postStream,Z as put,te as remove,F as request,K as router,U as stores,Te as wsClient};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetlinks-web/core",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "main": "dist/index.mjs",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
package/src/axios.ts CHANGED
@@ -309,7 +309,11 @@ export class AxiosService {
309
309
  }
310
310
 
311
311
  if (this.options.handleError && isFunction(this.options.handleError)) {
312
- this.options.handleError(description, _status, err as any)
312
+ const result = this.options.handleError(description, _status, err as any)
313
+ // 如果 handleError 返回了 Promise,则返回它以替换原始错误
314
+ if (result && typeof result.then === 'function') {
315
+ return result
316
+ }
313
317
  }
314
318
 
315
319
  return Promise.reject(err)
package/src/type.ts CHANGED
@@ -30,7 +30,7 @@ export interface Options {
30
30
  * @param status 错误code
31
31
  * @param error 错误实例
32
32
  */
33
- handleError?: (msg: string, status: string | number, error: AxiosError<any>) => void
33
+ handleError?: (msg: string, status: string | number, error: AxiosError<any>) => void | Promise<any>
34
34
  requestOptions?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Record<string, any>
35
35
  isCreateTokenRefresh?: boolean
36
36
  }