@jetlinks-web/core 2.2.18 → 2.3.0
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 +213 -51
- package/dist/index.mjs +2 -3
- package/package.json +3 -3
- package/src/axios.ts +528 -267
- package/src/fetch.ts +225 -195
- package/src/type.ts +14 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { AxiosError, AxiosResponse, InternalAxiosRequestConfig, AxiosInstance } from 'axios';
|
|
2
|
-
import { AxiosResponseRewrite } from '@jetlinks-web/types';
|
|
3
2
|
import { Observable } from 'rxjs';
|
|
4
3
|
|
|
4
|
+
interface AxiosResponseRewrite<T = any> extends AxiosResponse<T, any> {
|
|
5
|
+
result: T;
|
|
6
|
+
success: boolean;
|
|
7
|
+
}
|
|
5
8
|
interface Options {
|
|
6
|
-
tokenExpiration: (err?: AxiosError<any>, response?:
|
|
9
|
+
tokenExpiration: (err?: AxiosError<any>, response?: AxiosResponseRewrite) => void;
|
|
7
10
|
handleReconnect: () => Promise<any>;
|
|
8
11
|
filter_url?: Array<string>;
|
|
9
12
|
code?: number;
|
|
@@ -18,7 +21,7 @@ interface Options {
|
|
|
18
21
|
* response处理函数
|
|
19
22
|
* @param response AxiosResponse实例
|
|
20
23
|
*/
|
|
21
|
-
handleResponse?: (response:
|
|
24
|
+
handleResponse?: (response: AxiosResponseRewrite) => void;
|
|
22
25
|
/**
|
|
23
26
|
* 错误处理函数
|
|
24
27
|
* @param msg 错误消息
|
|
@@ -48,65 +51,153 @@ interface RequestOptions {
|
|
|
48
51
|
[key: string]: any;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
/**
|
|
55
|
+
* 扩展的 Options 接口,添加重复请求控制
|
|
56
|
+
*/
|
|
57
|
+
interface ExtendedOptions extends Options {
|
|
58
|
+
/**
|
|
59
|
+
* 是否取消重复请求,只保留最后一次
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
cancelDuplicateRequests?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* AxiosService 类 - 封装所有 axios 相关功能
|
|
66
|
+
*/
|
|
67
|
+
declare class AxiosService {
|
|
68
|
+
private instance;
|
|
69
|
+
private options;
|
|
70
|
+
private failedQueue;
|
|
71
|
+
private isRefreshing;
|
|
72
|
+
private pendingRequests;
|
|
73
|
+
private isApp;
|
|
74
|
+
constructor(options?: Partial<ExtendedOptions>);
|
|
75
|
+
/**
|
|
76
|
+
* 初始化 axios 实例
|
|
77
|
+
*/
|
|
78
|
+
initialize(options?: Partial<ExtendedOptions>): void;
|
|
79
|
+
/**
|
|
80
|
+
* 获取 axios 实例
|
|
81
|
+
*/
|
|
82
|
+
getInstance(): AxiosInstance;
|
|
83
|
+
/**
|
|
84
|
+
* 生成请求的唯一标识
|
|
85
|
+
* 如果启用了 cancelDuplicateRequests,则基于 method + url + params/data
|
|
86
|
+
* 否则使用随机字符串
|
|
87
|
+
*/
|
|
88
|
+
private generateRequestKey;
|
|
89
|
+
/**
|
|
90
|
+
* 记录请求 - 支持 AbortController
|
|
91
|
+
*/
|
|
92
|
+
private requestRecords;
|
|
93
|
+
/**
|
|
94
|
+
* 请求拦截器处理
|
|
95
|
+
*/
|
|
96
|
+
private handleRequest;
|
|
97
|
+
/**
|
|
98
|
+
* 响应拦截器处理
|
|
99
|
+
*/
|
|
100
|
+
private handleResponse;
|
|
101
|
+
/**
|
|
102
|
+
* Token 刷新处理
|
|
103
|
+
*/
|
|
104
|
+
private createTokenRefreshHandler;
|
|
105
|
+
/**
|
|
106
|
+
* 错误处理
|
|
107
|
+
*/
|
|
108
|
+
private errorHandler;
|
|
109
|
+
/**
|
|
110
|
+
* 取消所有进行中的请求
|
|
111
|
+
*/
|
|
112
|
+
abortAllRequests(): void;
|
|
113
|
+
/**
|
|
114
|
+
* 取消特定请求
|
|
115
|
+
*/
|
|
116
|
+
abortRequest(requestKey: string): void;
|
|
117
|
+
/**
|
|
118
|
+
* 获取当前进行中的请求数量
|
|
119
|
+
*/
|
|
120
|
+
getPendingRequestsCount(): number;
|
|
121
|
+
/**
|
|
122
|
+
* HTTP 方法封装 - POST
|
|
123
|
+
*/
|
|
124
|
+
post<T = any>(url: string, data?: any, ext?: any): Promise<AxiosResponseRewrite<T>>;
|
|
125
|
+
/**
|
|
126
|
+
* HTTP 方法封装 - GET
|
|
127
|
+
*/
|
|
128
|
+
get<T = any>(url: string, params?: any, ext?: any): Promise<AxiosResponseRewrite<T>>;
|
|
129
|
+
/**
|
|
130
|
+
* HTTP 方法封装 - PUT
|
|
131
|
+
*/
|
|
132
|
+
put<T = any>(url: string, data?: any, ext?: any): Promise<AxiosResponseRewrite<T>>;
|
|
133
|
+
/**
|
|
134
|
+
* HTTP 方法封装 - PATCH
|
|
135
|
+
*/
|
|
136
|
+
patch<T = any>(url: string, data?: any, ext?: any): Promise<AxiosResponseRewrite<T>>;
|
|
137
|
+
/**
|
|
138
|
+
* HTTP 方法封装 - DELETE
|
|
139
|
+
*/
|
|
140
|
+
remove<T = any>(url: string, params?: any, ext?: any): Promise<AxiosResponseRewrite<T>>;
|
|
141
|
+
/**
|
|
142
|
+
* 获取流数据 - GET
|
|
143
|
+
*/
|
|
144
|
+
getStream(url: string, params?: any, ext?: any): Promise<any>;
|
|
145
|
+
/**
|
|
146
|
+
* 获取流数据 - POST
|
|
147
|
+
*/
|
|
148
|
+
postStream(url: string, data: any, ext?: any): Promise<any>;
|
|
149
|
+
}
|
|
150
|
+
declare const createAxiosService: (options?: Partial<ExtendedOptions>) => AxiosService;
|
|
151
|
+
/**
|
|
152
|
+
* Request 类 - 业务请求封装
|
|
153
|
+
* 默认使用全局共享的 axios 实例,特殊情况可传入自定义实例
|
|
154
|
+
*/
|
|
70
155
|
declare class Request {
|
|
71
156
|
basePath: string;
|
|
72
|
-
|
|
157
|
+
private _instance?;
|
|
158
|
+
constructor(basePath: string, instance?: AxiosInstance);
|
|
159
|
+
/**
|
|
160
|
+
* 获取 axios 实例
|
|
161
|
+
* 延迟获取以确保全局实例已初始化
|
|
162
|
+
*/
|
|
163
|
+
private get instance();
|
|
73
164
|
private requestWrapper;
|
|
74
165
|
/**
|
|
75
166
|
* 分页查询
|
|
76
|
-
* @param
|
|
77
|
-
* @param
|
|
167
|
+
* @param data 查询参数
|
|
168
|
+
* @param options 请求配置
|
|
78
169
|
*/
|
|
79
170
|
page<T = any>(data?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<PageResult<T>>>;
|
|
80
171
|
/**
|
|
81
172
|
* 不分页查询
|
|
82
|
-
* @param
|
|
83
|
-
* @param
|
|
173
|
+
* @param data 查询参数
|
|
174
|
+
* @param options 请求配置
|
|
84
175
|
*/
|
|
85
176
|
noPage<T = any>(data?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<T[]>>;
|
|
86
177
|
/**
|
|
87
178
|
* 详情查询
|
|
88
|
-
* @param
|
|
89
|
-
* @param
|
|
90
|
-
* @param
|
|
179
|
+
* @param id 详情ID
|
|
180
|
+
* @param params 查询参数
|
|
181
|
+
* @param options 请求配置
|
|
91
182
|
*/
|
|
92
183
|
detail<T = any>(id: string, params?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<T>>;
|
|
93
184
|
/**
|
|
94
185
|
* 保存
|
|
95
|
-
* @param
|
|
96
|
-
* @param
|
|
186
|
+
* @param data 保存参数
|
|
187
|
+
* @param options 请求配置
|
|
97
188
|
*/
|
|
98
189
|
save<T = any>(data?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<T>>;
|
|
99
190
|
/**
|
|
100
191
|
* 更新
|
|
101
|
-
* @param
|
|
102
|
-
* @param
|
|
192
|
+
* @param data 更新参数
|
|
193
|
+
* @param options 请求配置
|
|
103
194
|
*/
|
|
104
195
|
update<T extends UpdateResult>(data?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<T>>;
|
|
105
196
|
/**
|
|
106
197
|
* 删除
|
|
107
|
-
* @param
|
|
108
|
-
* @param
|
|
109
|
-
* @param
|
|
198
|
+
* @param id 删除ID
|
|
199
|
+
* @param params 请求参数
|
|
200
|
+
* @param options 请求配置
|
|
110
201
|
* @example ${basePath}/${id}
|
|
111
202
|
*/
|
|
112
203
|
delete<T = any>(id: string, params?: any, options?: RequestOptions): Promise<AxiosResponseRewrite<T>>;
|
|
@@ -122,23 +213,94 @@ declare class Request {
|
|
|
122
213
|
put<T = any>(url: string, data?: any, options?: any): Promise<AxiosResponseRewrite<T>>;
|
|
123
214
|
patch<T = any>(url: string, data?: any, options?: any): Promise<AxiosResponseRewrite<T>>;
|
|
124
215
|
remove<T = any>(url: string, params?: any, options?: any): Promise<AxiosResponseRewrite<T>>;
|
|
125
|
-
getStream(url: string, params?: any, options?: any): Promise<
|
|
126
|
-
postStream(url: string, data?: any, options?: any): Promise<
|
|
216
|
+
getStream(url: string, params?: any, options?: any): Promise<any>;
|
|
217
|
+
postStream(url: string, data?: any, options?: any): Promise<any>;
|
|
127
218
|
}
|
|
219
|
+
declare const request: {
|
|
220
|
+
post: any;
|
|
221
|
+
get: any;
|
|
222
|
+
put: any;
|
|
223
|
+
patch: any;
|
|
224
|
+
remove: any;
|
|
225
|
+
getStream: any;
|
|
226
|
+
postStream: any;
|
|
227
|
+
};
|
|
228
|
+
declare const post: any;
|
|
229
|
+
declare const get: any;
|
|
230
|
+
declare const put: any;
|
|
231
|
+
declare const patch: any;
|
|
232
|
+
declare const remove: any;
|
|
233
|
+
declare const getStream: any;
|
|
234
|
+
declare const postStream: any;
|
|
235
|
+
declare const abortAllRequests: () => void;
|
|
236
|
+
declare const getInstance: () => AxiosInstance;
|
|
237
|
+
declare let instance: AxiosInstance;
|
|
238
|
+
declare const crateAxios: (options: ExtendedOptions) => void;
|
|
128
239
|
|
|
240
|
+
/**
|
|
241
|
+
* NdJson 配置选项
|
|
242
|
+
*/
|
|
243
|
+
interface NdJsonOptions {
|
|
244
|
+
/** 成功状态码 */
|
|
245
|
+
code?: number;
|
|
246
|
+
/** 状态码字段名 */
|
|
247
|
+
codeKey?: string;
|
|
248
|
+
/** 不需要 token 的 URL 列表 */
|
|
249
|
+
filter_url?: string[];
|
|
250
|
+
/** token 过期回调 */
|
|
251
|
+
tokenExpiration?: () => void;
|
|
252
|
+
/** 自定义请求配置 */
|
|
253
|
+
requestOptions?: (config: RequestInit) => Record<string, unknown>;
|
|
254
|
+
/** 自定义响应处理 */
|
|
255
|
+
handleResponse?: <T>(response: T) => T;
|
|
256
|
+
/** 基础 API 地址,默认使用 BASE_API 常量 */
|
|
257
|
+
baseURL?: string;
|
|
258
|
+
}
|
|
129
259
|
declare class NdJson {
|
|
130
|
-
options
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
260
|
+
private options;
|
|
261
|
+
private activeRequests;
|
|
262
|
+
constructor(options?: NdJsonOptions);
|
|
263
|
+
/**
|
|
264
|
+
* 初始化/更新配置
|
|
265
|
+
*/
|
|
266
|
+
create(options: NdJsonOptions): void;
|
|
267
|
+
/**
|
|
268
|
+
* 获取完整 URL
|
|
269
|
+
*/
|
|
270
|
+
private getUrl;
|
|
271
|
+
/**
|
|
272
|
+
* 处理 NDJSON 流的核心逻辑
|
|
273
|
+
*/
|
|
274
|
+
private processStream;
|
|
275
|
+
/**
|
|
276
|
+
* 解析缓冲区中的完整行
|
|
277
|
+
*/
|
|
278
|
+
private parseLines;
|
|
279
|
+
/**
|
|
280
|
+
* 刷新剩余缓冲区
|
|
281
|
+
*/
|
|
282
|
+
private flushBuffer;
|
|
283
|
+
/**
|
|
284
|
+
* 创建请求的 Observable
|
|
285
|
+
*/
|
|
286
|
+
private request;
|
|
287
|
+
get<T = unknown>(url: string, _data?: string, extra?: RequestInit): Observable<T>;
|
|
288
|
+
post<T = unknown>(url: string, data?: BodyInit | Record<string, unknown>, extra?: RequestInit): Observable<T>;
|
|
289
|
+
private handleRequest;
|
|
290
|
+
handleResponse<T>(response: T): T;
|
|
291
|
+
/**
|
|
292
|
+
* 取消所有活跃的请求
|
|
293
|
+
*/
|
|
294
|
+
cancelAll(): void;
|
|
141
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* 创建新的 NdJson 实例
|
|
298
|
+
*/
|
|
299
|
+
declare const createNdJson: (options?: NdJsonOptions) => NdJson;
|
|
300
|
+
/**
|
|
301
|
+
* 初始化默认实例
|
|
302
|
+
*/
|
|
303
|
+
declare const createNdJsonService: (options: NdJsonOptions) => void;
|
|
142
304
|
declare const ndJson: NdJson;
|
|
143
305
|
|
|
144
306
|
interface WebSocketMessage {
|
|
@@ -208,4 +370,4 @@ declare const installStores: (_s?: {}) => void;
|
|
|
208
370
|
declare let locales: any;
|
|
209
371
|
declare const installLocales: (l: any) => void;
|
|
210
372
|
|
|
211
|
-
export { NdJson, Request, WebSocketClient, abortAllRequests, crateAxios, get, getStream, installLocales, installRouter, installStores, instance, locales, ndJson, patch, post, postStream, put, remove, request, router, stores, wsClient };
|
|
373
|
+
export { AxiosService, type ExtendedOptions, NdJson, type NdJsonOptions, Request, WebSocketClient, abortAllRequests, crateAxios, createAxiosService, createNdJson, createNdJsonService, get, getInstance, getStream, installLocales, installRouter, installStores, instance, locales, ndJson, patch, post, postStream, put, remove, request, router, stores, wsClient };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import{TOKEN_KEY as
|
|
2
|
-
`);for(let
|
|
3
|
-
`);for(let u=0;u<f.length-1;++u){let b=f[u].trim();if(b.length>0)try{i.next(JSON.parse(b.startsWith("data:")?b.slice(5):b))}catch(O){i.error(O);return}}p=f[f.length-1],w()}).catch(d=>{d.name!=="AbortError"&&i.error(d)})};a.isRead=!0,w()}).catch(m=>{i.error(m)}),()=>{a.cancel()}})}handleRequest(e){let t={headers:{"Content-Type":"application/x-ndjson"}},n=te();if(!n&&this.options.filter_url?.some(r=>r.includes(e)))return this.options.tokenExpiration?.(),t;if(t.headers[N]||(t.headers[N]=n),this.options.requestOptions&&K(this.options.requestOptions)){let r=this.options.requestOptions(t);if(r&&L(r))for(let a in r)t[a]=r[a]}return t}handleResponse(e){return this.options.handleResponse&&K(this.options.handleResponse)?this.options.handleResponse(e):e}cancel(){this.isRead&&(this.isRead=!1),this.controller&&this.controller.abort()}},Ee=new _;import{webSocket as ne}from"rxjs/webSocket";import{Observable as re,Subject as ie,timer as Q,EMPTY as oe}from"rxjs";import{retry as ae,catchError as ce}from"rxjs/operators";import{notification as pe}from"ant-design-vue";var c=window.__MICRO_APP_ENVIRONMENT__,W=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=ne({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(ce(e=>(console.error("WebSocket error:",e),oe)),ae({delay:(e,t)=>{if(this.reconnectAttempts=t,t>this.maxReconnectAttempts)throw new Error("Max reconnection attempts reached");return Q(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=Q(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):pe.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,n={}){if(console.log("getWebSocket",this.wsClient,e),c&&this.wsClient)return this.wsClient.getWebSocket(e,t,n);let r=new ie;this.subscriptions.set(e,r);let a={id:e,topic:t,parameter:n,type:"sub"};return this.send(a),new re(y=>{let i=r.subscribe(y);return()=>{i.unsubscribe(),this.send({id:e,type:"unsub"}),this.subscriptions.delete(e)}})}},Me=new W;var ue,Pe=s=>{ue=s};var le={},je=(s={})=>{le=s};var he,Ne=s=>{he=s};export{_ as NdJson,v as Request,W as WebSocketClient,ge as abortAllRequests,we as crateAxios,T as get,X as getStream,Ne as installLocales,Pe as installRouter,je as installStores,l as instance,he as locales,Ee as ndJson,j as patch,x as post,Z as postStream,$ as put,I as remove,ee as request,ue as router,le as stores,Me 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||"",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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetlinks-web/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"main": "dist/index.mjs",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"axios": "^1.7.4",
|
|
30
30
|
"rxjs": "^7.8.1",
|
|
31
31
|
"@jetlinks-web/constants": "^1.0.9",
|
|
32
|
-
"@jetlinks-web/
|
|
33
|
-
"@jetlinks-web/
|
|
32
|
+
"@jetlinks-web/utils": "^1.2.12",
|
|
33
|
+
"@jetlinks-web/types": "^1.0.2"
|
|
34
34
|
},
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"registry": "https://registry.npmjs.org/",
|