etherreq 1.1.14 → 1.1.16

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/README.md CHANGED
@@ -59,22 +59,22 @@ console.log(login);
59
59
 
60
60
 
61
61
 
62
- ### 请求方法
62
+ ## Vue 集成
63
63
 
64
- etherreq.login(url,data)
65
-
66
- etherreq.get(url,data)
67
-
68
- etherreq.delete(url,data)
69
-
70
- etherreq.head(url,data)
71
-
72
- etherreq.options(url,data)
64
+ ### 安装插件(Vue2/Vue3 通用)
65
+ ```javascript
66
+ import { createApp } from 'vue'; // Vue3
67
+ // import Vue from 'vue'; // Vue2
68
+ import { etherreq } from 'etherreq';
73
69
 
74
- etherreq.post(url,data)
70
+ const app = createApp(App); // Vue3
71
+ // const app = new Vue({ ... }); // Vue2
75
72
 
76
- etherreq.put(url,data
73
+ // 安装插件(可选配置 baseURL
74
+ app.use(etherreq, { baseURL: 'https://api.example.com' });
77
75
 
78
- etherreq.patch(url,data)
76
+ // 挂载应用
77
+ app.mount('#app');
78
+ ```
79
79
 
80
80
  在login方法执行后后端需要返回token,之后在执行其他方法时不需要配置token,token会自动携带
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "etherreq",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "description": "A lightweight custom HTTP request library.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/types/etherreq.d.ts",
package/src/cache.js CHANGED
@@ -2,14 +2,16 @@
2
2
  const cacheStore = new Map();
3
3
 
4
4
  /**
5
- * 获取缓存 key
5
+ * 获取缓存 key(包含幂等令牌)
6
6
  * @param {string} url 请求地址
7
7
  * @param {Object} options 请求参数
8
8
  * @returns {string}
9
9
  */
10
10
  function getCacheKey(url, options) {
11
11
  const params = new URLSearchParams(options.params || {});
12
- return `${options.method}:${url}?${params.toString()}`;
12
+ // 新增:若存在幂等令牌则加入缓存键
13
+ const idempotencyKey = options.idempotencyKey ? `:${options.idempotencyKey}` : '';
14
+ return `${options.method}:${url}?${params.toString()}${idempotencyKey}`;
13
15
  }
14
16
 
15
17
  export const requestCache = {
package/src/etherreq.js CHANGED
@@ -18,8 +18,6 @@ const dispatchRequest = async (config) => {
18
18
  const nextConfig = await interceptor.fulfilled(config);
19
19
  // ✅ 拦截器可以返回一个 response 对象,表示中断请求
20
20
  if (nextConfig && nextConfig.isFromCache) {
21
- console.log(nextConfig.data);
22
-
23
21
  return nextConfig.data; // ✅ 直接返回缓存结果,不再往下执行
24
22
  }
25
23
  config = nextConfig;
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.js
2
- import { request, baseURL as _baseURL, setBaseURL } from './request';
2
+ import { request, baseURL as _baseURL, setBaseURL } from './request.js';
3
3
  // 示例封装方法
4
4
  const createMethod = (method) => (url, data, callback) => {
5
5
  let options;
@@ -54,5 +54,26 @@ export const etherreq = Object.assign(
54
54
  },
55
55
  }
56
56
  );
57
+ therreq.install = (app, options = {}) => {
58
+ // 合并基础 URL 配置
59
+ if (options.baseURL) {
60
+ setBaseURL(options.baseURL);
61
+ }
62
+
63
+ // 兼容 Vue2 和 Vue3 的挂载方式
64
+ if (typeof app === 'function' && app.prototype) { // Vue2
65
+ app.prototype.$etherreq = etherreq;
66
+ } else if (app.config) { // Vue3
67
+ app.config.globalProperties.$etherreq = etherreq;
68
+ }
69
+ };
57
70
 
71
+ // 导出组合式函数(仅 Vue3 可用)
72
+ export const useEtherReq = () => {
73
+ const instance = getCurrentInstance();
74
+ if (!instance) {
75
+ throw new Error('useEtherReq 必须在 Vue 组件的 setup 函数中调用');
76
+ }
77
+ return instance.appContext.config.globalProperties.$etherreq;
78
+ };
58
79
  export { setBaseURL, _baseURL as baseURL };
package/src/request.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/request.js
2
- import { create } from './etherreq';
3
- import { requestCache, getCacheKey } from './cache';
2
+ import { create } from './etherreq.js';
3
+ import { requestCache, getCacheKey } from './cache.js';
4
4
 
5
5
  // 创建一个带有默认配置的请求实例
6
6
  const instance = create({
@@ -17,12 +17,13 @@ instance.interceptors.request.use((config) => {
17
17
  'Content-Type': 'application/json',
18
18
  };
19
19
 
20
- if (config.method === 'GET' && !config.disableCache) {
20
+ // 新增:若存在幂等令牌,强制启用缓存校验(即使非GET请求)
21
+ const useCache = (config.method === 'GET' && !config.disableCache) || !!config.idempotencyKey;
22
+ if (useCache) {
21
23
  const cacheKey = getCacheKey(config.url, config);
22
24
  const cached = requestCache.get(cacheKey);
23
25
 
24
26
  if (cached) {
25
- console.log('命中缓存:', cacheKey);
26
27
  return Promise.resolve({
27
28
  data: cached,
28
29
  status: 200,
@@ -43,15 +44,15 @@ instance.interceptors.request.use((config) => {
43
44
  instance.interceptors.response.use(
44
45
  (response) => {
45
46
  if (response.isFromCache) {
46
- console.log('从缓存返回');
47
47
  return response.data;
48
48
  }
49
49
 
50
50
  const config = response.config;
51
- if (config && config.method === 'GET' && !config.disableCache) {
51
+ // 新增:若存在幂等令牌或GET请求未禁用缓存,则缓存结果
52
+ const shouldCache = !!config.idempotencyKey || (config.method === 'GET' && !config.disableCache);
53
+ if (shouldCache) {
52
54
  const cacheKey = getCacheKey(config.url, config);
53
55
  requestCache.set(cacheKey, response.data);
54
- console.log('写入缓存:', cacheKey);
55
56
  }
56
57
 
57
58
  return response.data;
@@ -61,7 +62,7 @@ instance.interceptors.response.use(
61
62
  return Promise.reject(error);
62
63
  }
63
64
  );
64
- let _baseURL = 'https://api.example.com'; // 内部变量用于保存 base URL
65
+ let _baseURL = 'https://api..com'; // 内部变量用于保存 base URL
65
66
 
66
67
  /**
67
68
  * 封装 request 函数,支持 baseURl 拼接等逻辑
@@ -4,6 +4,7 @@ interface EtherRequestOptions {
4
4
  body?: any;
5
5
  params?: Record<string, any>;
6
6
  baseURL?: string;
7
+ idempotencyKey?: string; // 新增:幂等请求令牌
7
8
  }
8
9
 
9
10
  interface EtherRequestResponse<T = any> {
@@ -20,15 +21,23 @@ type EtherRequestMethod = <T = any>(
20
21
  ) => Promise<T>;
21
22
 
22
23
  // 主函数类型(支持调用 + 属性方法)
24
+ // 导入 Vue 类型(需安装 @vue/runtime-core)
25
+ import type { App, ComponentInternalInstance } from 'vue';
26
+
27
+ // 扩展 EtherreqStatic 类型,添加 install 方法
23
28
  interface EtherreqStatic extends EtherRequestMethod {
24
29
  get: EtherRequestMethod;
25
30
  post: EtherRequestMethod;
26
31
  put: EtherRequestMethod;
27
32
  delete: EtherRequestMethod;
28
33
  del: EtherRequestMethod;
29
- login: EtherRequestMethod;
34
+ login: EtherRequestMethod;
35
+ install: (app: App | any, options?: { baseURL?: string }) => void; // 兼容 Vue2/Vue3
30
36
  }
31
37
 
38
+ // 声明组合式函数类型
39
+ export function useEtherReq(): EtherreqStatic;
40
+
32
41
  // 导出对象
33
42
  declare const etherreq: EtherreqStatic;
34
43
 
package/src/upload.js ADDED
@@ -0,0 +1,88 @@
1
+ // src/upload.js
2
+ import { etherreq } from './index.js';
3
+
4
+ /**
5
+ * 分片上传配置项
6
+ * @typedef {Object} ChunkedUploadOptions
7
+ * @property {number} chunkSize 分片大小,默认 5MB
8
+ * @property {function(number): void} onProgress 进度回调
9
+ * @property {boolean} resume 是否启用断点续传
10
+ */
11
+
12
+ /**
13
+ * 大文件分片上传
14
+ * @param {string} url 接口地址
15
+ * @param {File|Blob} file 文件对象
16
+ * @param {ChunkedUploadOptions} [options] 配置项
17
+ */
18
+ export async function uploadLargeFile(url, file, options = {}) {
19
+ const { chunkSize = 5 * 1024 * 1024, onProgress = () => {}, resume = true } = options;
20
+
21
+ const totalChunks = Math.ceil(file.size / chunkSize);
22
+ const uploadedChunks = await getUploadedChunks(url, file, totalChunks, resume);
23
+
24
+ let current = 0;
25
+
26
+ for (let i = 0; i < totalChunks; i++) {
27
+ if (uploadedChunks.includes(i)) {
28
+ current++;
29
+ onProgress(Math.round((current / totalChunks) * 100));
30
+ continue;
31
+ }
32
+
33
+ const start = i * chunkSize;
34
+ const end = Math.min(start + chunkSize, file.size);
35
+ const chunk = file.slice(start, end);
36
+
37
+ const formData = new FormData();
38
+ formData.append('file', chunk);
39
+ formData.append('chunkIndex', i);
40
+ formData.append('totalChunks', totalChunks);
41
+ formData.append('fileName', file.name);
42
+
43
+ try {
44
+ await etherreq.post(url, formData, {
45
+ headers: {
46
+ 'Content-Type': 'multipart/form-data',
47
+ },
48
+ });
49
+
50
+ current++;
51
+ onProgress(Math.round((current / totalChunks) * 100));
52
+ } catch (error) {
53
+ console.error(`上传分片 ${i} 失败`, error);
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ // 合并请求
59
+ await etherreq.post(`${url}/complete`, {
60
+ fileName: file.name,
61
+ totalChunks,
62
+ });
63
+
64
+ return {
65
+ fileName: file.name,
66
+ size: file.size,
67
+ status: 'completed',
68
+ };
69
+ }
70
+
71
+ /**
72
+ * 获取已上传的分片索引(用于断点续传)
73
+ * @param {string} uploadUrl
74
+ * @param {File} file
75
+ * @param {number} totalChunks
76
+ * @param {boolean} enableResume
77
+ * @returns {Promise<number[]>}
78
+ */
79
+ async function getUploadedChunks(uploadUrl, file, totalChunks, enableResume) {
80
+ if (!enableResume) return [];
81
+
82
+ try {
83
+ const res = await etherreq.get(`${uploadUrl}?check=1&fileName=${encodeURIComponent(file.name)}&totalChunks=${totalChunks}`);
84
+ return res.data.uploadedChunks || [];
85
+ } catch (e) {
86
+ return [];
87
+ }
88
+ }