upload-sdk 1.0.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.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * 动态创建 web worker
3
+ */
4
+ declare class DynamicWorker {
5
+ core: string;
6
+ blob: Blob;
7
+ url: string;
8
+ worker: any;
9
+ constructor(core: any);
10
+ send(data: Record<string, any>): void;
11
+ onMessage(callback: (data: Record<string, any>) => void): void;
12
+ close(): void;
13
+ }
14
+
15
+ declare class FileHashWorker extends DynamicWorker {
16
+ constructor();
17
+ }
18
+
19
+ declare class FileChunkHashWorker extends DynamicWorker {
20
+ constructor();
21
+ }
22
+
23
+ declare const fileChunkHashWorkerCode = "\n importScripts('https://cdn.jsdelivr.net/npm/spark-md5@3.0.2/spark-md5.min.js');\n self.onmessage = async function(e) {\n const { file, chunkSize, index, startChunksIndex, endChunksIndex } = e.data\n const promises = []\n for (let i = startChunksIndex; i < endChunksIndex; i++) {\n const promise = new Promise((resolve, reject) => {\n const spark = new self.SparkMD5.ArrayBuffer()\n const start = i * chunkSize\n const end = Math.min(start + chunkSize, file.size)\n const blob = file.slice(start, end)\n\n const reader = new FileReader()\n reader.onload = (event) => {\n spark.append(event.target.result)\n const chunk = {\n fileHash: spark.end(),\n chunkIndex: i,\n chunkSize: chunkSize,\n blob: blob,\n result: event.target.result\n }\n self.postMessage({\n type: 'COMPLETE_CHUNK',\n data: {\n index: index,\n chunk: chunk\n }\n })\n resolve(chunk)\n }\n\n reader.onerror = (event) => {\n reject(event.target.error)\n }\n reader.readAsArrayBuffer(blob)\n })\n promises.push(promise)\n }\n\n const allChunks = await Promise.all(promises)\n self.postMessage({\n type: 'COMPLETE_CHUNKS',\n data: {\n index: index,\n chunks: allChunks\n }\n })\n }\n";
24
+ declare const fileHashWorkerCode = "\n importScripts('https://cdn.jsdelivr.net/npm/spark-md5@3.0.2/spark-md5.min.js');\n function calculateFileMd5(file) {\n return new Promise((resolve) => {\n const spark = new SparkMD5.ArrayBuffer();\n const reader = new FileReader();\n const chunkSize = 500 * 1024;\n let currentChunk = 0;\n const totalChunks = Math.ceil(file.size / chunkSize);\n // \u5206\u7247\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\n function loadNextChunk() {\n const start = currentChunk * chunkSize;\n const end = Math.min(start + chunkSize, file.size);\n reader.readAsArrayBuffer(file.slice(start, end));\n }\n\n reader.onload = (e) => {\n spark.append(e.target.result); // \u8FFD\u52A0\u5206\u7247\u5185\u5BB9\u5230MD5\u8BA1\u7B97\n currentChunk++;\n if (currentChunk < totalChunks) {\n loadNextChunk(); // \u7EE7\u7EED\u8BFB\u53D6\u4E0B\u4E00\u4E2A\u5206\u7247\n } else {\n const md5 = spark.end(); // \u8BA1\u7B97\u5B8C\u6210\uFF0C\u5F97\u5230\u6700\u7EC8MD5\n resolve(md5);\n }\n };\n loadNextChunk();\n });\n }\n\n self.onmessage = async function(e) {\n const { file, chunkSize } = e.data\n const fileHash = await calculateFileMd5(file)\n console.log('fileHash', fileHash)\n self.postMessage({\n data: {\n fileHash: fileHash\n }\n })\n }\n";
25
+
26
+ interface RequestConfig {
27
+ url: string;
28
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'PATCH';
29
+ baseURL?: string;
30
+ headers?: Record<string, string>;
31
+ params?: Record<string, any>;
32
+ data?: any;
33
+ timeout?: number;
34
+ responseType?: 'json' | 'text' | 'blob' | 'arraybuffer' | 'stream';
35
+ withCredentials?: boolean;
36
+ adapter?: 'fetch' | 'axios' | 'uni';
37
+ validateStatus?: (status: number) => boolean;
38
+ onUploadProgress?: (progressEvent: any) => void;
39
+ onDownloadProgress?: (progressEvent: any) => void;
40
+ cancelToken?: any;
41
+ }
42
+ interface Response<T = any> {
43
+ data: T;
44
+ status: number;
45
+ statusText: string;
46
+ headers: Record<string, string>;
47
+ config: RequestConfig;
48
+ request?: any;
49
+ }
50
+ interface HttpClientInstance {
51
+ request<T = any>(config: RequestConfig): Promise<Response<T>>;
52
+ get<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
53
+ post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
54
+ put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
55
+ delete<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
56
+ patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
57
+ }
58
+
59
+ declare class HttpClient implements HttpClientInstance {
60
+ private adapter;
61
+ private defaultConfig;
62
+ private interceptors;
63
+ constructor(config?: Partial<RequestConfig>);
64
+ /**
65
+ * 核心请求方法
66
+ */
67
+ request<T = any>(config: RequestConfig): Promise<Response<T>>;
68
+ /**
69
+ * 快捷方法
70
+ */
71
+ get<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
72
+ post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
73
+ put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
74
+ delete<T = any>(url: string, config?: RequestConfig): Promise<Response<T>>;
75
+ patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>;
76
+ /**
77
+ * 添加请求拦截器
78
+ */
79
+ addRequestInterceptor(interceptor: (config: RequestConfig) => RequestConfig | Promise<RequestConfig>): void;
80
+ /**
81
+ * 添加响应拦截器
82
+ */
83
+ addResponseInterceptor(interceptor: (response: Response) => Response | Promise<Response>): void;
84
+ /**
85
+ * 切换适配器
86
+ */
87
+ setAdapter(adapterName: 'fetch' | 'axios' | 'uni'): void;
88
+ /**
89
+ * 获取当前适配器名称
90
+ */
91
+ getAdapterName(): string;
92
+ }
93
+
94
+ declare function createHttpClient(config?: Partial<RequestConfig>): HttpClient;
95
+
96
+ declare class TaskQueue {
97
+ tasks: any[];
98
+ }
99
+
100
+ declare const isH5: false | {
101
+ <K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K];
102
+ <K extends keyof HTMLElementDeprecatedTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementDeprecatedTagNameMap[K];
103
+ (tagName: string, options?: ElementCreationOptions): HTMLElement;
104
+ };
105
+ declare const isWeb: boolean;
106
+ declare const isUniApp: boolean;
107
+
108
+ export { DynamicWorker, FileChunkHashWorker, FileHashWorker, TaskQueue, createHttpClient, fileChunkHashWorkerCode as defineFileChunkHashWorkerCode, fileHashWorkerCode as defineFileHashWorkerCode, isH5, isUniApp, isWeb };
@@ -0,0 +1,572 @@
1
+ /**
2
+ * 动态创建 web worker
3
+ */
4
+ class DynamicWorker {
5
+ constructor(core) {
6
+ this.core = core.toString();
7
+ this.blob = new Blob([`(()=>{${this.core}})()`], { type: "text/javascript" });
8
+ this.url = URL.createObjectURL(this.blob);
9
+ this.worker = new Worker(this.url);
10
+ }
11
+ // 发送到 web worker
12
+ send(data) {
13
+ if (!this.worker) {
14
+ console.error("worker is not ready");
15
+ return;
16
+ }
17
+ this.worker.postMessage(data);
18
+ }
19
+ // 接收到 web worker 的消息
20
+ onMessage(callback) {
21
+ if (!this.worker) {
22
+ console.error("worker is not ready");
23
+ return;
24
+ }
25
+ this.worker.addEventListener("message", (e) => {
26
+ callback(e.data);
27
+ });
28
+ }
29
+ // 关闭 web worker
30
+ close() {
31
+ URL.revokeObjectURL(this.url);
32
+ if (this.worker) {
33
+ this.worker.terminate();
34
+ this.worker = null;
35
+ }
36
+ }
37
+ }
38
+
39
+ const fileChunkHashWorkerCode = `
40
+ importScripts('https://cdn.jsdelivr.net/npm/spark-md5@3.0.2/spark-md5.min.js');
41
+ self.onmessage = async function(e) {
42
+ const { file, chunkSize, index, startChunksIndex, endChunksIndex } = e.data
43
+ const promises = []
44
+ for (let i = startChunksIndex; i < endChunksIndex; i++) {
45
+ const promise = new Promise((resolve, reject) => {
46
+ const spark = new self.SparkMD5.ArrayBuffer()
47
+ const start = i * chunkSize
48
+ const end = Math.min(start + chunkSize, file.size)
49
+ const blob = file.slice(start, end)
50
+
51
+ const reader = new FileReader()
52
+ reader.onload = (event) => {
53
+ spark.append(event.target.result)
54
+ const chunk = {
55
+ fileHash: spark.end(),
56
+ chunkIndex: i,
57
+ chunkSize: chunkSize,
58
+ blob: blob,
59
+ result: event.target.result
60
+ }
61
+ self.postMessage({
62
+ type: 'COMPLETE_CHUNK',
63
+ data: {
64
+ index: index,
65
+ chunk: chunk
66
+ }
67
+ })
68
+ resolve(chunk)
69
+ }
70
+
71
+ reader.onerror = (event) => {
72
+ reject(event.target.error)
73
+ }
74
+ reader.readAsArrayBuffer(blob)
75
+ })
76
+ promises.push(promise)
77
+ }
78
+
79
+ const allChunks = await Promise.all(promises)
80
+ self.postMessage({
81
+ type: 'COMPLETE_CHUNKS',
82
+ data: {
83
+ index: index,
84
+ chunks: allChunks
85
+ }
86
+ })
87
+ }
88
+ `;
89
+ const fileHashWorkerCode = `
90
+ importScripts('https://cdn.jsdelivr.net/npm/spark-md5@3.0.2/spark-md5.min.js');
91
+ function calculateFileMd5(file) {
92
+ return new Promise((resolve) => {
93
+ const spark = new SparkMD5.ArrayBuffer();
94
+ const reader = new FileReader();
95
+ const chunkSize = 500 * 1024;
96
+ let currentChunk = 0;
97
+ const totalChunks = Math.ceil(file.size / chunkSize);
98
+ // 分片读取文件内容
99
+ function loadNextChunk() {
100
+ const start = currentChunk * chunkSize;
101
+ const end = Math.min(start + chunkSize, file.size);
102
+ reader.readAsArrayBuffer(file.slice(start, end));
103
+ }
104
+
105
+ reader.onload = (e) => {
106
+ spark.append(e.target.result); // 追加分片内容到MD5计算
107
+ currentChunk++;
108
+ if (currentChunk < totalChunks) {
109
+ loadNextChunk(); // 继续读取下一个分片
110
+ } else {
111
+ const md5 = spark.end(); // 计算完成,得到最终MD5
112
+ resolve(md5);
113
+ }
114
+ };
115
+ loadNextChunk();
116
+ });
117
+ }
118
+
119
+ self.onmessage = async function(e) {
120
+ const { file, chunkSize } = e.data
121
+ const fileHash = await calculateFileMd5(file)
122
+ console.log('fileHash', fileHash)
123
+ self.postMessage({
124
+ data: {
125
+ fileHash: fileHash
126
+ }
127
+ })
128
+ }
129
+ `;
130
+
131
+ class FileHashWorker extends DynamicWorker {
132
+ constructor() {
133
+ super(fileHashWorkerCode);
134
+ }
135
+ }
136
+
137
+ class FileChunkHashWorker extends DynamicWorker {
138
+ constructor() {
139
+ super(fileChunkHashWorkerCode);
140
+ }
141
+ }
142
+
143
+ class FetchAdapter {
144
+ constructor() {
145
+ this.name = 'fetch';
146
+ }
147
+ isAvailable() {
148
+ return typeof fetch !== 'undefined' && typeof window !== 'undefined';
149
+ }
150
+ async request(config) {
151
+ const { url, method = 'GET', headers = {}, data, params, timeout = 30000, responseType = 'json', withCredentials = false, } = config;
152
+ // 处理 URL 参数
153
+ let fullUrl = this.buildFullUrl(url, config.baseURL);
154
+ if (params) {
155
+ fullUrl = this.appendParams(fullUrl, params);
156
+ }
157
+ // 创建请求配置
158
+ const fetchConfig = {
159
+ method: method.toUpperCase(),
160
+ headers: this.normalizeHeaders(headers),
161
+ credentials: withCredentials ? 'include' : 'same-origin',
162
+ };
163
+ // 处理请求体
164
+ if (data) {
165
+ fetchConfig.body = this.processRequestBody(data, headers);
166
+ }
167
+ // 超时处理
168
+ const controller = new AbortController();
169
+ fetchConfig.signal = controller.signal;
170
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
171
+ try {
172
+ const response = await fetch(fullUrl, fetchConfig);
173
+ clearTimeout(timeoutId);
174
+ // 处理响应
175
+ const responseData = await this.processResponse(response, responseType);
176
+ const responseHeaders = this.extractHeaders(response.headers);
177
+ return {
178
+ data: responseData,
179
+ status: response.status,
180
+ statusText: response.statusText,
181
+ headers: responseHeaders,
182
+ config,
183
+ request: null,
184
+ };
185
+ }
186
+ catch (error) {
187
+ clearTimeout(timeoutId);
188
+ if (error.name === 'AbortError') {
189
+ throw new Error(`Request timeout after ${timeout}ms`);
190
+ }
191
+ throw error;
192
+ }
193
+ }
194
+ buildFullUrl(url, baseURL) {
195
+ if (baseURL) {
196
+ return baseURL.replace(/\/+$/, '') + '/' + url.replace(/^\/+/, '');
197
+ }
198
+ return url;
199
+ }
200
+ appendParams(url, params) {
201
+ const urlObj = new URL(url, window.location.origin);
202
+ Object.keys(params).forEach(key => {
203
+ if (params[key] !== undefined && params[key] !== null) {
204
+ urlObj.searchParams.append(key, String(params[key]));
205
+ }
206
+ });
207
+ return urlObj.toString();
208
+ }
209
+ normalizeHeaders(headers) {
210
+ const normalized = {};
211
+ Object.keys(headers).forEach(key => {
212
+ const value = headers[key];
213
+ if (value !== undefined && value !== null) {
214
+ normalized[key] = String(value);
215
+ }
216
+ });
217
+ // 如果没有 Content-Type 且不是 FormData,默认添加
218
+ if (!normalized['Content-Type'] && !normalized['content-type']) {
219
+ normalized['Content-Type'] = 'application/json';
220
+ }
221
+ return normalized;
222
+ }
223
+ processRequestBody(data, headers) {
224
+ const contentType = headers['Content-Type'] || headers['content-type'];
225
+ if (data instanceof FormData || data instanceof URLSearchParams) {
226
+ return data;
227
+ }
228
+ if (contentType?.includes('application/json')) {
229
+ return JSON.stringify(data);
230
+ }
231
+ if (contentType?.includes('application/x-www-form-urlencoded')) {
232
+ return new URLSearchParams(data).toString();
233
+ }
234
+ return String(data);
235
+ }
236
+ async processResponse(response, responseType) {
237
+ switch (responseType) {
238
+ case 'json':
239
+ return response.json();
240
+ case 'text':
241
+ return response.text();
242
+ case 'blob':
243
+ return response.blob();
244
+ case 'arraybuffer':
245
+ return response.arrayBuffer();
246
+ default:
247
+ return response.text();
248
+ }
249
+ }
250
+ extractHeaders(headers) {
251
+ const result = {};
252
+ headers.forEach((value, key) => {
253
+ result[key] = value;
254
+ });
255
+ return result;
256
+ }
257
+ }
258
+
259
+ class AxiosAdapter {
260
+ constructor() {
261
+ this.name = 'axios';
262
+ }
263
+ isAvailable() {
264
+ try {
265
+ return typeof require !== 'undefined' && !!require('axios') ||
266
+ (typeof window !== 'undefined' && !!window.axios);
267
+ }
268
+ catch {
269
+ return false;
270
+ }
271
+ }
272
+ async request(config) {
273
+ const axios = await this.getAxios();
274
+ try {
275
+ const response = await axios({
276
+ url: config.url,
277
+ method: config.method,
278
+ baseURL: config.baseURL,
279
+ headers: config.headers,
280
+ params: config.params,
281
+ data: config.data,
282
+ timeout: config.timeout,
283
+ responseType: config.responseType,
284
+ withCredentials: config.withCredentials,
285
+ onUploadProgress: config.onUploadProgress,
286
+ onDownloadProgress: config.onDownloadProgress,
287
+ cancelToken: config.cancelToken,
288
+ validateStatus: config.validateStatus,
289
+ });
290
+ return {
291
+ data: response.data,
292
+ status: response.status,
293
+ statusText: response.statusText,
294
+ headers: response.headers,
295
+ config: response.config,
296
+ request: response.request,
297
+ };
298
+ }
299
+ catch (error) {
300
+ if (error.response) {
301
+ throw {
302
+ data: error.response.data,
303
+ status: error.response.status,
304
+ statusText: error.response.statusText,
305
+ headers: error.response.headers,
306
+ config: error.response.config,
307
+ };
308
+ }
309
+ throw error;
310
+ }
311
+ }
312
+ async getAxios() {
313
+ // 动态导入 axios
314
+ if (typeof window !== 'undefined' && window.axios) {
315
+ return window.axios;
316
+ }
317
+ if (typeof require !== 'undefined') {
318
+ return require('axios');
319
+ }
320
+ throw new Error('Axios is not available');
321
+ }
322
+ }
323
+
324
+ class UniAdapter {
325
+ constructor() {
326
+ this.name = 'uni';
327
+ }
328
+ isAvailable() {
329
+ return typeof uni !== 'undefined' && typeof uni.request === 'function';
330
+ }
331
+ request(config) {
332
+ return new Promise((resolve, reject) => {
333
+ if (!uni || !uni.request) {
334
+ reject(new Error('uni.request is not available'));
335
+ return;
336
+ }
337
+ const { url, method = 'GET', headers = {}, data, timeout = 30000, responseType = 'json', withCredentials = false, } = config;
338
+ const uniConfig = {
339
+ url: this.buildFullUrl(url, config.baseURL),
340
+ method: method.toUpperCase(),
341
+ header: headers,
342
+ data,
343
+ timeout,
344
+ dataType: responseType === 'json' ? 'json' : 'text',
345
+ responseType: responseType === 'arraybuffer' ? 'arraybuffer' : 'text',
346
+ sslVerify: true,
347
+ withCredentials,
348
+ firstIpv4: false,
349
+ };
350
+ // 处理参数
351
+ if (config.params) {
352
+ uniConfig.url = this.appendParams(uniConfig.url, config.params);
353
+ }
354
+ uni.request({
355
+ ...uniConfig,
356
+ success: (res) => {
357
+ resolve({
358
+ data: res.data,
359
+ status: res.statusCode,
360
+ statusText: this.getStatusText(res.statusCode),
361
+ headers: res.header,
362
+ config,
363
+ request: null,
364
+ });
365
+ },
366
+ fail: (err) => {
367
+ reject(new Error(err.errMsg || 'uni.request failed'));
368
+ },
369
+ });
370
+ });
371
+ }
372
+ buildFullUrl(url, baseURL) {
373
+ if (baseURL) {
374
+ return baseURL.replace(/\/+$/, '') + '/' + url.replace(/^\/+/, '');
375
+ }
376
+ return url;
377
+ }
378
+ appendParams(url, params) {
379
+ const paramStr = Object.keys(params)
380
+ .filter(key => params[key] !== undefined && params[key] !== null)
381
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
382
+ .join('&');
383
+ return url + (url.includes('?') ? '&' : '?') + paramStr;
384
+ }
385
+ getStatusText(status) {
386
+ const statusMap = {
387
+ 200: 'OK',
388
+ 201: 'Created',
389
+ 400: 'Bad Request',
390
+ 401: 'Unauthorized',
391
+ 403: 'Forbidden',
392
+ 404: 'Not Found',
393
+ 500: 'Internal Server Error',
394
+ };
395
+ return statusMap[status] || 'Unknown';
396
+ }
397
+ }
398
+
399
+ class AdapterFactory {
400
+ /**
401
+ * 自动选择可用的适配器
402
+ */
403
+ static getAvailableAdapter() {
404
+ for (const adapter of this.adapters) {
405
+ if (adapter.isAvailable()) {
406
+ console.log(`Using ${adapter.name} adapter`);
407
+ return adapter;
408
+ }
409
+ }
410
+ throw new Error('No available adapter found');
411
+ }
412
+ /**
413
+ * 获取指定适配器
414
+ */
415
+ static getAdapter(name) {
416
+ const adapter = this.adapters.find(a => a.name === name);
417
+ if (!adapter) {
418
+ throw new Error(`Adapter ${name} not found`);
419
+ }
420
+ if (!adapter.isAvailable()) {
421
+ throw new Error(`Adapter ${name} is not available in current environment`);
422
+ }
423
+ return adapter;
424
+ }
425
+ /**
426
+ * 注册自定义适配器
427
+ */
428
+ static registerAdapter(adapter) {
429
+ this.adapters.unshift(adapter); // 优先使用自定义适配器
430
+ }
431
+ }
432
+ AdapterFactory.adapters = [
433
+ new FetchAdapter(),
434
+ new AxiosAdapter(),
435
+ new UniAdapter(),
436
+ ];
437
+
438
+ class HttpClient {
439
+ constructor(config = {}) {
440
+ this.defaultConfig = config;
441
+ this.interceptors = {
442
+ request: [],
443
+ response: [],
444
+ };
445
+ // 自动选择适配器或使用指定的适配器
446
+ if (config.adapter) {
447
+ this.adapter = AdapterFactory.getAdapter(config.adapter);
448
+ }
449
+ else {
450
+ this.adapter = AdapterFactory.getAvailableAdapter();
451
+ }
452
+ }
453
+ /**
454
+ * 核心请求方法
455
+ */
456
+ async request(config) {
457
+ // 合并配置
458
+ const mergedConfig = {
459
+ ...this.defaultConfig,
460
+ ...config,
461
+ headers: {
462
+ ...this.defaultConfig.headers,
463
+ ...config.headers,
464
+ },
465
+ };
466
+ // 执行请求拦截器
467
+ let requestConfig = mergedConfig;
468
+ for (const interceptor of this.interceptors.request) {
469
+ requestConfig = await interceptor(requestConfig);
470
+ }
471
+ // 发送请求
472
+ const response = await this.adapter.request(requestConfig);
473
+ // 执行响应拦截器
474
+ let processedResponse = response;
475
+ for (const interceptor of this.interceptors.response) {
476
+ processedResponse = await interceptor(processedResponse);
477
+ }
478
+ return processedResponse;
479
+ }
480
+ /**
481
+ * 快捷方法
482
+ */
483
+ get(url, config) {
484
+ return this.request({ ...config, url, method: 'GET' });
485
+ }
486
+ post(url, data, config) {
487
+ return this.request({ ...config, url, method: 'POST', data });
488
+ }
489
+ put(url, data, config) {
490
+ return this.request({ ...config, url, method: 'PUT', data });
491
+ }
492
+ delete(url, config) {
493
+ return this.request({ ...config, url, method: 'DELETE' });
494
+ }
495
+ patch(url, data, config) {
496
+ return this.request({ ...config, url, method: 'PATCH', data });
497
+ }
498
+ /**
499
+ * 添加请求拦截器
500
+ */
501
+ addRequestInterceptor(interceptor) {
502
+ this.interceptors.request.push(interceptor);
503
+ }
504
+ /**
505
+ * 添加响应拦截器
506
+ */
507
+ addResponseInterceptor(interceptor) {
508
+ this.interceptors.response.push(interceptor);
509
+ }
510
+ /**
511
+ * 切换适配器
512
+ */
513
+ setAdapter(adapterName) {
514
+ this.adapter = AdapterFactory.getAdapter(adapterName);
515
+ }
516
+ /**
517
+ * 获取当前适配器名称
518
+ */
519
+ getAdapterName() {
520
+ return this.adapter.name;
521
+ }
522
+ }
523
+
524
+ function createHttpClient(config = {}) {
525
+ const client = new HttpClient(config);
526
+ // 默认请求拦截器 - 添加认证信息
527
+ client.addRequestInterceptor(async (config) => {
528
+ // 从存储中获取 token
529
+ // const token = localStorage?.getItem('token') || uni?.getStorageSync?.('token');
530
+ // if (token && !config.headers?.['Authorization']) {
531
+ // config.headers = {
532
+ // ...config.headers,
533
+ // 'Authorization': `Bearer ${token}`,
534
+ // };
535
+ // }
536
+ return config;
537
+ });
538
+ // 默认响应拦截器 - 处理业务错误
539
+ client.addResponseInterceptor(async (response) => {
540
+ // 如果响应状态码不在 200-299 范围内
541
+ if (response.status < 200 || response.status >= 300) {
542
+ throw new Error(`Request failed with status ${response.status}`);
543
+ }
544
+ // 处理业务逻辑错误码(根据后端接口规范调整)
545
+ if (response.data && response.data.code !== 0) {
546
+ throw new Error(response.data.message || 'Business logic error');
547
+ }
548
+ return response;
549
+ });
550
+ return client;
551
+ }
552
+
553
+ class TaskQueue {
554
+ constructor() {
555
+ this.tasks = [];
556
+ }
557
+ }
558
+
559
+ const useEnv = () => {
560
+ const isH5 = typeof window !== 'undefined' && window.document && window.document.createElement;
561
+ const isWeb = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development';
562
+ const isUniApp = typeof uni !== 'undefined';
563
+ return {
564
+ isH5,
565
+ isWeb,
566
+ isUniApp
567
+ };
568
+ };
569
+ const { isH5, isWeb, isUniApp } = useEnv();
570
+
571
+ export { DynamicWorker, FileChunkHashWorker, FileHashWorker, TaskQueue, createHttpClient, fileChunkHashWorkerCode as defineFileChunkHashWorkerCode, fileHashWorkerCode as defineFileHashWorkerCode, isH5, isUniApp, isWeb };
572
+ //# sourceMappingURL=index.esm.js.map