@ahoo-wang/fetcher-react 2.5.8 → 2.5.9

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
@@ -56,7 +56,8 @@ const MyComponent = () => {
56
56
 
57
57
  ### useExecutePromise Hook
58
58
 
59
- The `useExecutePromise` hook manages asynchronous operations with automatic state handling.
59
+ The `useExecutePromise` hook manages asynchronous operations with automatic state handling and built-in race condition
60
+ protection.
60
61
 
61
62
  ```typescript jsx
62
63
  import { useExecutePromise } from '@ahoo-wang/fetcher-react';
@@ -91,6 +92,41 @@ const MyComponent = () => {
91
92
  };
92
93
  ```
93
94
 
95
+ ### useRequestId Hook
96
+
97
+ The `useRequestId` hook provides request ID management for preventing race conditions in async operations.
98
+
99
+ ```typescript jsx
100
+ import { useRequestId } from '@ahoo-wang/fetcher-react';
101
+
102
+ const MyComponent = () => {
103
+ const { generate, isLatest, invalidate } = useRequestId();
104
+
105
+ const handleFetch = async () => {
106
+ const requestId = generate();
107
+
108
+ try {
109
+ const result = await fetchData();
110
+
111
+ if (isLatest(requestId)) {
112
+ setData(result);
113
+ }
114
+ } catch (error) {
115
+ if (isLatest(requestId)) {
116
+ setError(error);
117
+ }
118
+ }
119
+ };
120
+
121
+ return (
122
+ <div>
123
+ <button onClick={handleFetch}>Fetch Data</button>
124
+ <button onClick={invalidate}>Cancel Ongoing</button>
125
+ </div>
126
+ );
127
+ };
128
+ ```
129
+
94
130
  ### useFetcher Hook
95
131
 
96
132
  The `useFetcher` hook provides data fetching capabilities with automatic state management.
@@ -214,9 +250,27 @@ An object containing:
214
250
  - `loading`: Indicates if currently loading
215
251
  - `result`: The result value
216
252
  - `error`: The error value
217
- - `execute`: Function to execute a promise supplier
253
+ - `execute`: Function to execute a promise supplier or promise
218
254
  - `reset`: Function to reset the state to initial values
219
255
 
256
+ ### useRequestId
257
+
258
+ ```typescript
259
+ function useRequestId(): UseRequestIdReturn;
260
+ ```
261
+
262
+ A React hook for managing request IDs and race condition protection.
263
+
264
+ **Returns:**
265
+
266
+ An object containing:
267
+
268
+ - `generate`: Generate a new request ID and get the current one
269
+ - `current`: Get the current request ID without generating a new one
270
+ - `isLatest`: Check if a given request ID is the latest
271
+ - `invalidate`: Invalidate current request ID (mark as stale)
272
+ - `reset`: Reset request ID counter
273
+
220
274
  ### useFetcher
221
275
 
222
276
  ```typescript
package/README.zh-CN.md CHANGED
@@ -55,7 +55,7 @@ const MyComponent = () => {
55
55
 
56
56
  ### useExecutePromise Hook
57
57
 
58
- `useExecutePromise` hook 管理异步操作,具有自动状态处理。
58
+ `useExecutePromise` hook 管理异步操作,具有自动状态处理和内置竞态条件保护。
59
59
 
60
60
  ```typescript jsx
61
61
  import { useExecutePromise } from '@ahoo-wang/fetcher-react';
@@ -90,6 +90,41 @@ const MyComponent = () => {
90
90
  };
91
91
  ```
92
92
 
93
+ ### useRequestId Hook
94
+
95
+ `useRequestId` hook 提供请求ID管理,用于防止异步操作中的竞态条件。
96
+
97
+ ```typescript jsx
98
+ import { useRequestId } from '@ahoo-wang/fetcher-react';
99
+
100
+ const MyComponent = () => {
101
+ const { generate, isLatest, invalidate } = useRequestId();
102
+
103
+ const handleFetch = async () => {
104
+ const requestId = generate();
105
+
106
+ try {
107
+ const result = await fetchData();
108
+
109
+ if (isLatest(requestId)) {
110
+ setData(result);
111
+ }
112
+ } catch (error) {
113
+ if (isLatest(requestId)) {
114
+ setError(error);
115
+ }
116
+ }
117
+ };
118
+
119
+ return (
120
+ <div>
121
+ <button onClick={handleFetch}>获取数据</button>
122
+ <button onClick={invalidate}>取消进行中</button>
123
+ </div>
124
+ );
125
+ };
126
+ ```
127
+
93
128
  ### useFetcher Hook
94
129
 
95
130
  `useFetcher` hook 提供数据获取功能,具有自动状态管理。
@@ -209,9 +244,27 @@ function useExecutePromise<R = unknown>(): UseExecutePromiseReturn<R>;
209
244
  - `loading`: 指示当前是否加载中
210
245
  - `result`: 结果值
211
246
  - `error`: 错误值
212
- - `execute`: 执行 promise 提供者的函数
247
+ - `execute`: 执行 promise supplier 或 promise 的函数
213
248
  - `reset`: 重置状态到初始值的函数
214
249
 
250
+ ### useRequestId
251
+
252
+ ```typescript
253
+ function useRequestId(): UseRequestIdReturn;
254
+ ```
255
+
256
+ 用于管理请求ID和竞态条件保护的 React hook。
257
+
258
+ **返回值:**
259
+
260
+ 包含以下属性的对象:
261
+
262
+ - `generate`: 生成新请求ID并获取当前ID
263
+ - `current`: 获取当前请求ID而不生成新ID
264
+ - `isLatest`: 检查给定请求ID是否为最新
265
+ - `invalidate`: 使当前请求ID失效(标记为过时)
266
+ - `reset`: 重置请求ID计数器
267
+
215
268
  ### useFetcher
216
269
 
217
270
  ```typescript
@@ -1,3 +1,4 @@
1
1
  export * from './useExecutePromise';
2
2
  export * from './usePromiseState';
3
+ export * from './useRequestId';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAaA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAaA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
@@ -8,7 +8,7 @@ export type PromiseSupplier<R> = () => Promise<R>;
8
8
  * Interface defining the return type of useExecutePromise hook
9
9
  * @template R - The type of the result value
10
10
  */
11
- export interface UseExecutePromiseReturn<R> extends PromiseState<R> {
11
+ export interface UseExecutePromiseReturn<R, E = unknown> extends PromiseState<R, E> {
12
12
  /** Function to execute a promise supplier or promise */
13
13
  execute: (input: PromiseSupplier<R> | Promise<R>) => Promise<R>;
14
14
  /** Function to reset the state to initial values */
@@ -1 +1 @@
1
- {"version":3,"file":"useExecutePromise.d.ts","sourceRoot":"","sources":["../../src/core/useExecutePromise.ts"],"names":[],"mappings":"AAeA,OAAO,EAAmB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IACjE,wDAAwD;IACxD,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,KAAK,uBAAuB,CAAC,CAAC,CAAC,CAkD3E"}
1
+ {"version":3,"file":"useExecutePromise.d.ts","sourceRoot":"","sources":["../../src/core/useExecutePromise.ts"],"names":[],"mappings":"AAeA,OAAO,EAAmB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGlE;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CACrD,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1B,wDAAwD;IACxD,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,oDAAoD;IACpD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,KAAK,uBAAuB,CAAC,CAAC,CAAC,CAuD3E"}
@@ -7,7 +7,7 @@ export declare enum PromiseStatus {
7
7
  SUCCESS = "success",
8
8
  ERROR = "error"
9
9
  }
10
- export interface PromiseState<R> {
10
+ export interface PromiseState<R, E = unknown> {
11
11
  /** Current status of the promise */
12
12
  status: PromiseStatus;
13
13
  /** Indicates if currently loading */
@@ -15,7 +15,7 @@ export interface PromiseState<R> {
15
15
  /** The result value */
16
16
  result: R | undefined;
17
17
  /** The error value */
18
- error: unknown | undefined;
18
+ error: E | undefined;
19
19
  }
20
20
  /**
21
21
  * Options for configuring usePromiseState behavior
@@ -30,25 +30,25 @@ export interface PromiseState<R> {
30
30
  * };
31
31
  * ```
32
32
  */
33
- export interface UsePromiseStateOptions<R> {
33
+ export interface UsePromiseStateOptions<R, E = unknown> {
34
34
  /** Initial status, defaults to IDLE */
35
35
  initialStatus?: PromiseStatus;
36
36
  /** Callback invoked on success */
37
37
  onSuccess?: (result: R) => void;
38
38
  /** Callback invoked on error */
39
- onError?: (error: unknown) => void;
39
+ onError?: (error: E) => void;
40
40
  }
41
41
  /**
42
42
  * Return type for usePromiseState hook
43
43
  * @template R - The type of result
44
44
  */
45
- export interface UsePromiseStateReturn<R> extends PromiseState<R> {
45
+ export interface UsePromiseStateReturn<R, E = unknown> extends PromiseState<R, E> {
46
46
  /** Set status to LOADING */
47
47
  setLoading: () => void;
48
48
  /** Set status to SUCCESS with result */
49
49
  setSuccess: (result: R) => void;
50
50
  /** Set status to ERROR with error */
51
- setError: (error: unknown) => void;
51
+ setError: (error: E) => void;
52
52
  /** Set status to IDLE */
53
53
  setIdle: () => void;
54
54
  }
@@ -82,5 +82,5 @@ export interface UsePromiseStateReturn<R> extends PromiseState<R> {
82
82
  * }
83
83
  * ```
84
84
  */
85
- export declare function usePromiseState<R = unknown>(options?: UsePromiseStateOptions<R>): UsePromiseStateReturn<R>;
85
+ export declare function usePromiseState<R = unknown, E = unknown>(options?: UsePromiseStateOptions<R, E>): UsePromiseStateReturn<R, E>;
86
86
  //# sourceMappingURL=usePromiseState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePromiseState.d.ts","sourceRoot":"","sources":["../../src/core/usePromiseState.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,oCAAoC;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IACtB,sBAAsB;IACtB,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,uCAAuC;IACvC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kCAAkC;IAClC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAChC,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IAC/D,4BAA4B;IAC5B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,wCAAwC;IACxC,UAAU,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAChC,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,yBAAyB;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,OAAO,EACzC,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAClC,qBAAqB,CAAC,CAAC,CAAC,CAyD1B"}
1
+ {"version":3,"file":"usePromiseState.d.ts","sourceRoot":"","sources":["../../src/core/usePromiseState.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,oBAAY,aAAa;IACvB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO;IAC1C,oCAAoC;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IACtB,sBAAsB;IACtB,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO;IACpD,uCAAuC;IACvC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kCAAkC;IAClC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAChC,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/E,4BAA4B;IAC5B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,wCAAwC;IACxC,UAAU,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAChC,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B,yBAAyB;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACtD,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GACrC,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,CAwD7B"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Return type for useRequestId hook
3
+ */
4
+ export interface UseRequestIdReturn {
5
+ /** Generate a new request ID and get the current one */
6
+ generate: () => number;
7
+ /** Get the current request ID without generating a new one */
8
+ current: () => number;
9
+ /** Check if a given request ID is the latest */
10
+ isLatest: (requestId: number) => boolean;
11
+ /** Invalidate current request ID (mark as stale) */
12
+ invalidate: () => void;
13
+ /** Reset request ID counter */
14
+ reset: () => void;
15
+ }
16
+ /**
17
+ * A React hook for managing request IDs and race condition protection
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Basic usage
22
+ * const requestId = useRequestId();
23
+ *
24
+ * const execute = async () => {
25
+ * const id = requestId.generate();
26
+ *
27
+ * try {
28
+ * const result = await someAsyncOperation();
29
+ *
30
+ * // Check if this is still the latest request
31
+ * if (requestId.isLatest(id)) {
32
+ * setState(result);
33
+ * }
34
+ * } catch (error) {
35
+ * if (requestId.isLatest(id)) {
36
+ * setError(error);
37
+ * }
38
+ * }
39
+ * };
40
+ *
41
+ * // Manual cancellation
42
+ * const handleCancel = () => {
43
+ * requestId.invalidate(); // All ongoing requests will be ignored
44
+ * };
45
+ * ```
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // With async operation wrapper
50
+ * const { execute, cancel } = useAsyncOperation(async (data) => {
51
+ * return await apiCall(data);
52
+ * }, [requestId]);
53
+ * ```
54
+ */
55
+ export declare function useRequestId(): UseRequestIdReturn;
56
+ //# sourceMappingURL=useRequestId.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRequestId.d.ts","sourceRoot":"","sources":["../../src/core/useRequestId.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,oDAAoD;IACpD,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,YAAY,IAAI,kBAAkB,CA8BjD"}
@@ -6,7 +6,7 @@ import { PromiseState } from '../core';
6
6
  */
7
7
  export interface UseFetcherOptions extends RequestOptions, FetcherCapable {
8
8
  }
9
- export interface UseFetcherReturn<R> extends PromiseState<R> {
9
+ export interface UseFetcherReturn<R, E = unknown> extends PromiseState<R, E> {
10
10
  /** The FetchExchange object representing the ongoing fetch operation */
11
11
  exchange?: FetchExchange;
12
12
  execute: (request: FetchRequest) => Promise<void>;
@@ -38,5 +38,5 @@ export interface UseFetcherReturn<R> extends PromiseState<R> {
38
38
  * }
39
39
  * ```
40
40
  */
41
- export declare function useFetcher<R>(options?: UseFetcherOptions): UseFetcherReturn<R>;
41
+ export declare function useFetcher<R, E = unknown>(options?: UseFetcherOptions): UseFetcherReturn<R, E>;
42
42
  //# sourceMappingURL=useFetcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useFetcher.d.ts","sourceRoot":"","sources":["../../src/fetcher/useFetcher.ts"],"names":[],"mappings":"AAaA,OAAO,EAEL,cAAc,EACd,aAAa,EACb,YAAY,EAEZ,cAAc,EACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,cAAc,EAAE,cAAc;CACxE;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IAC1D,wEAAwE;IACxE,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,gBAAgB,CAAC,CAAC,CAAC,CA8DrB"}
1
+ {"version":3,"file":"useFetcher.d.ts","sourceRoot":"","sources":["../../src/fetcher/useFetcher.ts"],"names":[],"mappings":"AAaA,OAAO,EAEL,cAAc,EACd,aAAa,EACb,YAAY,EAEZ,cAAc,EACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,YAAY,EAAiC,MAAM,SAAS,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,cAAc,EAAE,cAAc;CACxE;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1E,wEAAwE;IACxE,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EACvC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAgExB"}
package/dist/index.es.js CHANGED
@@ -1,130 +1,151 @@
1
- import { useRef as v, useCallback as u, useEffect as b, useState as d, useSyncExternalStore as S } from "react";
2
- import { fetcher as m, getFetcher as C } from "@ahoo-wang/fetcher";
3
- function g() {
4
- var t = v(!1), n = u(function() {
1
+ import { useRef as h, useCallback as c, useEffect as L, useState as E, useMemo as I, useSyncExternalStore as x } from "react";
2
+ import { fetcher as S, getFetcher as C } from "@ahoo-wang/fetcher";
3
+ function v() {
4
+ var t = h(!1), r = c(function() {
5
5
  return t.current;
6
6
  }, []);
7
- return b(function() {
7
+ return L(function() {
8
8
  return t.current = !0, function() {
9
9
  t.current = !1;
10
10
  };
11
- }, []), n;
11
+ }, []), r;
12
12
  }
13
- var R = /* @__PURE__ */ ((t) => (t.IDLE = "idle", t.LOADING = "loading", t.SUCCESS = "success", t.ERROR = "error", t))(R || {});
14
- function x(t) {
15
- const [n, e] = d(
13
+ var w = /* @__PURE__ */ ((t) => (t.IDLE = "idle", t.LOADING = "loading", t.SUCCESS = "success", t.ERROR = "error", t))(w || {});
14
+ function R(t) {
15
+ const [r, e] = E(
16
16
  t?.initialStatus ?? "idle"
17
17
  /* IDLE */
18
- ), [a, s] = d(void 0), [o, r] = d(void 0), c = g(), E = u(() => {
19
- c() && (e(
18
+ ), [i, u] = E(void 0), [n, s] = E(void 0), o = v(), d = c(() => {
19
+ o() && (e(
20
20
  "loading"
21
21
  /* LOADING */
22
- ), r(void 0));
23
- }, [c]), f = u(
24
- (l) => {
25
- c() && (s(l), e(
22
+ ), s(void 0));
23
+ }, [o]), g = c(
24
+ (a) => {
25
+ o() && (u(a), e(
26
26
  "success"
27
27
  /* SUCCESS */
28
- ), r(void 0), t?.onSuccess?.(l));
28
+ ), s(void 0), t?.onSuccess?.(a));
29
29
  },
30
- [c, t]
31
- ), i = u(
32
- (l) => {
33
- c() && (r(l), e(
30
+ [o, t]
31
+ ), f = c(
32
+ (a) => {
33
+ o() && (s(a), e(
34
34
  "error"
35
35
  /* ERROR */
36
- ), s(void 0), t?.onError?.(l));
36
+ ), u(void 0), t?.onError?.(a));
37
37
  },
38
- [c, t]
39
- ), h = u(() => {
40
- c() && (e(
38
+ [o, t]
39
+ ), l = c(() => {
40
+ o() && (e(
41
41
  "idle"
42
42
  /* IDLE */
43
- ), r(void 0), s(void 0));
44
- }, [c]);
43
+ ), s(void 0), u(void 0));
44
+ }, [o]);
45
+ return I(() => ({
46
+ status: r,
47
+ loading: r === "loading",
48
+ result: i,
49
+ error: n,
50
+ setLoading: d,
51
+ setSuccess: g,
52
+ setError: f,
53
+ setIdle: l
54
+ }), [r, i, n, d, g, f, l]);
55
+ }
56
+ function b() {
57
+ const t = h(0), r = c(() => ++t.current, []), e = c(() => t.current, []), i = c((s) => s === t.current, []), u = c(() => {
58
+ t.current++;
59
+ }, []), n = c(() => {
60
+ t.current = 0;
61
+ }, []);
45
62
  return {
46
- status: n,
47
- loading: n === "loading",
48
- result: a,
49
- error: o,
50
- setLoading: E,
51
- setSuccess: f,
52
- setError: i,
53
- setIdle: h
63
+ generate: r,
64
+ current: e,
65
+ isLatest: i,
66
+ invalidate: u,
67
+ reset: n
54
68
  };
55
69
  }
56
- function L() {
57
- const t = x(), n = g(), e = u(
58
- async (s) => {
59
- if (!n())
70
+ function q() {
71
+ const t = R(), r = v(), e = b(), i = c(
72
+ async (n) => {
73
+ if (!r())
60
74
  throw new Error("Component is unmounted");
75
+ const s = e.generate();
61
76
  t.setLoading();
62
77
  try {
63
- const r = await (typeof s == "function" ? s() : s);
64
- return n() && t.setSuccess(r), r;
78
+ const d = await (typeof n == "function" ? n() : n);
79
+ return r() && e.isLatest(s) && t.setSuccess(d), d;
65
80
  } catch (o) {
66
- throw n() && t.setError(o), o;
81
+ throw r() && e.isLatest(s) && t.setError(o), o;
67
82
  }
68
83
  },
69
- [t, n]
70
- ), a = u(() => {
71
- n() && t.setIdle();
72
- }, [t, n]);
73
- return {
74
- loading: t.loading,
75
- result: t.result,
76
- error: t.error,
77
- execute: e,
78
- reset: a,
79
- status: t.status
80
- };
84
+ [t, r, e]
85
+ ), u = c(() => {
86
+ r() && t.setIdle();
87
+ }, [t, r]);
88
+ return I(
89
+ () => ({
90
+ loading: t.loading,
91
+ result: t.result,
92
+ error: t.error,
93
+ execute: i,
94
+ reset: u,
95
+ status: t.status
96
+ }),
97
+ [t.loading, t.result, t.error, i, u, t.status]
98
+ );
81
99
  }
82
- function I(t) {
83
- const n = u(
84
- (o) => t.addListener(o),
100
+ function y(t) {
101
+ const r = c(
102
+ (n) => t.addListener(n),
85
103
  [t]
86
- ), e = u(() => t.get(), [t]), a = S(n, e, e), s = u(
87
- (o) => t.set(o),
104
+ ), e = c(() => t.get(), [t]), i = x(r, e, e), u = c(
105
+ (n) => t.set(n),
88
106
  [t]
89
107
  );
90
- return [a, s];
108
+ return [i, u];
91
109
  }
92
- function M(t) {
93
- const { fetcher: n = m } = t || {}, e = x(), [a, s] = d(
110
+ function A(t) {
111
+ const { fetcher: r = S } = t || {}, e = R(), [i, u] = E(
94
112
  void 0
95
- ), o = g(), r = v(), c = C(n), E = u(
113
+ ), n = v(), s = h(), o = b(), d = C(r), g = c(
96
114
  async (f) => {
97
- r.current && r.current.abort(), r.current = f.abortController ?? new AbortController(), f.abortController = r.current, e.setLoading();
115
+ s.current && s.current.abort(), s.current = f.abortController ?? new AbortController(), f.abortController = s.current;
116
+ const l = o.generate();
117
+ e.setLoading();
98
118
  try {
99
- const i = await c.exchange(f, t);
100
- o() && s(i);
101
- const h = await i.extractResult();
102
- o() && e.setSuccess(h);
103
- } catch (i) {
104
- if (i instanceof Error && i.name === "AbortError") {
105
- o() && e.setIdle();
119
+ const a = await d.exchange(f, t);
120
+ n() && o.isLatest(l) && u(a);
121
+ const m = await a.extractResult();
122
+ n() && o.isLatest(l) && e.setSuccess(m);
123
+ } catch (a) {
124
+ if (a instanceof Error && a.name === "AbortError") {
125
+ n() && e.setIdle();
106
126
  return;
107
127
  }
108
- o() && e.setError(i);
128
+ n() && o.isLatest(l) && e.setError(a);
109
129
  } finally {
110
- r.current === f.abortController && (r.current = void 0);
130
+ s.current === f.abortController && (s.current = void 0);
111
131
  }
112
132
  },
113
- [c, o, t, e]
133
+ [d, n, t, e, o]
114
134
  );
115
- return b(() => () => {
116
- r.current?.abort(), r.current = void 0;
135
+ return L(() => () => {
136
+ s.current?.abort(), s.current = void 0;
117
137
  }, []), {
118
138
  ...e,
119
- exchange: a,
120
- execute: E
139
+ exchange: i,
140
+ execute: g
121
141
  };
122
142
  }
123
143
  export {
124
- R as PromiseStatus,
125
- L as useExecutePromise,
126
- M as useFetcher,
127
- I as useKeyStorage,
128
- x as usePromiseState
144
+ w as PromiseStatus,
145
+ q as useExecutePromise,
146
+ A as useFetcher,
147
+ y as useKeyStorage,
148
+ R as usePromiseState,
149
+ b as useRequestId
129
150
  };
130
151
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../../../node_modules/.pnpm/react-use@17.6.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-use/esm/useMountedState.js","../src/core/usePromiseState.ts","../src/core/useExecutePromise.ts","../src/storage/useKeyStorage.ts","../src/fetcher/useFetcher.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useMountedState } from 'react-use';\n\n/**\n * Enumeration of possible promise execution states\n */\nexport enum PromiseStatus {\n IDLE = 'idle',\n LOADING = 'loading',\n SUCCESS = 'success',\n ERROR = 'error',\n}\n\nexport interface PromiseState<R> {\n /** Current status of the promise */\n status: PromiseStatus;\n /** Indicates if currently loading */\n loading: boolean;\n /** The result value */\n result: R | undefined;\n /** The error value */\n error: unknown | undefined;\n}\n\n/**\n * Options for configuring usePromiseState behavior\n * @template R - The type of result\n *\n * @example\n * ```typescript\n * const options: UsePromiseStateOptions<string> = {\n * initialStatus: PromiseStatus.IDLE,\n * onSuccess: (result) => console.log('Success:', result),\n * onError: (error) => console.error('Error:', error),\n * };\n * ```\n */\nexport interface UsePromiseStateOptions<R> {\n /** Initial status, defaults to IDLE */\n initialStatus?: PromiseStatus;\n /** Callback invoked on success */\n onSuccess?: (result: R) => void;\n /** Callback invoked on error */\n onError?: (error: unknown) => void;\n}\n\n/**\n * Return type for usePromiseState hook\n * @template R - The type of result\n */\nexport interface UsePromiseStateReturn<R> extends PromiseState<R> {\n /** Set status to LOADING */\n setLoading: () => void;\n /** Set status to SUCCESS with result */\n setSuccess: (result: R) => void;\n /** Set status to ERROR with error */\n setError: (error: unknown) => void;\n /** Set status to IDLE */\n setIdle: () => void;\n}\n\n/**\n * A React hook for managing promise state without execution logic\n * @template R - The type of result\n * @param options - Configuration options\n * @returns State management object\n *\n * @example\n * ```typescript\n * import { usePromiseState, PromiseStatus } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { status, loading, result, error, setSuccess, setError, setIdle } = usePromiseState<string>();\n *\n * const handleSuccess = () => setSuccess('Data loaded');\n * const handleError = () => setError(new Error('Failed to load'));\n *\n * return (\n * <div>\n * <button onClick={handleSuccess}>Set Success</button>\n * <button onClick={handleError}>Set Error</button>\n * <button onClick={setIdle}>Reset</button>\n * <p>Status: {status}</p>\n * {loading && <p>Loading...</p>}\n * {result && <p>Result: {result}</p>}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePromiseState<R = unknown>(\n options?: UsePromiseStateOptions<R>,\n): UsePromiseStateReturn<R> {\n const [status, setStatus] = useState<PromiseStatus>(\n options?.initialStatus ?? PromiseStatus.IDLE,\n );\n const [result, setResult] = useState<R | undefined>(undefined);\n const [error, setErrorState] = useState<unknown | undefined>(undefined);\n const isMounted = useMountedState();\n\n const setLoadingFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.LOADING);\n setErrorState(undefined);\n }\n }, [isMounted]);\n\n const setSuccessFn = useCallback(\n (result: R) => {\n if (isMounted()) {\n setResult(result);\n setStatus(PromiseStatus.SUCCESS);\n setErrorState(undefined);\n options?.onSuccess?.(result);\n }\n },\n [isMounted, options],\n );\n\n const setErrorFn = useCallback(\n (error: unknown) => {\n if (isMounted()) {\n setErrorState(error);\n setStatus(PromiseStatus.ERROR);\n setResult(undefined);\n options?.onError?.(error);\n }\n },\n [isMounted, options],\n );\n\n const setIdleFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.IDLE);\n setErrorState(undefined);\n setResult(undefined);\n }\n }, [isMounted]);\n\n return {\n status,\n loading: status === PromiseStatus.LOADING,\n result,\n error,\n setLoading: setLoadingFn,\n setSuccess: setSuccessFn,\n setError: setErrorFn,\n setIdle: setIdleFn,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback } from 'react';\nimport { useMountedState } from 'react-use';\nimport { usePromiseState, PromiseState } from './usePromiseState';\n\n/**\n * Type definition for a function that returns a Promise\n * @template R - The type of value the promise will resolve to\n */\nexport type PromiseSupplier<R> = () => Promise<R>;\n\n/**\n * Interface defining the return type of useExecutePromise hook\n * @template R - The type of the result value\n */\nexport interface UseExecutePromiseReturn<R> extends PromiseState<R> {\n /** Function to execute a promise supplier or promise */\n execute: (input: PromiseSupplier<R> | Promise<R>) => Promise<R>;\n /** Function to reset the state to initial values */\n reset: () => void;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @template R - The type of the result value\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useExecutePromise } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute, reset } = useExecutePromise<string>();\n *\n * const fetchData = async () => {\n * const response = await fetch('/api/data');\n * return response.text();\n * };\n *\n * const handleFetch = () => {\n * execute(fetchData);\n * };\n *\n * const handleReset = () => {\n * reset();\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * <button onClick={handleReset}>Reset</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useExecutePromise<R = unknown>(): UseExecutePromiseReturn<R> {\n const state = usePromiseState<R>();\n const isMounted = useMountedState();\n\n /**\n * Execute a promise supplier or promise and manage its state\n * @param input - A function that returns a Promise or a Promise to be executed\n * @returns A Promise that resolves with the result of the executed promise\n */\n const execute = useCallback(\n async (input: PromiseSupplier<R> | Promise<R>): Promise<R> => {\n if (!isMounted()) {\n throw new Error('Component is unmounted');\n }\n state.setLoading();\n try {\n const promise = typeof input === 'function' ? input() : input;\n const data = await promise;\n\n if (isMounted()) {\n state.setSuccess(data);\n }\n return data;\n } catch (err) {\n if (isMounted()) {\n state.setError(err);\n }\n throw err;\n }\n },\n [state, isMounted],\n );\n\n /**\n * Reset the state to initial values\n */\n const reset = useCallback(() => {\n if (isMounted()) {\n state.setIdle();\n }\n }, [state, isMounted]);\n\n return {\n loading: state.loading,\n result: state.result,\n error: state.error,\n execute,\n reset,\n status: state.status,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { KeyStorage } from '@ahoo-wang/fetcher-storage';\n\n/**\n * A React hook that provides state management for a KeyStorage instance.\n * Subscribes to storage changes and returns the current value along with a setter function.\n *\n * @template T - The type of value stored in the key storage\n * @param keyStorage - The KeyStorage instance to subscribe to and manage\n * @returns A tuple containing the current stored value and a function to update it\n */\nexport function useKeyStorage<T>(\n keyStorage: KeyStorage<T>,\n): [T | null, (value: T) => void] {\n const subscribe = useCallback(\n (callback: () => void) => keyStorage.addListener(callback),\n [keyStorage],\n );\n const getSnapshot = useCallback(() => keyStorage.get(), [keyStorage]);\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setValue = useCallback(\n (value: T) => keyStorage.set(value),\n [keyStorage],\n );\n return [value, setValue];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n fetcher as defaultFetcher,\n FetcherCapable,\n FetchExchange,\n FetchRequest,\n getFetcher,\n RequestOptions,\n} from '@ahoo-wang/fetcher';\nimport { useRef, useCallback, useEffect, useState } from 'react';\nimport { useMountedState } from 'react-use';\nimport {\n PromiseState,\n usePromiseState,\n} from '../core';\n\n/**\n * Configuration options for the useFetcher hook.\n * Extends RequestOptions and FetcherCapable interfaces.\n */\nexport interface UseFetcherOptions extends RequestOptions, FetcherCapable {\n}\n\nexport interface UseFetcherReturn<R> extends PromiseState<R> {\n /** The FetchExchange object representing the ongoing fetch operation */\n exchange?: FetchExchange;\n execute: (request: FetchRequest) => Promise<void>;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @param options - Configuration options for the fetcher\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useFetcher } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute } = useFetcher<string>();\n *\n * const handleFetch = () => {\n * execute({ url: '/api/data', method: 'GET' });\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useFetcher<R>(\n options?: UseFetcherOptions,\n): UseFetcherReturn<R> {\n const { fetcher = defaultFetcher } = options || {};\n const state = usePromiseState<R>();\n const [exchange, setExchange] = useState<FetchExchange | undefined>(\n undefined,\n );\n const isMounted = useMountedState();\n const abortControllerRef = useRef<AbortController | undefined>();\n\n const currentFetcher = getFetcher(fetcher);\n /**\n * Execute the fetch operation.\n * Cancels any ongoing fetch before starting a new one.\n */\n const execute = useCallback(\n async (request: FetchRequest) => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current =\n request.abortController ?? new AbortController();\n request.abortController = abortControllerRef.current;\n state.setLoading();\n try {\n const exchange = await currentFetcher.exchange(request, options);\n if (isMounted()) {\n setExchange(exchange);\n }\n const result = await exchange.extractResult<R>();\n if (isMounted()) {\n state.setSuccess(result);\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (isMounted()) {\n state.setIdle();\n }\n return;\n }\n if (isMounted()) {\n state.setError(error);\n }\n } finally {\n if (abortControllerRef.current === request.abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [currentFetcher, isMounted, options, state],\n );\n\n useEffect(() => {\n return () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = undefined;\n };\n }, []);\n return {\n ...state,\n exchange,\n execute,\n };\n}\n"],"names":["useMountedState","mountedRef","useRef","get","useCallback","useEffect","PromiseStatus","usePromiseState","options","status","setStatus","useState","result","setResult","error","setErrorState","isMounted","setLoadingFn","setSuccessFn","setErrorFn","setIdleFn","useExecutePromise","state","execute","input","data","err","reset","useKeyStorage","keyStorage","subscribe","callback","getSnapshot","value","useSyncExternalStore","setValue","useFetcher","fetcher","defaultFetcher","exchange","setExchange","abortControllerRef","currentFetcher","getFetcher","request"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.es.js","sources":["../../../node_modules/.pnpm/react-use@17.6.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-use/esm/useMountedState.js","../src/core/usePromiseState.ts","../src/core/useRequestId.ts","../src/core/useExecutePromise.ts","../src/storage/useKeyStorage.ts","../src/fetcher/useFetcher.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useMountedState } from 'react-use';\n\n/**\n * Enumeration of possible promise execution states\n */\nexport enum PromiseStatus {\n IDLE = 'idle',\n LOADING = 'loading',\n SUCCESS = 'success',\n ERROR = 'error',\n}\n\nexport interface PromiseState<R, E = unknown> {\n /** Current status of the promise */\n status: PromiseStatus;\n /** Indicates if currently loading */\n loading: boolean;\n /** The result value */\n result: R | undefined;\n /** The error value */\n error: E | undefined;\n}\n\n/**\n * Options for configuring usePromiseState behavior\n * @template R - The type of result\n *\n * @example\n * ```typescript\n * const options: UsePromiseStateOptions<string> = {\n * initialStatus: PromiseStatus.IDLE,\n * onSuccess: (result) => console.log('Success:', result),\n * onError: (error) => console.error('Error:', error),\n * };\n * ```\n */\nexport interface UsePromiseStateOptions<R, E = unknown> {\n /** Initial status, defaults to IDLE */\n initialStatus?: PromiseStatus;\n /** Callback invoked on success */\n onSuccess?: (result: R) => void;\n /** Callback invoked on error */\n onError?: (error: E) => void;\n}\n\n/**\n * Return type for usePromiseState hook\n * @template R - The type of result\n */\nexport interface UsePromiseStateReturn<R, E = unknown> extends PromiseState<R, E> {\n /** Set status to LOADING */\n setLoading: () => void;\n /** Set status to SUCCESS with result */\n setSuccess: (result: R) => void;\n /** Set status to ERROR with error */\n setError: (error: E) => void;\n /** Set status to IDLE */\n setIdle: () => void;\n}\n\n/**\n * A React hook for managing promise state without execution logic\n * @template R - The type of result\n * @param options - Configuration options\n * @returns State management object\n *\n * @example\n * ```typescript\n * import { usePromiseState, PromiseStatus } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { status, loading, result, error, setSuccess, setError, setIdle } = usePromiseState<string>();\n *\n * const handleSuccess = () => setSuccess('Data loaded');\n * const handleError = () => setError(new Error('Failed to load'));\n *\n * return (\n * <div>\n * <button onClick={handleSuccess}>Set Success</button>\n * <button onClick={handleError}>Set Error</button>\n * <button onClick={setIdle}>Reset</button>\n * <p>Status: {status}</p>\n * {loading && <p>Loading...</p>}\n * {result && <p>Result: {result}</p>}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePromiseState<R = unknown, E = unknown>(\n options?: UsePromiseStateOptions<R, E>,\n): UsePromiseStateReturn<R, E> {\n const [status, setStatus] = useState<PromiseStatus>(\n options?.initialStatus ?? PromiseStatus.IDLE,\n );\n const [result, setResult] = useState<R | undefined>(undefined);\n const [error, setErrorState] = useState<E | undefined>(undefined);\n const isMounted = useMountedState();\n\n const setLoadingFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.LOADING);\n setErrorState(undefined);\n }\n }, [isMounted]);\n\n const setSuccessFn = useCallback(\n (result: R) => {\n if (isMounted()) {\n setResult(result);\n setStatus(PromiseStatus.SUCCESS);\n setErrorState(undefined);\n options?.onSuccess?.(result);\n }\n },\n [isMounted, options],\n );\n\n const setErrorFn = useCallback(\n (error: E) => {\n if (isMounted()) {\n setErrorState(error);\n setStatus(PromiseStatus.ERROR);\n setResult(undefined);\n options?.onError?.(error);\n }\n },\n [isMounted, options],\n );\n\n const setIdleFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.IDLE);\n setErrorState(undefined);\n setResult(undefined);\n }\n }, [isMounted]);\n return useMemo(() => ({\n status,\n loading: status === PromiseStatus.LOADING,\n result,\n error,\n setLoading: setLoadingFn,\n setSuccess: setSuccessFn,\n setError: setErrorFn,\n setIdle: setIdleFn,\n }), [status, result, error, setLoadingFn, setSuccessFn, setErrorFn, setIdleFn]);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useRef, useCallback } from 'react';\n\n/**\n * Return type for useRequestId hook\n */\nexport interface UseRequestIdReturn {\n /** Generate a new request ID and get the current one */\n generate: () => number;\n /** Get the current request ID without generating a new one */\n current: () => number;\n /** Check if a given request ID is the latest */\n isLatest: (requestId: number) => boolean;\n /** Invalidate current request ID (mark as stale) */\n invalidate: () => void;\n /** Reset request ID counter */\n reset: () => void;\n}\n\n/**\n * A React hook for managing request IDs and race condition protection\n *\n * @example\n * ```typescript\n * // Basic usage\n * const requestId = useRequestId();\n *\n * const execute = async () => {\n * const id = requestId.generate();\n *\n * try {\n * const result = await someAsyncOperation();\n *\n * // Check if this is still the latest request\n * if (requestId.isLatest(id)) {\n * setState(result);\n * }\n * } catch (error) {\n * if (requestId.isLatest(id)) {\n * setError(error);\n * }\n * }\n * };\n *\n * // Manual cancellation\n * const handleCancel = () => {\n * requestId.invalidate(); // All ongoing requests will be ignored\n * };\n * ```\n *\n * @example\n * ```typescript\n * // With async operation wrapper\n * const { execute, cancel } = useAsyncOperation(async (data) => {\n * return await apiCall(data);\n * }, [requestId]);\n * ```\n */\nexport function useRequestId(): UseRequestIdReturn {\n const requestIdRef = useRef<number>(0);\n\n const generate = useCallback((): number => {\n return ++requestIdRef.current;\n }, []);\n\n const current = useCallback((): number => {\n return requestIdRef.current;\n }, []);\n\n const isLatest = useCallback((requestId: number): boolean => {\n return requestId === requestIdRef.current;\n }, []);\n\n const invalidate = useCallback((): void => {\n requestIdRef.current++;\n }, []);\n\n const reset = useCallback((): void => {\n requestIdRef.current = 0;\n }, []);\n\n return {\n generate,\n current,\n isLatest,\n invalidate,\n reset,\n };\n}","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useMountedState } from 'react-use';\nimport { usePromiseState, PromiseState } from './usePromiseState';\nimport { useRequestId } from './useRequestId';\n\n/**\n * Type definition for a function that returns a Promise\n * @template R - The type of value the promise will resolve to\n */\nexport type PromiseSupplier<R> = () => Promise<R>;\n\n/**\n * Interface defining the return type of useExecutePromise hook\n * @template R - The type of the result value\n */\nexport interface UseExecutePromiseReturn<R, E = unknown>\n extends PromiseState<R, E> {\n /** Function to execute a promise supplier or promise */\n execute: (input: PromiseSupplier<R> | Promise<R>) => Promise<R>;\n /** Function to reset the state to initial values */\n reset: () => void;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @template R - The type of the result value\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useExecutePromise } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute, reset } = useExecutePromise<string>();\n *\n * const fetchData = async () => {\n * const response = await fetch('/api/data');\n * return response.text();\n * };\n *\n * const handleFetch = () => {\n * execute(fetchData);\n * };\n *\n * const handleReset = () => {\n * reset();\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * <button onClick={handleReset}>Reset</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useExecutePromise<R = unknown>(): UseExecutePromiseReturn<R> {\n const state = usePromiseState<R>();\n const isMounted = useMountedState();\n const requestId = useRequestId();\n\n /**\n * Execute a promise supplier or promise and manage its state\n * @param input - A function that returns a Promise or a Promise to be executed\n * @returns A Promise that resolves with the result of the executed promise\n */\n const execute = useCallback(\n async (input: PromiseSupplier<R> | Promise<R>): Promise<R> => {\n if (!isMounted()) {\n throw new Error('Component is unmounted');\n }\n const currentRequestId = requestId.generate();\n state.setLoading();\n try {\n const promise = typeof input === 'function' ? input() : input;\n const data = await promise;\n\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setSuccess(data);\n }\n return data;\n } catch (err) {\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setError(err);\n }\n throw err;\n }\n },\n [state, isMounted, requestId],\n );\n\n /**\n * Reset the state to initial values\n */\n const reset = useCallback(() => {\n if (isMounted()) {\n state.setIdle();\n }\n }, [state, isMounted]);\n\n return useMemo(\n () => ({\n loading: state.loading,\n result: state.result,\n error: state.error,\n execute,\n reset,\n status: state.status,\n }),\n [state.loading, state.result, state.error, execute, reset, state.status],\n );\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { KeyStorage } from '@ahoo-wang/fetcher-storage';\n\n/**\n * A React hook that provides state management for a KeyStorage instance.\n * Subscribes to storage changes and returns the current value along with a setter function.\n *\n * @template T - The type of value stored in the key storage\n * @param keyStorage - The KeyStorage instance to subscribe to and manage\n * @returns A tuple containing the current stored value and a function to update it\n */\nexport function useKeyStorage<T>(\n keyStorage: KeyStorage<T>,\n): [T | null, (value: T) => void] {\n const subscribe = useCallback(\n (callback: () => void) => keyStorage.addListener(callback),\n [keyStorage],\n );\n const getSnapshot = useCallback(() => keyStorage.get(), [keyStorage]);\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setValue = useCallback(\n (value: T) => keyStorage.set(value),\n [keyStorage],\n );\n return [value, setValue];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n fetcher as defaultFetcher,\n FetcherCapable,\n FetchExchange,\n FetchRequest,\n getFetcher,\n RequestOptions,\n} from '@ahoo-wang/fetcher';\nimport { useRef, useCallback, useEffect, useState } from 'react';\nimport { useMountedState } from 'react-use';\nimport { PromiseState, usePromiseState, useRequestId } from '../core';\n\n/**\n * Configuration options for the useFetcher hook.\n * Extends RequestOptions and FetcherCapable interfaces.\n */\nexport interface UseFetcherOptions extends RequestOptions, FetcherCapable {\n}\n\nexport interface UseFetcherReturn<R, E = unknown> extends PromiseState<R, E> {\n /** The FetchExchange object representing the ongoing fetch operation */\n exchange?: FetchExchange;\n execute: (request: FetchRequest) => Promise<void>;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @param options - Configuration options for the fetcher\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useFetcher } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute } = useFetcher<string>();\n *\n * const handleFetch = () => {\n * execute({ url: '/api/data', method: 'GET' });\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useFetcher<R, E = unknown>(\n options?: UseFetcherOptions,\n): UseFetcherReturn<R, E> {\n const { fetcher = defaultFetcher } = options || {};\n const state = usePromiseState<R, E>();\n const [exchange, setExchange] = useState<FetchExchange | undefined>(\n undefined,\n );\n const isMounted = useMountedState();\n const abortControllerRef = useRef<AbortController | undefined>();\n const requestId = useRequestId();\n\n const currentFetcher = getFetcher(fetcher);\n /**\n * Execute the fetch operation.\n * Cancels any ongoing fetch before starting a new one.\n */\n const execute = useCallback(\n async (request: FetchRequest) => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current =\n request.abortController ?? new AbortController();\n request.abortController = abortControllerRef.current;\n const currentRequestId = requestId.generate();\n state.setLoading();\n try {\n const exchange = await currentFetcher.exchange(request, options);\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n setExchange(exchange);\n }\n const result = await exchange.extractResult<R>();\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setSuccess(result);\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (isMounted()) {\n state.setIdle();\n }\n return;\n }\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setError(error as E);\n }\n } finally {\n if (abortControllerRef.current === request.abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [currentFetcher, isMounted, options, state, requestId],\n );\n\n useEffect(() => {\n return () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = undefined;\n };\n }, []);\n return {\n ...state,\n exchange,\n execute,\n };\n}\n"],"names":["useMountedState","mountedRef","useRef","get","useCallback","useEffect","PromiseStatus","usePromiseState","options","status","setStatus","useState","result","setResult","error","setErrorState","isMounted","setLoadingFn","setSuccessFn","setErrorFn","setIdleFn","useMemo","useRequestId","requestIdRef","generate","current","isLatest","requestId","invalidate","reset","useExecutePromise","state","execute","input","currentRequestId","data","err","useKeyStorage","keyStorage","subscribe","callback","getSnapshot","value","useSyncExternalStore","setValue","useFetcher","fetcher","defaultFetcher","exchange","setExchange","abortControllerRef","currentFetcher","getFetcher","request"],"mappings":"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","x_google_ignoreList":[0]}
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- (function(u,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("react"),require("@ahoo-wang/fetcher")):typeof define=="function"&&define.amd?define(["exports","react","@ahoo-wang/fetcher"],t):(u=typeof globalThis<"u"?globalThis:u||self,t(u.FetcherReact={},u.React,u.Fetcher))})(this,(function(u,t,S){"use strict";function h(){var e=t.useRef(!1),s=t.useCallback(function(){return e.current},[]);return t.useEffect(function(){return e.current=!0,function(){e.current=!1}},[]),s}var g=(e=>(e.IDLE="idle",e.LOADING="loading",e.SUCCESS="success",e.ERROR="error",e))(g||{});function b(e){const[s,r]=t.useState(e?.initialStatus??"idle"),[l,c]=t.useState(void 0),[o,n]=t.useState(void 0),i=h(),C=t.useCallback(()=>{i()&&(r("loading"),n(void 0))},[i]),f=t.useCallback(d=>{i()&&(c(d),r("success"),n(void 0),e?.onSuccess?.(d))},[i,e]),a=t.useCallback(d=>{i()&&(n(d),r("error"),c(void 0),e?.onError?.(d))},[i,e]),E=t.useCallback(()=>{i()&&(r("idle"),n(void 0),c(void 0))},[i]);return{status:s,loading:s==="loading",result:l,error:o,setLoading:C,setSuccess:f,setError:a,setIdle:E}}function v(){const e=b(),s=h(),r=t.useCallback(async c=>{if(!s())throw new Error("Component is unmounted");e.setLoading();try{const n=await(typeof c=="function"?c():c);return s()&&e.setSuccess(n),n}catch(o){throw s()&&e.setError(o),o}},[e,s]),l=t.useCallback(()=>{s()&&e.setIdle()},[e,s]);return{loading:e.loading,result:e.result,error:e.error,execute:r,reset:l,status:e.status}}function m(e){const s=t.useCallback(o=>e.addListener(o),[e]),r=t.useCallback(()=>e.get(),[e]),l=t.useSyncExternalStore(s,r,r),c=t.useCallback(o=>e.set(o),[e]);return[l,c]}function F(e){const{fetcher:s=S.fetcher}=e||{},r=b(),[l,c]=t.useState(void 0),o=h(),n=t.useRef(),i=S.getFetcher(s),C=t.useCallback(async f=>{n.current&&n.current.abort(),n.current=f.abortController??new AbortController,f.abortController=n.current,r.setLoading();try{const a=await i.exchange(f,e);o()&&c(a);const E=await a.extractResult();o()&&r.setSuccess(E)}catch(a){if(a instanceof Error&&a.name==="AbortError"){o()&&r.setIdle();return}o()&&r.setError(a)}finally{n.current===f.abortController&&(n.current=void 0)}},[i,o,e,r]);return t.useEffect(()=>()=>{n.current?.abort(),n.current=void 0},[]),{...r,exchange:l,execute:C}}u.PromiseStatus=g,u.useExecutePromise=v,u.useFetcher=F,u.useKeyStorage=m,u.usePromiseState=b,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(c,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("react"),require("@ahoo-wang/fetcher")):typeof define=="function"&&define.amd?define(["exports","react","@ahoo-wang/fetcher"],t):(c=typeof globalThis<"u"?globalThis:c||self,t(c.FetcherReact={},c.React,c.Fetcher))})(this,(function(c,t,S){"use strict";function C(){var e=t.useRef(!1),s=t.useCallback(function(){return e.current},[]);return t.useEffect(function(){return e.current=!0,function(){e.current=!1}},[]),s}var v=(e=>(e.IDLE="idle",e.LOADING="loading",e.SUCCESS="success",e.ERROR="error",e))(v||{});function g(e){const[s,r]=t.useState(e?.initialStatus??"idle"),[l,i]=t.useState(void 0),[n,u]=t.useState(void 0),o=C(),d=t.useCallback(()=>{o()&&(r("loading"),u(void 0))},[o]),h=t.useCallback(a=>{o()&&(i(a),r("success"),u(void 0),e?.onSuccess?.(a))},[o,e]),f=t.useCallback(a=>{o()&&(u(a),r("error"),i(void 0),e?.onError?.(a))},[o,e]),b=t.useCallback(()=>{o()&&(r("idle"),u(void 0),i(void 0))},[o]);return t.useMemo(()=>({status:s,loading:s==="loading",result:l,error:n,setLoading:d,setSuccess:h,setError:f,setIdle:b}),[s,l,n,d,h,f,b])}function E(){const e=t.useRef(0),s=t.useCallback(()=>++e.current,[]),r=t.useCallback(()=>e.current,[]),l=t.useCallback(u=>u===e.current,[]),i=t.useCallback(()=>{e.current++},[]),n=t.useCallback(()=>{e.current=0},[]);return{generate:s,current:r,isLatest:l,invalidate:i,reset:n}}function m(){const e=g(),s=C(),r=E(),l=t.useCallback(async n=>{if(!s())throw new Error("Component is unmounted");const u=r.generate();e.setLoading();try{const d=await(typeof n=="function"?n():n);return s()&&r.isLatest(u)&&e.setSuccess(d),d}catch(o){throw s()&&r.isLatest(u)&&e.setError(o),o}},[e,s,r]),i=t.useCallback(()=>{s()&&e.setIdle()},[e,s]);return t.useMemo(()=>({loading:e.loading,result:e.result,error:e.error,execute:l,reset:i,status:e.status}),[e.loading,e.result,e.error,l,i,e.status])}function I(e){const s=t.useCallback(n=>e.addListener(n),[e]),r=t.useCallback(()=>e.get(),[e]),l=t.useSyncExternalStore(s,r,r),i=t.useCallback(n=>e.set(n),[e]);return[l,i]}function L(e){const{fetcher:s=S.fetcher}=e||{},r=g(),[l,i]=t.useState(void 0),n=C(),u=t.useRef(),o=E(),d=S.getFetcher(s),h=t.useCallback(async f=>{u.current&&u.current.abort(),u.current=f.abortController??new AbortController,f.abortController=u.current;const b=o.generate();r.setLoading();try{const a=await d.exchange(f,e);n()&&o.isLatest(b)&&i(a);const k=await a.extractResult();n()&&o.isLatest(b)&&r.setSuccess(k)}catch(a){if(a instanceof Error&&a.name==="AbortError"){n()&&r.setIdle();return}n()&&o.isLatest(b)&&r.setError(a)}finally{u.current===f.abortController&&(u.current=void 0)}},[d,n,e,r,o]);return t.useEffect(()=>()=>{u.current?.abort(),u.current=void 0},[]),{...r,exchange:l,execute:h}}c.PromiseStatus=v,c.useExecutePromise=m,c.useFetcher=L,c.useKeyStorage=I,c.usePromiseState=g,c.useRequestId=E,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../../../node_modules/.pnpm/react-use@17.6.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-use/esm/useMountedState.js","../src/core/usePromiseState.ts","../src/core/useExecutePromise.ts","../src/storage/useKeyStorage.ts","../src/fetcher/useFetcher.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useMountedState } from 'react-use';\n\n/**\n * Enumeration of possible promise execution states\n */\nexport enum PromiseStatus {\n IDLE = 'idle',\n LOADING = 'loading',\n SUCCESS = 'success',\n ERROR = 'error',\n}\n\nexport interface PromiseState<R> {\n /** Current status of the promise */\n status: PromiseStatus;\n /** Indicates if currently loading */\n loading: boolean;\n /** The result value */\n result: R | undefined;\n /** The error value */\n error: unknown | undefined;\n}\n\n/**\n * Options for configuring usePromiseState behavior\n * @template R - The type of result\n *\n * @example\n * ```typescript\n * const options: UsePromiseStateOptions<string> = {\n * initialStatus: PromiseStatus.IDLE,\n * onSuccess: (result) => console.log('Success:', result),\n * onError: (error) => console.error('Error:', error),\n * };\n * ```\n */\nexport interface UsePromiseStateOptions<R> {\n /** Initial status, defaults to IDLE */\n initialStatus?: PromiseStatus;\n /** Callback invoked on success */\n onSuccess?: (result: R) => void;\n /** Callback invoked on error */\n onError?: (error: unknown) => void;\n}\n\n/**\n * Return type for usePromiseState hook\n * @template R - The type of result\n */\nexport interface UsePromiseStateReturn<R> extends PromiseState<R> {\n /** Set status to LOADING */\n setLoading: () => void;\n /** Set status to SUCCESS with result */\n setSuccess: (result: R) => void;\n /** Set status to ERROR with error */\n setError: (error: unknown) => void;\n /** Set status to IDLE */\n setIdle: () => void;\n}\n\n/**\n * A React hook for managing promise state without execution logic\n * @template R - The type of result\n * @param options - Configuration options\n * @returns State management object\n *\n * @example\n * ```typescript\n * import { usePromiseState, PromiseStatus } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { status, loading, result, error, setSuccess, setError, setIdle } = usePromiseState<string>();\n *\n * const handleSuccess = () => setSuccess('Data loaded');\n * const handleError = () => setError(new Error('Failed to load'));\n *\n * return (\n * <div>\n * <button onClick={handleSuccess}>Set Success</button>\n * <button onClick={handleError}>Set Error</button>\n * <button onClick={setIdle}>Reset</button>\n * <p>Status: {status}</p>\n * {loading && <p>Loading...</p>}\n * {result && <p>Result: {result}</p>}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePromiseState<R = unknown>(\n options?: UsePromiseStateOptions<R>,\n): UsePromiseStateReturn<R> {\n const [status, setStatus] = useState<PromiseStatus>(\n options?.initialStatus ?? PromiseStatus.IDLE,\n );\n const [result, setResult] = useState<R | undefined>(undefined);\n const [error, setErrorState] = useState<unknown | undefined>(undefined);\n const isMounted = useMountedState();\n\n const setLoadingFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.LOADING);\n setErrorState(undefined);\n }\n }, [isMounted]);\n\n const setSuccessFn = useCallback(\n (result: R) => {\n if (isMounted()) {\n setResult(result);\n setStatus(PromiseStatus.SUCCESS);\n setErrorState(undefined);\n options?.onSuccess?.(result);\n }\n },\n [isMounted, options],\n );\n\n const setErrorFn = useCallback(\n (error: unknown) => {\n if (isMounted()) {\n setErrorState(error);\n setStatus(PromiseStatus.ERROR);\n setResult(undefined);\n options?.onError?.(error);\n }\n },\n [isMounted, options],\n );\n\n const setIdleFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.IDLE);\n setErrorState(undefined);\n setResult(undefined);\n }\n }, [isMounted]);\n\n return {\n status,\n loading: status === PromiseStatus.LOADING,\n result,\n error,\n setLoading: setLoadingFn,\n setSuccess: setSuccessFn,\n setError: setErrorFn,\n setIdle: setIdleFn,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback } from 'react';\nimport { useMountedState } from 'react-use';\nimport { usePromiseState, PromiseState } from './usePromiseState';\n\n/**\n * Type definition for a function that returns a Promise\n * @template R - The type of value the promise will resolve to\n */\nexport type PromiseSupplier<R> = () => Promise<R>;\n\n/**\n * Interface defining the return type of useExecutePromise hook\n * @template R - The type of the result value\n */\nexport interface UseExecutePromiseReturn<R> extends PromiseState<R> {\n /** Function to execute a promise supplier or promise */\n execute: (input: PromiseSupplier<R> | Promise<R>) => Promise<R>;\n /** Function to reset the state to initial values */\n reset: () => void;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @template R - The type of the result value\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useExecutePromise } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute, reset } = useExecutePromise<string>();\n *\n * const fetchData = async () => {\n * const response = await fetch('/api/data');\n * return response.text();\n * };\n *\n * const handleFetch = () => {\n * execute(fetchData);\n * };\n *\n * const handleReset = () => {\n * reset();\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * <button onClick={handleReset}>Reset</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useExecutePromise<R = unknown>(): UseExecutePromiseReturn<R> {\n const state = usePromiseState<R>();\n const isMounted = useMountedState();\n\n /**\n * Execute a promise supplier or promise and manage its state\n * @param input - A function that returns a Promise or a Promise to be executed\n * @returns A Promise that resolves with the result of the executed promise\n */\n const execute = useCallback(\n async (input: PromiseSupplier<R> | Promise<R>): Promise<R> => {\n if (!isMounted()) {\n throw new Error('Component is unmounted');\n }\n state.setLoading();\n try {\n const promise = typeof input === 'function' ? input() : input;\n const data = await promise;\n\n if (isMounted()) {\n state.setSuccess(data);\n }\n return data;\n } catch (err) {\n if (isMounted()) {\n state.setError(err);\n }\n throw err;\n }\n },\n [state, isMounted],\n );\n\n /**\n * Reset the state to initial values\n */\n const reset = useCallback(() => {\n if (isMounted()) {\n state.setIdle();\n }\n }, [state, isMounted]);\n\n return {\n loading: state.loading,\n result: state.result,\n error: state.error,\n execute,\n reset,\n status: state.status,\n };\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { KeyStorage } from '@ahoo-wang/fetcher-storage';\n\n/**\n * A React hook that provides state management for a KeyStorage instance.\n * Subscribes to storage changes and returns the current value along with a setter function.\n *\n * @template T - The type of value stored in the key storage\n * @param keyStorage - The KeyStorage instance to subscribe to and manage\n * @returns A tuple containing the current stored value and a function to update it\n */\nexport function useKeyStorage<T>(\n keyStorage: KeyStorage<T>,\n): [T | null, (value: T) => void] {\n const subscribe = useCallback(\n (callback: () => void) => keyStorage.addListener(callback),\n [keyStorage],\n );\n const getSnapshot = useCallback(() => keyStorage.get(), [keyStorage]);\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setValue = useCallback(\n (value: T) => keyStorage.set(value),\n [keyStorage],\n );\n return [value, setValue];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n fetcher as defaultFetcher,\n FetcherCapable,\n FetchExchange,\n FetchRequest,\n getFetcher,\n RequestOptions,\n} from '@ahoo-wang/fetcher';\nimport { useRef, useCallback, useEffect, useState } from 'react';\nimport { useMountedState } from 'react-use';\nimport {\n PromiseState,\n usePromiseState,\n} from '../core';\n\n/**\n * Configuration options for the useFetcher hook.\n * Extends RequestOptions and FetcherCapable interfaces.\n */\nexport interface UseFetcherOptions extends RequestOptions, FetcherCapable {\n}\n\nexport interface UseFetcherReturn<R> extends PromiseState<R> {\n /** The FetchExchange object representing the ongoing fetch operation */\n exchange?: FetchExchange;\n execute: (request: FetchRequest) => Promise<void>;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @param options - Configuration options for the fetcher\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useFetcher } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute } = useFetcher<string>();\n *\n * const handleFetch = () => {\n * execute({ url: '/api/data', method: 'GET' });\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useFetcher<R>(\n options?: UseFetcherOptions,\n): UseFetcherReturn<R> {\n const { fetcher = defaultFetcher } = options || {};\n const state = usePromiseState<R>();\n const [exchange, setExchange] = useState<FetchExchange | undefined>(\n undefined,\n );\n const isMounted = useMountedState();\n const abortControllerRef = useRef<AbortController | undefined>();\n\n const currentFetcher = getFetcher(fetcher);\n /**\n * Execute the fetch operation.\n * Cancels any ongoing fetch before starting a new one.\n */\n const execute = useCallback(\n async (request: FetchRequest) => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current =\n request.abortController ?? new AbortController();\n request.abortController = abortControllerRef.current;\n state.setLoading();\n try {\n const exchange = await currentFetcher.exchange(request, options);\n if (isMounted()) {\n setExchange(exchange);\n }\n const result = await exchange.extractResult<R>();\n if (isMounted()) {\n state.setSuccess(result);\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (isMounted()) {\n state.setIdle();\n }\n return;\n }\n if (isMounted()) {\n state.setError(error);\n }\n } finally {\n if (abortControllerRef.current === request.abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [currentFetcher, isMounted, options, state],\n );\n\n useEffect(() => {\n return () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = undefined;\n };\n }, []);\n return {\n ...state,\n exchange,\n execute,\n };\n}\n"],"names":["useMountedState","mountedRef","useRef","get","useCallback","useEffect","PromiseStatus","usePromiseState","options","status","setStatus","useState","result","setResult","error","setErrorState","isMounted","setLoadingFn","setSuccessFn","setErrorFn","setIdleFn","useExecutePromise","state","execute","input","data","err","reset","useKeyStorage","keyStorage","subscribe","callback","getSnapshot","value","useSyncExternalStore","setValue","useFetcher","fetcher","defaultFetcher","exchange","setExchange","abortControllerRef","currentFetcher","getFetcher","request"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.umd.js","sources":["../../../node_modules/.pnpm/react-use@17.6.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-use/esm/useMountedState.js","../src/core/usePromiseState.ts","../src/core/useRequestId.ts","../src/core/useExecutePromise.ts","../src/storage/useKeyStorage.ts","../src/fetcher/useFetcher.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nexport default function useMountedState() {\n var mountedRef = useRef(false);\n var get = useCallback(function () { return mountedRef.current; }, []);\n useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useMountedState } from 'react-use';\n\n/**\n * Enumeration of possible promise execution states\n */\nexport enum PromiseStatus {\n IDLE = 'idle',\n LOADING = 'loading',\n SUCCESS = 'success',\n ERROR = 'error',\n}\n\nexport interface PromiseState<R, E = unknown> {\n /** Current status of the promise */\n status: PromiseStatus;\n /** Indicates if currently loading */\n loading: boolean;\n /** The result value */\n result: R | undefined;\n /** The error value */\n error: E | undefined;\n}\n\n/**\n * Options for configuring usePromiseState behavior\n * @template R - The type of result\n *\n * @example\n * ```typescript\n * const options: UsePromiseStateOptions<string> = {\n * initialStatus: PromiseStatus.IDLE,\n * onSuccess: (result) => console.log('Success:', result),\n * onError: (error) => console.error('Error:', error),\n * };\n * ```\n */\nexport interface UsePromiseStateOptions<R, E = unknown> {\n /** Initial status, defaults to IDLE */\n initialStatus?: PromiseStatus;\n /** Callback invoked on success */\n onSuccess?: (result: R) => void;\n /** Callback invoked on error */\n onError?: (error: E) => void;\n}\n\n/**\n * Return type for usePromiseState hook\n * @template R - The type of result\n */\nexport interface UsePromiseStateReturn<R, E = unknown> extends PromiseState<R, E> {\n /** Set status to LOADING */\n setLoading: () => void;\n /** Set status to SUCCESS with result */\n setSuccess: (result: R) => void;\n /** Set status to ERROR with error */\n setError: (error: E) => void;\n /** Set status to IDLE */\n setIdle: () => void;\n}\n\n/**\n * A React hook for managing promise state without execution logic\n * @template R - The type of result\n * @param options - Configuration options\n * @returns State management object\n *\n * @example\n * ```typescript\n * import { usePromiseState, PromiseStatus } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { status, loading, result, error, setSuccess, setError, setIdle } = usePromiseState<string>();\n *\n * const handleSuccess = () => setSuccess('Data loaded');\n * const handleError = () => setError(new Error('Failed to load'));\n *\n * return (\n * <div>\n * <button onClick={handleSuccess}>Set Success</button>\n * <button onClick={handleError}>Set Error</button>\n * <button onClick={setIdle}>Reset</button>\n * <p>Status: {status}</p>\n * {loading && <p>Loading...</p>}\n * {result && <p>Result: {result}</p>}\n * {error && <p>Error: {error.message}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePromiseState<R = unknown, E = unknown>(\n options?: UsePromiseStateOptions<R, E>,\n): UsePromiseStateReturn<R, E> {\n const [status, setStatus] = useState<PromiseStatus>(\n options?.initialStatus ?? PromiseStatus.IDLE,\n );\n const [result, setResult] = useState<R | undefined>(undefined);\n const [error, setErrorState] = useState<E | undefined>(undefined);\n const isMounted = useMountedState();\n\n const setLoadingFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.LOADING);\n setErrorState(undefined);\n }\n }, [isMounted]);\n\n const setSuccessFn = useCallback(\n (result: R) => {\n if (isMounted()) {\n setResult(result);\n setStatus(PromiseStatus.SUCCESS);\n setErrorState(undefined);\n options?.onSuccess?.(result);\n }\n },\n [isMounted, options],\n );\n\n const setErrorFn = useCallback(\n (error: E) => {\n if (isMounted()) {\n setErrorState(error);\n setStatus(PromiseStatus.ERROR);\n setResult(undefined);\n options?.onError?.(error);\n }\n },\n [isMounted, options],\n );\n\n const setIdleFn = useCallback(() => {\n if (isMounted()) {\n setStatus(PromiseStatus.IDLE);\n setErrorState(undefined);\n setResult(undefined);\n }\n }, [isMounted]);\n return useMemo(() => ({\n status,\n loading: status === PromiseStatus.LOADING,\n result,\n error,\n setLoading: setLoadingFn,\n setSuccess: setSuccessFn,\n setError: setErrorFn,\n setIdle: setIdleFn,\n }), [status, result, error, setLoadingFn, setSuccessFn, setErrorFn, setIdleFn]);\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useRef, useCallback } from 'react';\n\n/**\n * Return type for useRequestId hook\n */\nexport interface UseRequestIdReturn {\n /** Generate a new request ID and get the current one */\n generate: () => number;\n /** Get the current request ID without generating a new one */\n current: () => number;\n /** Check if a given request ID is the latest */\n isLatest: (requestId: number) => boolean;\n /** Invalidate current request ID (mark as stale) */\n invalidate: () => void;\n /** Reset request ID counter */\n reset: () => void;\n}\n\n/**\n * A React hook for managing request IDs and race condition protection\n *\n * @example\n * ```typescript\n * // Basic usage\n * const requestId = useRequestId();\n *\n * const execute = async () => {\n * const id = requestId.generate();\n *\n * try {\n * const result = await someAsyncOperation();\n *\n * // Check if this is still the latest request\n * if (requestId.isLatest(id)) {\n * setState(result);\n * }\n * } catch (error) {\n * if (requestId.isLatest(id)) {\n * setError(error);\n * }\n * }\n * };\n *\n * // Manual cancellation\n * const handleCancel = () => {\n * requestId.invalidate(); // All ongoing requests will be ignored\n * };\n * ```\n *\n * @example\n * ```typescript\n * // With async operation wrapper\n * const { execute, cancel } = useAsyncOperation(async (data) => {\n * return await apiCall(data);\n * }, [requestId]);\n * ```\n */\nexport function useRequestId(): UseRequestIdReturn {\n const requestIdRef = useRef<number>(0);\n\n const generate = useCallback((): number => {\n return ++requestIdRef.current;\n }, []);\n\n const current = useCallback((): number => {\n return requestIdRef.current;\n }, []);\n\n const isLatest = useCallback((requestId: number): boolean => {\n return requestId === requestIdRef.current;\n }, []);\n\n const invalidate = useCallback((): void => {\n requestIdRef.current++;\n }, []);\n\n const reset = useCallback((): void => {\n requestIdRef.current = 0;\n }, []);\n\n return {\n generate,\n current,\n isLatest,\n invalidate,\n reset,\n };\n}","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useMountedState } from 'react-use';\nimport { usePromiseState, PromiseState } from './usePromiseState';\nimport { useRequestId } from './useRequestId';\n\n/**\n * Type definition for a function that returns a Promise\n * @template R - The type of value the promise will resolve to\n */\nexport type PromiseSupplier<R> = () => Promise<R>;\n\n/**\n * Interface defining the return type of useExecutePromise hook\n * @template R - The type of the result value\n */\nexport interface UseExecutePromiseReturn<R, E = unknown>\n extends PromiseState<R, E> {\n /** Function to execute a promise supplier or promise */\n execute: (input: PromiseSupplier<R> | Promise<R>) => Promise<R>;\n /** Function to reset the state to initial values */\n reset: () => void;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @template R - The type of the result value\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useExecutePromise } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute, reset } = useExecutePromise<string>();\n *\n * const fetchData = async () => {\n * const response = await fetch('/api/data');\n * return response.text();\n * };\n *\n * const handleFetch = () => {\n * execute(fetchData);\n * };\n *\n * const handleReset = () => {\n * reset();\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * <button onClick={handleReset}>Reset</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useExecutePromise<R = unknown>(): UseExecutePromiseReturn<R> {\n const state = usePromiseState<R>();\n const isMounted = useMountedState();\n const requestId = useRequestId();\n\n /**\n * Execute a promise supplier or promise and manage its state\n * @param input - A function that returns a Promise or a Promise to be executed\n * @returns A Promise that resolves with the result of the executed promise\n */\n const execute = useCallback(\n async (input: PromiseSupplier<R> | Promise<R>): Promise<R> => {\n if (!isMounted()) {\n throw new Error('Component is unmounted');\n }\n const currentRequestId = requestId.generate();\n state.setLoading();\n try {\n const promise = typeof input === 'function' ? input() : input;\n const data = await promise;\n\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setSuccess(data);\n }\n return data;\n } catch (err) {\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setError(err);\n }\n throw err;\n }\n },\n [state, isMounted, requestId],\n );\n\n /**\n * Reset the state to initial values\n */\n const reset = useCallback(() => {\n if (isMounted()) {\n state.setIdle();\n }\n }, [state, isMounted]);\n\n return useMemo(\n () => ({\n loading: state.loading,\n result: state.result,\n error: state.error,\n execute,\n reset,\n status: state.status,\n }),\n [state.loading, state.result, state.error, execute, reset, state.status],\n );\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { KeyStorage } from '@ahoo-wang/fetcher-storage';\n\n/**\n * A React hook that provides state management for a KeyStorage instance.\n * Subscribes to storage changes and returns the current value along with a setter function.\n *\n * @template T - The type of value stored in the key storage\n * @param keyStorage - The KeyStorage instance to subscribe to and manage\n * @returns A tuple containing the current stored value and a function to update it\n */\nexport function useKeyStorage<T>(\n keyStorage: KeyStorage<T>,\n): [T | null, (value: T) => void] {\n const subscribe = useCallback(\n (callback: () => void) => keyStorage.addListener(callback),\n [keyStorage],\n );\n const getSnapshot = useCallback(() => keyStorage.get(), [keyStorage]);\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setValue = useCallback(\n (value: T) => keyStorage.set(value),\n [keyStorage],\n );\n return [value, setValue];\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n fetcher as defaultFetcher,\n FetcherCapable,\n FetchExchange,\n FetchRequest,\n getFetcher,\n RequestOptions,\n} from '@ahoo-wang/fetcher';\nimport { useRef, useCallback, useEffect, useState } from 'react';\nimport { useMountedState } from 'react-use';\nimport { PromiseState, usePromiseState, useRequestId } from '../core';\n\n/**\n * Configuration options for the useFetcher hook.\n * Extends RequestOptions and FetcherCapable interfaces.\n */\nexport interface UseFetcherOptions extends RequestOptions, FetcherCapable {\n}\n\nexport interface UseFetcherReturn<R, E = unknown> extends PromiseState<R, E> {\n /** The FetchExchange object representing the ongoing fetch operation */\n exchange?: FetchExchange;\n execute: (request: FetchRequest) => Promise<void>;\n}\n\n/**\n * A React hook for managing asynchronous operations with proper state handling\n * @param options - Configuration options for the fetcher\n * @returns An object containing the current state and control functions\n *\n * @example\n * ```typescript\n * import { useFetcher } from '@ahoo-wang/fetcher-react';\n *\n * function MyComponent() {\n * const { loading, result, error, execute } = useFetcher<string>();\n *\n * const handleFetch = () => {\n * execute({ url: '/api/data', method: 'GET' });\n * };\n *\n * if (loading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return (\n * <div>\n * <button onClick={handleFetch}>Fetch Data</button>\n * {result && <p>{result}</p>}\n * </div>\n * );\n * }\n * ```\n */\nexport function useFetcher<R, E = unknown>(\n options?: UseFetcherOptions,\n): UseFetcherReturn<R, E> {\n const { fetcher = defaultFetcher } = options || {};\n const state = usePromiseState<R, E>();\n const [exchange, setExchange] = useState<FetchExchange | undefined>(\n undefined,\n );\n const isMounted = useMountedState();\n const abortControllerRef = useRef<AbortController | undefined>();\n const requestId = useRequestId();\n\n const currentFetcher = getFetcher(fetcher);\n /**\n * Execute the fetch operation.\n * Cancels any ongoing fetch before starting a new one.\n */\n const execute = useCallback(\n async (request: FetchRequest) => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n abortControllerRef.current =\n request.abortController ?? new AbortController();\n request.abortController = abortControllerRef.current;\n const currentRequestId = requestId.generate();\n state.setLoading();\n try {\n const exchange = await currentFetcher.exchange(request, options);\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n setExchange(exchange);\n }\n const result = await exchange.extractResult<R>();\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setSuccess(result);\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n if (isMounted()) {\n state.setIdle();\n }\n return;\n }\n if (isMounted() && requestId.isLatest(currentRequestId)) {\n state.setError(error as E);\n }\n } finally {\n if (abortControllerRef.current === request.abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [currentFetcher, isMounted, options, state, requestId],\n );\n\n useEffect(() => {\n return () => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = undefined;\n };\n }, []);\n return {\n ...state,\n exchange,\n execute,\n };\n}\n"],"names":["useMountedState","mountedRef","useRef","get","useCallback","useEffect","PromiseStatus","usePromiseState","options","status","setStatus","useState","result","setResult","error","setErrorState","isMounted","setLoadingFn","setSuccessFn","setErrorFn","setIdleFn","useMemo","useRequestId","requestIdRef","generate","current","isLatest","requestId","invalidate","reset","useExecutePromise","state","execute","input","currentRequestId","data","err","useKeyStorage","keyStorage","subscribe","callback","getSnapshot","value","useSyncExternalStore","setValue","useFetcher","fetcher","defaultFetcher","exchange","setExchange","abortControllerRef","currentFetcher","getFetcher","request"],"mappings":"uUACe,SAASA,GAAkB,CACtC,IAAIC,EAAaC,EAAAA,OAAO,EAAK,EACzBC,EAAMC,EAAAA,YAAY,UAAY,CAAE,OAAOH,EAAW,OAAS,EAAG,EAAE,EACpEI,OAAAA,EAAAA,UAAU,UAAY,CAClB,OAAAJ,EAAW,QAAU,GACd,UAAY,CACfA,EAAW,QAAU,EACzB,CACJ,EAAG,CAAA,CAAE,EACEE,CACX,CCQO,IAAKG,GAAAA,IACVA,EAAA,KAAO,OACPA,EAAA,QAAU,UACVA,EAAA,QAAU,UACVA,EAAA,MAAQ,QAJEA,IAAAA,GAAA,CAAA,CAAA,EAqFL,SAASC,EACdC,EAC6B,CAC7B,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAC1BH,GAAS,eAAiB,MAAA,EAEtB,CAACI,EAAQC,CAAS,EAAIF,EAAAA,SAAwB,MAAS,EACvD,CAACG,EAAOC,CAAa,EAAIJ,EAAAA,SAAwB,MAAS,EAC1DK,EAAYhB,EAAA,EAEZiB,EAAeb,EAAAA,YAAY,IAAM,CACjCY,MACFN,EAAU,SAAA,EACVK,EAAc,MAAS,EAE3B,EAAG,CAACC,CAAS,CAAC,EAERE,EAAed,EAAAA,YAClBQ,GAAc,CACTI,MACFH,EAAUD,CAAM,EAChBF,EAAU,SAAA,EACVK,EAAc,MAAS,EACvBP,GAAS,YAAYI,CAAM,EAE/B,EACA,CAACI,EAAWR,CAAO,CAAA,EAGfW,EAAaf,EAAAA,YAChBU,GAAa,CACRE,MACFD,EAAcD,CAAK,EACnBJ,EAAU,OAAA,EACVG,EAAU,MAAS,EACnBL,GAAS,UAAUM,CAAK,EAE5B,EACA,CAACE,EAAWR,CAAO,CAAA,EAGfY,EAAYhB,EAAAA,YAAY,IAAM,CAC9BY,MACFN,EAAU,MAAA,EACVK,EAAc,MAAS,EACvBF,EAAU,MAAS,EAEvB,EAAG,CAACG,CAAS,CAAC,EACd,OAAOK,EAAAA,QAAQ,KAAO,CACpB,OAAAZ,EACA,QAASA,IAAW,UACpB,OAAAG,EACA,MAAAE,EACA,WAAYG,EACZ,WAAYC,EACZ,SAAUC,EACV,QAASC,CAAA,GACP,CAACX,EAAQG,EAAQE,EAAOG,EAAcC,EAAcC,EAAYC,CAAS,CAAC,CAChF,CC5FO,SAASE,GAAmC,CACjD,MAAMC,EAAerB,EAAAA,OAAe,CAAC,EAE/BsB,EAAWpB,EAAAA,YAAY,IACpB,EAAEmB,EAAa,QACrB,CAAA,CAAE,EAECE,EAAUrB,EAAAA,YAAY,IACnBmB,EAAa,QACnB,CAAA,CAAE,EAECG,EAAWtB,cAAauB,GACrBA,IAAcJ,EAAa,QACjC,CAAA,CAAE,EAECK,EAAaxB,EAAAA,YAAY,IAAY,CACzCmB,EAAa,SACf,EAAG,CAAA,CAAE,EAECM,EAAQzB,EAAAA,YAAY,IAAY,CACpCmB,EAAa,QAAU,CACzB,EAAG,CAAA,CAAE,EAEL,MAAO,CACL,SAAAC,EACA,QAAAC,EACA,SAAAC,EACA,WAAAE,EACA,MAAAC,CAAA,CAEJ,CC3BO,SAASC,GAA6D,CAC3E,MAAMC,EAAQxB,EAAA,EACRS,EAAYhB,EAAA,EACZ2B,EAAYL,EAAA,EAOZU,EAAU5B,EAAAA,YACd,MAAO6B,GAAuD,CAC5D,GAAI,CAACjB,IACH,MAAM,IAAI,MAAM,wBAAwB,EAE1C,MAAMkB,EAAmBP,EAAU,SAAA,EACnCI,EAAM,WAAA,EACN,GAAI,CAEF,MAAMI,EAAO,MADG,OAAOF,GAAU,WAAaA,IAAUA,GAGxD,OAAIjB,EAAA,GAAeW,EAAU,SAASO,CAAgB,GACpDH,EAAM,WAAWI,CAAI,EAEhBA,CACT,OAASC,EAAK,CACZ,MAAIpB,EAAA,GAAeW,EAAU,SAASO,CAAgB,GACpDH,EAAM,SAASK,CAAG,EAEdA,CACR,CACF,EACA,CAACL,EAAOf,EAAWW,CAAS,CAAA,EAMxBE,EAAQzB,EAAAA,YAAY,IAAM,CAC1BY,KACFe,EAAM,QAAA,CAEV,EAAG,CAACA,EAAOf,CAAS,CAAC,EAErB,OAAOK,EAAAA,QACL,KAAO,CACL,QAASU,EAAM,QACf,OAAQA,EAAM,OACd,MAAOA,EAAM,MACb,QAAAC,EACA,MAAAH,EACA,OAAQE,EAAM,MAAA,GAEhB,CAACA,EAAM,QAASA,EAAM,OAAQA,EAAM,MAAOC,EAASH,EAAOE,EAAM,MAAM,CAAA,CAE3E,CCxGO,SAASM,EACdC,EACgC,CAChC,MAAMC,EAAYnC,EAAAA,YACfoC,GAAyBF,EAAW,YAAYE,CAAQ,EACzD,CAACF,CAAU,CAAA,EAEPG,EAAcrC,EAAAA,YAAY,IAAMkC,EAAW,MAAO,CAACA,CAAU,CAAC,EAC9DI,EAAQC,EAAAA,qBAAqBJ,EAAWE,EAAaA,CAAW,EAChEG,EAAWxC,EAAAA,YACdsC,GAAaJ,EAAW,IAAII,CAAK,EAClC,CAACJ,CAAU,CAAA,EAEb,MAAO,CAACI,EAAOE,CAAQ,CACzB,CC2BO,SAASC,EACdrC,EACwB,CACxB,KAAM,SAAEsC,EAAUC,SAAA,EAAmBvC,GAAW,CAAA,EAC1CuB,EAAQxB,EAAA,EACR,CAACyC,EAAUC,CAAW,EAAItC,EAAAA,SAC9B,MAAA,EAEIK,EAAYhB,EAAA,EACZkD,EAAqBhD,EAAAA,OAAA,EACrByB,EAAYL,EAAA,EAEZ6B,EAAiBC,EAAAA,WAAWN,CAAO,EAKnCd,EAAU5B,EAAAA,YACd,MAAOiD,GAA0B,CAC3BH,EAAmB,SACrBA,EAAmB,QAAQ,MAAA,EAE7BA,EAAmB,QACjBG,EAAQ,iBAAmB,IAAI,gBACjCA,EAAQ,gBAAkBH,EAAmB,QAC7C,MAAMhB,EAAmBP,EAAU,SAAA,EACnCI,EAAM,WAAA,EACN,GAAI,CACF,MAAMiB,EAAW,MAAMG,EAAe,SAASE,EAAS7C,CAAO,EAC3DQ,EAAA,GAAeW,EAAU,SAASO,CAAgB,GACpDe,EAAYD,CAAQ,EAEtB,MAAMpC,EAAS,MAAMoC,EAAS,cAAA,EAC1BhC,EAAA,GAAeW,EAAU,SAASO,CAAgB,GACpDH,EAAM,WAAWnB,CAAM,CAE3B,OAASE,EAAO,CACd,GAAIA,aAAiB,OAASA,EAAM,OAAS,aAAc,CACrDE,KACFe,EAAM,QAAA,EAER,MACF,CACIf,EAAA,GAAeW,EAAU,SAASO,CAAgB,GACpDH,EAAM,SAASjB,CAAU,CAE7B,QAAA,CACMoC,EAAmB,UAAYG,EAAQ,kBACzCH,EAAmB,QAAU,OAEjC,CACF,EACA,CAACC,EAAgBnC,EAAWR,EAASuB,EAAOJ,CAAS,CAAA,EAGvDtB,OAAAA,EAAAA,UAAU,IACD,IAAM,CACX6C,EAAmB,SAAS,MAAA,EAC5BA,EAAmB,QAAU,MAC/B,EACC,CAAA,CAAE,EACE,CACL,GAAGnB,EACH,SAAAiB,EACA,QAAAhB,CAAA,CAEJ","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahoo-wang/fetcher-react",
3
- "version": "2.5.8",
3
+ "version": "2.5.9",
4
4
  "description": "React integration for Fetcher HTTP client. Provides React Hooks and components for seamless data fetching with automatic re-rendering and loading states.",
5
5
  "keywords": [
6
6
  "fetch",