xxf_react 0.8.6 → 0.8.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../../src/http/client/HttpClient.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAW,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,IAAI,SAAS,EAAE,MAAM,IAAI,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAEH,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,UAAU,EAMlB,MAAM,UAAU,CAAA;AAyFjB,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,gBAAgB;IA8BpC;;OAEG;IACH,aAAa,IAAI,UAAU;IAI3B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAIzC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,GAAE,UAAe,GAAG,SAAS,CAAC,CAAC,CAAC;IAmFhF;;OAEG;YACY,wBAAwB;IAqCvC;;;;;;;;;;;OAWG;YACW,mBAAmB;IAwCjC;;OAEG;YACW,gBAAgB;IAY9B;;OAEG;YACY,kBAAkB;IAWjC;;OAEG;YACY,iBAAiB;IAQhC;;OAEG;YACY,eAAe;IAiB9B;;OAEG;YACY,mBAAmB;IAqBlC;;OAEG;YACY,kBAAkB;IA0BjC;;OAEG;YACY,iBAAiB;IA0BhC;;OAEG;IACH,QAAQ,IAAI,SAAS;IAIrB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGpC"}
1
+ {"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../../src/http/client/HttpClient.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAW,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,IAAI,SAAS,EAAE,MAAM,IAAI,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EAEH,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,UAAU,EAMlB,MAAM,UAAU,CAAA;AA0DjB,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,gBAAgB;IA8BpC;;OAEG;IACH,aAAa,IAAI,UAAU;IAI3B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAIzC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,GAAE,UAAe,GAAG,SAAS,CAAC,CAAC,CAAC;IAmFhF;;OAEG;YACY,wBAAwB;IAqCvC;;;;;;;;;;;OAWG;YACW,mBAAmB;IAwCjC;;OAEG;YACW,gBAAgB;IAY9B;;OAEG;YACY,kBAAkB;IAWjC;;OAEG;YACY,iBAAiB;IAQhC;;OAEG;YACY,eAAe;IAiB9B;;OAEG;YACY,mBAAmB;IAqBlC;;OAEG;YACY,kBAAkB;IA0BjC;;OAEG;YACY,iBAAiB;IA0BhC;;OAEG;IACH,QAAQ,IAAI,SAAS;IAIrB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGpC"}
@@ -9,37 +9,8 @@
9
9
  import ky from 'ky';
10
10
  import { HttpCache } from '../cache/HttpCache';
11
11
  import { ApiStream } from './ApiStream';
12
+ import { stableStringify } from '../utils/StableStringify';
12
13
  import { CacheMode, } from '../types';
13
- /**
14
- * 对象 key 排序(用于生成稳定的缓存 key)
15
- * 支持嵌套对象递归排序
16
- */
17
- function sortKeys(obj) {
18
- const sorted = {};
19
- for (const key of Object.keys(obj).sort()) {
20
- const value = obj[key];
21
- // 递归处理嵌套对象(排除 null 和数组)
22
- if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
23
- sorted[key] = sortKeys(value);
24
- }
25
- else {
26
- sorted[key] = value;
27
- }
28
- }
29
- return sorted;
30
- }
31
- /**
32
- * 简单 hash 函数
33
- */
34
- function simpleHash(str) {
35
- let hash = 0;
36
- for (let i = 0; i < str.length; i++) {
37
- const char = str.charCodeAt(i);
38
- hash = (hash << 5) - hash + char;
39
- hash = hash & hash; // Convert to 32bit integer
40
- }
41
- return Math.abs(hash).toString(36);
42
- }
43
14
  /**
44
15
  * 过滤对象中的 undefined 和 null 值
45
16
  */
@@ -60,10 +31,10 @@ function filterUndefined(obj) {
60
31
  function defaultGenerateCacheKey(request, keyHeaders) {
61
32
  const parts = [request.method, request.path];
62
33
  if (request.query && Object.keys(request.query).length > 0) {
63
- parts.push(JSON.stringify(sortKeys(request.query)));
34
+ parts.push(stableStringify(request.query));
64
35
  }
65
36
  if (request.body) {
66
- parts.push(simpleHash(JSON.stringify(request.body)));
37
+ parts.push(stableStringify(request.body));
67
38
  }
68
39
  if ((keyHeaders === null || keyHeaders === void 0 ? void 0 : keyHeaders.length) && request.headers) {
69
40
  const headerParts = keyHeaders
@@ -7,6 +7,7 @@ import { CacheInterceptor } from './CacheInterceptor';
7
7
  * 默认缓存拦截器
8
8
  *
9
9
  * 只有满足以下条件才缓存:
10
+ * - 请求方法为 GET
10
11
  * - HTTP 状态码 = 200
11
12
  * - Content-Type 包含 application/json(不区分大小写)
12
13
  * - data 是有效对象或数组
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultCacheInterceptor.d.ts","sourceRoot":"","sources":["../../../src/http/interceptor/DefaultCacheInterceptor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBAuCrC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,GAChE,gBAAgB,CAiBlB"}
1
+ {"version":3,"file":"DefaultCacheInterceptor.d.ts","sourceRoot":"","sources":["../../../src/http/interceptor/DefaultCacheInterceptor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBA4CrC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,GAChE,gBAAgB,CAiBlB"}
@@ -7,6 +7,7 @@ import { isApiSuccess } from '../../models';
7
7
  * 默认缓存拦截器
8
8
  *
9
9
  * 只有满足以下条件才缓存:
10
+ * - 请求方法为 GET
10
11
  * - HTTP 状态码 = 200
11
12
  * - Content-Type 包含 application/json(不区分大小写)
12
13
  * - data 是有效对象或数组
@@ -27,6 +28,10 @@ import { isApiSuccess } from '../../models';
27
28
  export const defaultCacheInterceptor = (ctx) => {
28
29
  var _a, _b;
29
30
  try {
31
+ // 0. 只缓存 GET 请求
32
+ if (ctx.request.method !== 'GET') {
33
+ return false;
34
+ }
30
35
  // 1. 检查 HTTP 状态码
31
36
  if (ctx.status !== 200) {
32
37
  return false;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 稳定序列化工具
3
+ *
4
+ * 用于生成稳定的缓存 key,特点:
5
+ * - 对象 key 自动排序,保证相同内容输出相同结果
6
+ * - 支持循环引用检测,不会 crash
7
+ * - 超长内容自动 hash,避免 key 过长
8
+ * - 零依赖,高性能
9
+ */
10
+ /**
11
+ * 简单 hash(DJB2 变种)
12
+ * 32 位哈希,输出 36 进制字符串
13
+ */
14
+ export declare function simpleHash(str: string): string;
15
+ /**
16
+ * 稳定序列化
17
+ *
18
+ * 将任意对象转为稳定的字符串,用于缓存 key 生成
19
+ * - 对象 key 自动排序
20
+ * - 超过阈值自动 hash
21
+ * - 支持循环引用检测
22
+ *
23
+ * @param obj 要序列化的对象
24
+ * @param hashThreshold 超过此长度自动 hash,默认 200
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * stableStringify({b: 2, a: 1}) // → "a=1&b=2"
29
+ * stableStringify({data: "很长..."}) // → "1a2b3c" (自动 hash)
30
+ * ```
31
+ */
32
+ export declare function stableStringify(obj: unknown, hashThreshold?: number): string;
33
+ //# sourceMappingURL=StableStringify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StableStringify.d.ts","sourceRoot":"","sources":["../../../src/http/utils/StableStringify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,SAAM,GAAG,MAAM,CAIzE"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 稳定序列化工具
3
+ *
4
+ * 用于生成稳定的缓存 key,特点:
5
+ * - 对象 key 自动排序,保证相同内容输出相同结果
6
+ * - 支持循环引用检测,不会 crash
7
+ * - 超长内容自动 hash,避免 key 过长
8
+ * - 零依赖,高性能
9
+ */
10
+ /**
11
+ * 简单 hash(DJB2 变种)
12
+ * 32 位哈希,输出 36 进制字符串
13
+ */
14
+ export function simpleHash(str) {
15
+ let hash = 0;
16
+ for (let i = 0; i < str.length; i++) {
17
+ hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0;
18
+ }
19
+ return (hash >>> 0).toString(36);
20
+ }
21
+ /**
22
+ * 稳定序列化
23
+ *
24
+ * 将任意对象转为稳定的字符串,用于缓存 key 生成
25
+ * - 对象 key 自动排序
26
+ * - 超过阈值自动 hash
27
+ * - 支持循环引用检测
28
+ *
29
+ * @param obj 要序列化的对象
30
+ * @param hashThreshold 超过此长度自动 hash,默认 200
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * stableStringify({b: 2, a: 1}) // → "a=1&b=2"
35
+ * stableStringify({data: "很长..."}) // → "1a2b3c" (自动 hash)
36
+ * ```
37
+ */
38
+ export function stableStringify(obj, hashThreshold = 200) {
39
+ const seen = new WeakSet();
40
+ const result = doStableStringify(obj, seen);
41
+ return result.length > hashThreshold ? simpleHash(result) : result;
42
+ }
43
+ /**
44
+ * 内部递归序列化
45
+ */
46
+ function doStableStringify(obj, seen) {
47
+ // 基础类型
48
+ if (obj === null)
49
+ return 'null';
50
+ if (obj === undefined)
51
+ return '';
52
+ const type = typeof obj;
53
+ if (type === 'string' || type === 'number' || type === 'boolean') {
54
+ return String(obj);
55
+ }
56
+ if (type === 'symbol' || type === 'function') {
57
+ return ''; // 忽略 Symbol 和 Function
58
+ }
59
+ // 对象类型
60
+ if (type === 'object') {
61
+ // 循环引用检测
62
+ if (seen.has(obj))
63
+ return '[Circular]';
64
+ seen.add(obj);
65
+ // Date
66
+ if (obj instanceof Date)
67
+ return obj.toISOString();
68
+ // Array
69
+ if (Array.isArray(obj)) {
70
+ return '[' + obj.map(v => doStableStringify(v, seen)).join(',') + ']';
71
+ }
72
+ // Plain Object
73
+ const record = obj;
74
+ const keys = Object.keys(record).sort();
75
+ const pairs = [];
76
+ for (const key of keys) {
77
+ const value = record[key];
78
+ if (value !== undefined) {
79
+ pairs.push(key + '=' + doStableStringify(value, seen));
80
+ }
81
+ }
82
+ return pairs.join('&');
83
+ }
84
+ return '';
85
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xxf_react",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",