@taicode/common-web 1.1.15 → 1.1.17

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,7 +1,7 @@
1
1
  type ApiFunc<P extends unknown[], R = unknown> = (...args: P) => Promise<R>;
2
2
  export declare class CacheApi<P extends unknown[], R> {
3
3
  private func;
4
- private cache;
4
+ private readonly cache;
5
5
  private lastArgs;
6
6
  private accessor pendingRequests;
7
7
  constructor(func: ApiFunc<P, R>);
@@ -14,6 +14,10 @@ export declare class CacheApi<P extends unknown[], R> {
14
14
  * @param force 强制刷新,清除缓存
15
15
  */
16
16
  refresh(force?: boolean): Promise<R>;
17
+ /**
18
+ * 重置缓存和状态
19
+ */
20
+ reset(): Promise<void>;
17
21
  }
18
22
  export {};
19
23
  //# sourceMappingURL=cache-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-api.d.ts","sourceRoot":"","sources":["../../source/cache-api/cache-api.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAE3E,qBAAa,QAAQ,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC;IAU9B,OAAO,CAAC,IAAI;IATxB,OAAO,CAAC,KAAK,CAAqB;IAGlC,OAAO,CAAC,QAAQ,CAAe;IAI/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAI;gBAEhB,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAIvC,IACI,OAAO,IAAI,OAAO,CAErB;IAED,IACI,KAAK,IAAI,OAAO,CAEnB;IAED,IACI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAGK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAuBlC;;;OAGG;IAEG,OAAO,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,CAAC,CAAC;CAalD"}
1
+ {"version":3,"file":"cache-api.d.ts","sourceRoot":"","sources":["../../source/cache-api/cache-api.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAE3E,qBAAa,QAAQ,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC;IAW9B,OAAO,CAAC,IAAI;IATxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAG3C,OAAO,CAAC,QAAQ,CAAe;IAI/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAI;gBAEhB,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAIvC,IACI,OAAO,IAAI,OAAO,CAErB;IAED,IACI,KAAK,IAAI,OAAO,CAEnB;IAED,IACI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAGK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAuBlC;;;OAGG;IAEG,OAAO,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,CAAC,CAAC;IAcjD;;OAEG;IAEG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
@@ -43,12 +43,12 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
43
43
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
44
44
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
45
45
  };
46
- import { action, computed, observable } from 'mobx';
46
+ import { action, computed, observable, when } from 'mobx';
47
47
  import { catchIt } from '@taicode/common-base';
48
48
  import { SideCache } from '../side-cache';
49
49
  let CacheApi = (() => {
50
50
  var _a, _CacheApi_pendingRequests_accessor_storage;
51
- var _b, _c;
51
+ var _b, _c, _d;
52
52
  let _instanceExtraInitializers = [];
53
53
  let _pendingRequests_decorators;
54
54
  let _pendingRequests_initializers = [];
@@ -58,6 +58,7 @@ let CacheApi = (() => {
58
58
  let _get_value_decorators;
59
59
  let _call_decorators;
60
60
  let _refresh_decorators;
61
+ let _reset_decorators;
61
62
  return _a = class CacheApi {
62
63
  // 记录当前正在进行的请求数量
63
64
  get pendingRequests() { return __classPrivateFieldGet(this, _CacheApi_pendingRequests_accessor_storage, "f"); }
@@ -111,6 +112,14 @@ let CacheApi = (() => {
111
112
  // 重新调用最近一次的参数
112
113
  return await this.call(...this.lastArgs);
113
114
  }
115
+ /**
116
+ * 重置缓存和状态
117
+ */
118
+ async reset() {
119
+ await when(() => this.pendingRequests === 0);
120
+ this.lastArgs = undefined;
121
+ this.cache.clear();
122
+ }
114
123
  },
115
124
  _CacheApi_pendingRequests_accessor_storage = new WeakMap(),
116
125
  (() => {
@@ -121,12 +130,14 @@ let CacheApi = (() => {
121
130
  _get_value_decorators = [computed];
122
131
  _call_decorators = [(_b = action).bound.bind(_b)];
123
132
  _refresh_decorators = [(_c = action).bound.bind(_c)];
133
+ _reset_decorators = [(_d = action).bound.bind(_d)];
124
134
  __esDecorate(_a, null, _pendingRequests_decorators, { kind: "accessor", name: "pendingRequests", static: false, private: false, access: { has: obj => "pendingRequests" in obj, get: obj => obj.pendingRequests, set: (obj, value) => { obj.pendingRequests = value; } }, metadata: _metadata }, _pendingRequests_initializers, _pendingRequests_extraInitializers);
125
135
  __esDecorate(_a, null, _get_loading_decorators, { kind: "getter", name: "loading", static: false, private: false, access: { has: obj => "loading" in obj, get: obj => obj.loading }, metadata: _metadata }, null, _instanceExtraInitializers);
126
136
  __esDecorate(_a, null, _get_empty_decorators, { kind: "getter", name: "empty", static: false, private: false, access: { has: obj => "empty" in obj, get: obj => obj.empty }, metadata: _metadata }, null, _instanceExtraInitializers);
127
137
  __esDecorate(_a, null, _get_value_decorators, { kind: "getter", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value }, metadata: _metadata }, null, _instanceExtraInitializers);
128
138
  __esDecorate(_a, null, _call_decorators, { kind: "method", name: "call", static: false, private: false, access: { has: obj => "call" in obj, get: obj => obj.call }, metadata: _metadata }, null, _instanceExtraInitializers);
129
139
  __esDecorate(_a, null, _refresh_decorators, { kind: "method", name: "refresh", static: false, private: false, access: { has: obj => "refresh" in obj, get: obj => obj.refresh }, metadata: _metadata }, null, _instanceExtraInitializers);
140
+ __esDecorate(_a, null, _reset_decorators, { kind: "method", name: "reset", static: false, private: false, access: { has: obj => "reset" in obj, get: obj => obj.reset }, metadata: _metadata }, null, _instanceExtraInitializers);
130
141
  if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
131
142
  })(),
132
143
  _a;
@@ -446,4 +446,165 @@ describe('CacheApi', () => {
446
446
  expect(noParamMockFunc).toHaveBeenCalledTimes(2);
447
447
  });
448
448
  });
449
+ describe('reset 方法', () => {
450
+ it('应该清除所有缓存数据', async () => {
451
+ mockApiFunc.mockResolvedValue('test-result');
452
+ // 先调用 API 产生缓存
453
+ await cacheApi.call('param1', 123);
454
+ expect(cacheApi.value).toBe('test-result');
455
+ expect(cacheApi.empty).toBe(false);
456
+ // 重置
457
+ await cacheApi.reset();
458
+ // 验证缓存被清除
459
+ expect(cacheApi.value).toBeUndefined();
460
+ expect(cacheApi.empty).toBe(true);
461
+ });
462
+ it('应该清除 lastArgs 参数记录', async () => {
463
+ mockApiFunc.mockResolvedValue('test-result');
464
+ // 先调用 API
465
+ await cacheApi.call('param1', 123);
466
+ // 重置
467
+ await cacheApi.reset();
468
+ // 尝试刷新应该抛出错误,因为 lastArgs 已被清除
469
+ await expect(cacheApi.refresh()).rejects.toThrow('没有可用的参数来刷新数据,请先调用 call 方法');
470
+ });
471
+ it('应该在没有任何调用时也能正常重置', async () => {
472
+ // 直接重置,不应该抛出错误
473
+ await expect(cacheApi.reset()).resolves.toBeUndefined();
474
+ // 验证状态
475
+ expect(cacheApi.value).toBeUndefined();
476
+ expect(cacheApi.empty).toBe(true);
477
+ expect(cacheApi.loading).toBe(false);
478
+ });
479
+ it('应该等待所有进行中的请求完成后再重置', async () => {
480
+ let resolveFn;
481
+ const promise = new Promise((resolve) => {
482
+ resolveFn = resolve;
483
+ });
484
+ mockApiFunc.mockReturnValue(promise);
485
+ // 启动一个异步请求
486
+ const callPromise = cacheApi.call('test', 1);
487
+ expect(cacheApi.loading).toBe(true);
488
+ // 开始重置(应该等待请求完成)
489
+ const resetPromise = cacheApi.reset();
490
+ // 此时请求还在进行中,缓存应该还有值
491
+ await new Promise(resolve => setTimeout(resolve, 10));
492
+ // 完成请求
493
+ resolveFn('result');
494
+ await callPromise;
495
+ // 等待重置完成
496
+ await resetPromise;
497
+ // 验证重置后的状态
498
+ expect(cacheApi.value).toBeUndefined();
499
+ expect(cacheApi.empty).toBe(true);
500
+ expect(cacheApi.loading).toBe(false);
501
+ });
502
+ it('应该等待多个并发请求都完成后再重置', async () => {
503
+ const resolvers = [];
504
+ mockApiFunc.mockImplementation((param) => {
505
+ return new Promise((resolve) => {
506
+ resolvers.push((value) => resolve(`${param}-${value}`));
507
+ });
508
+ });
509
+ // 启动三个并发请求
510
+ const promise1 = cacheApi.call('req1', 1);
511
+ const promise2 = cacheApi.call('req2', 2);
512
+ const promise3 = cacheApi.call('req3', 3);
513
+ expect(cacheApi.loading).toBe(true);
514
+ // 开始重置
515
+ const resetPromise = cacheApi.reset();
516
+ // 等待一下
517
+ await new Promise(resolve => setTimeout(resolve, 10));
518
+ // 依次完成所有请求
519
+ resolvers[0]('result1');
520
+ await promise1;
521
+ resolvers[1]('result2');
522
+ await promise2;
523
+ resolvers[2]('result3');
524
+ await promise3;
525
+ // 等待重置完成
526
+ await resetPromise;
527
+ // 验证重置后的状态
528
+ expect(cacheApi.value).toBeUndefined();
529
+ expect(cacheApi.empty).toBe(true);
530
+ expect(cacheApi.loading).toBe(false);
531
+ });
532
+ it('应该在请求失败后也能正常重置', async () => {
533
+ const error = new Error('API Error');
534
+ mockApiFunc.mockRejectedValue(error);
535
+ // 调用失败的请求
536
+ try {
537
+ await cacheApi.call('test', 1);
538
+ }
539
+ catch (e) {
540
+ // 忽略错误
541
+ }
542
+ // 重置应该成功
543
+ await expect(cacheApi.reset()).resolves.toBeUndefined();
544
+ // 验证状态
545
+ expect(cacheApi.value).toBeUndefined();
546
+ expect(cacheApi.empty).toBe(true);
547
+ expect(cacheApi.loading).toBe(false);
548
+ });
549
+ it('重置后应该能够正常调用新的请求', async () => {
550
+ mockApiFunc.mockResolvedValueOnce('first-result');
551
+ mockApiFunc.mockResolvedValueOnce('second-result');
552
+ // 第一次调用
553
+ await cacheApi.call('param1', 123);
554
+ expect(cacheApi.value).toBe('first-result');
555
+ // 重置
556
+ await cacheApi.reset();
557
+ expect(cacheApi.value).toBeUndefined();
558
+ // 重置后再次调用
559
+ await cacheApi.call('param2', 456);
560
+ expect(cacheApi.value).toBe('second-result');
561
+ expect(cacheApi.empty).toBe(false);
562
+ });
563
+ it('重置后 refresh 应该需要先调用 call', async () => {
564
+ mockApiFunc.mockResolvedValue('test-result');
565
+ // 先调用并刷新
566
+ await cacheApi.call('test', 1);
567
+ await cacheApi.refresh();
568
+ // 重置
569
+ await cacheApi.reset();
570
+ // 重置后 refresh 应该抛出错误
571
+ await expect(cacheApi.refresh()).rejects.toThrow('没有可用的参数来刷新数据,请先调用 call 方法');
572
+ });
573
+ it('应该正确处理重置期间的 loading 状态', async () => {
574
+ let resolveFn;
575
+ const promise = new Promise((resolve) => {
576
+ resolveFn = resolve;
577
+ });
578
+ mockApiFunc.mockReturnValue(promise);
579
+ // 启动请求
580
+ const callPromise = cacheApi.call('test', 1);
581
+ expect(cacheApi.loading).toBe(true);
582
+ // 启动重置(会等待请求完成)
583
+ const resetPromise = cacheApi.reset();
584
+ // loading 应该还是 true
585
+ expect(cacheApi.loading).toBe(true);
586
+ // 完成请求
587
+ resolveFn('result');
588
+ await callPromise;
589
+ // loading 变为 false
590
+ expect(cacheApi.loading).toBe(false);
591
+ // 等待重置完成
592
+ await resetPromise;
593
+ // 重置后 loading 应该仍然是 false
594
+ expect(cacheApi.loading).toBe(false);
595
+ });
596
+ it('应该清除所有缓存的 key', async () => {
597
+ mockApiFunc.mockResolvedValue('result');
598
+ // 调用多次产生多个缓存
599
+ await cacheApi.call('param1', 1);
600
+ await cacheApi.call('param2', 2);
601
+ await cacheApi.call('param3', 3);
602
+ expect(cacheApi.empty).toBe(false);
603
+ // 重置
604
+ await cacheApi.reset();
605
+ // 验证所有缓存都被清除
606
+ expect(cacheApi.empty).toBe(true);
607
+ expect(cacheApi.value).toBeUndefined();
608
+ });
609
+ });
449
610
  });
@@ -0,0 +1,2 @@
1
+ export { SizeProvider } from './size-provider';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/size-provider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1 @@
1
+ export { SizeProvider } from './size-provider';
@@ -0,0 +1,9 @@
1
+ import React, { ReactNode } from 'react';
2
+ interface SizeProviderProps {
3
+ className?: string;
4
+ render?: (width: number, height: number) => ReactNode;
5
+ children?: (width: number, height: number) => ReactNode;
6
+ }
7
+ export declare const SizeProvider: React.FC<SizeProviderProps>;
8
+ export {};
9
+ //# sourceMappingURL=size-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"size-provider.d.ts","sourceRoot":"","sources":["../../source/size-provider/size-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAA+B,SAAS,EAAE,MAAM,OAAO,CAAA;AAErE,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,CAAA;IACrD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,CAAA;CACxD;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuCpD,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import clsx from 'clsx';
3
+ import { useRef, useState, useEffect } from 'react';
4
+ export const SizeProvider = (props) => {
5
+ const { children, className } = props;
6
+ const [width, setWidth] = useState(0);
7
+ const [height, setHeight] = useState(0);
8
+ const sizeRef = useRef(null);
9
+ useEffect(() => {
10
+ const resizeObserver = new ResizeObserver((entries) => {
11
+ for (const entry of entries) {
12
+ const { width, height } = entry.contentRect;
13
+ setWidth(width);
14
+ setHeight(height);
15
+ }
16
+ });
17
+ if (sizeRef.current) {
18
+ resizeObserver.observe(sizeRef.current);
19
+ }
20
+ return () => {
21
+ if (sizeRef.current) {
22
+ // eslint-disable-next-line react-hooks/exhaustive-deps
23
+ resizeObserver.unobserve(sizeRef.current);
24
+ }
25
+ };
26
+ }, []);
27
+ const render = props.render || children || null;
28
+ return (_jsxs("div", { className: clsx(className, 'relative w-full h-full overflow-hidden isolate'), children: [_jsx("div", { ref: sizeRef, className: 'absolute flex-shrink-0 w-full h-full z-0 opacity-0', children: "SizeProvider" }), _jsx("div", { className: 'absolute w-full h-full z-1', children: render === null || render === void 0 ? void 0 : render(width, height) })] }));
29
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taicode/common-web",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "author": "Alain",
5
5
  "license": "ISC",
6
6
  "description": "",