@tanstack/pacer 0.16.2 → 0.16.4

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.
Files changed (180) hide show
  1. package/README.md +165 -0
  2. package/dist/async-batcher.cjs +355 -0
  3. package/dist/async-batcher.cjs.map +1 -0
  4. package/dist/async-batcher.d.cts +344 -0
  5. package/dist/async-batcher.d.ts +344 -0
  6. package/dist/async-batcher.js +353 -0
  7. package/dist/async-batcher.js.map +1 -0
  8. package/dist/async-debouncer.cjs +340 -0
  9. package/dist/async-debouncer.cjs.map +1 -0
  10. package/dist/async-debouncer.d.cts +300 -0
  11. package/dist/async-debouncer.d.ts +300 -0
  12. package/dist/async-debouncer.js +338 -0
  13. package/dist/async-debouncer.js.map +1 -0
  14. package/dist/async-queuer.cjs +496 -0
  15. package/dist/async-queuer.cjs.map +1 -0
  16. package/dist/async-queuer.d.cts +440 -0
  17. package/dist/async-queuer.d.ts +440 -0
  18. package/dist/async-queuer.js +494 -0
  19. package/dist/async-queuer.js.map +1 -0
  20. package/dist/async-rate-limiter.cjs +381 -0
  21. package/dist/async-rate-limiter.cjs.map +1 -0
  22. package/dist/{cjs/async-rate-limiter.d.cts → async-rate-limiter.d.cts} +190 -185
  23. package/dist/{esm/async-rate-limiter.d.ts → async-rate-limiter.d.ts} +190 -185
  24. package/dist/async-rate-limiter.js +379 -0
  25. package/dist/async-rate-limiter.js.map +1 -0
  26. package/dist/async-retryer.cjs +378 -0
  27. package/dist/async-retryer.cjs.map +1 -0
  28. package/dist/async-retryer.d.cts +312 -0
  29. package/dist/async-retryer.d.ts +312 -0
  30. package/dist/async-retryer.js +376 -0
  31. package/dist/async-retryer.js.map +1 -0
  32. package/dist/async-throttler.cjs +362 -0
  33. package/dist/async-throttler.cjs.map +1 -0
  34. package/dist/async-throttler.d.cts +320 -0
  35. package/dist/async-throttler.d.ts +320 -0
  36. package/dist/async-throttler.js +360 -0
  37. package/dist/async-throttler.js.map +1 -0
  38. package/dist/batcher.cjs +194 -0
  39. package/dist/batcher.cjs.map +1 -0
  40. package/dist/batcher.d.cts +180 -0
  41. package/dist/batcher.d.ts +180 -0
  42. package/dist/batcher.js +193 -0
  43. package/dist/batcher.js.map +1 -0
  44. package/dist/debouncer.cjs +197 -0
  45. package/dist/debouncer.cjs.map +1 -0
  46. package/dist/debouncer.d.cts +167 -0
  47. package/dist/debouncer.d.ts +167 -0
  48. package/dist/debouncer.js +195 -0
  49. package/dist/debouncer.js.map +1 -0
  50. package/dist/event-client.cjs +20 -0
  51. package/dist/event-client.cjs.map +1 -0
  52. package/dist/event-client.d.cts +49 -0
  53. package/dist/event-client.d.ts +49 -0
  54. package/dist/event-client.js +19 -0
  55. package/dist/event-client.js.map +1 -0
  56. package/dist/index.cjs +49 -0
  57. package/dist/index.d.cts +15 -0
  58. package/dist/index.d.ts +15 -0
  59. package/dist/{esm/index.js → index.js} +5 -41
  60. package/dist/queuer.cjs +393 -0
  61. package/dist/queuer.cjs.map +1 -0
  62. package/dist/queuer.d.cts +345 -0
  63. package/dist/queuer.d.ts +345 -0
  64. package/dist/queuer.js +391 -0
  65. package/dist/queuer.js.map +1 -0
  66. package/dist/rate-limiter.cjs +251 -0
  67. package/dist/rate-limiter.cjs.map +1 -0
  68. package/dist/{cjs/rate-limiter.d.cts → rate-limiter.d.cts} +113 -108
  69. package/dist/{esm/rate-limiter.d.ts → rate-limiter.d.ts} +113 -108
  70. package/dist/rate-limiter.js +249 -0
  71. package/dist/rate-limiter.js.map +1 -0
  72. package/dist/throttler.cjs +209 -0
  73. package/dist/throttler.cjs.map +1 -0
  74. package/dist/throttler.d.cts +207 -0
  75. package/dist/throttler.d.ts +207 -0
  76. package/dist/throttler.js +207 -0
  77. package/dist/throttler.js.map +1 -0
  78. package/dist/types.cjs +0 -0
  79. package/dist/types.d.cts +13 -0
  80. package/dist/types.d.ts +13 -0
  81. package/dist/types.js +1 -0
  82. package/dist/utils.cjs +13 -0
  83. package/dist/utils.cjs.map +1 -0
  84. package/dist/utils.d.cts +8 -0
  85. package/dist/utils.d.ts +8 -0
  86. package/dist/utils.js +11 -0
  87. package/dist/utils.js.map +1 -0
  88. package/package.json +38 -122
  89. package/src/async-batcher.ts +7 -5
  90. package/src/async-debouncer.ts +7 -5
  91. package/src/async-queuer.ts +7 -5
  92. package/src/async-rate-limiter.ts +7 -5
  93. package/src/async-retryer.ts +7 -5
  94. package/src/async-throttler.ts +7 -5
  95. package/src/batcher.ts +7 -5
  96. package/src/debouncer.ts +7 -5
  97. package/src/queuer.ts +7 -5
  98. package/src/rate-limiter.ts +7 -5
  99. package/src/throttler.ts +7 -5
  100. package/dist/cjs/async-batcher.cjs +0 -220
  101. package/dist/cjs/async-batcher.cjs.map +0 -1
  102. package/dist/cjs/async-batcher.d.cts +0 -340
  103. package/dist/cjs/async-debouncer.cjs +0 -231
  104. package/dist/cjs/async-debouncer.cjs.map +0 -1
  105. package/dist/cjs/async-debouncer.d.cts +0 -295
  106. package/dist/cjs/async-queuer.cjs +0 -397
  107. package/dist/cjs/async-queuer.cjs.map +0 -1
  108. package/dist/cjs/async-queuer.d.cts +0 -435
  109. package/dist/cjs/async-rate-limiter.cjs +0 -252
  110. package/dist/cjs/async-rate-limiter.cjs.map +0 -1
  111. package/dist/cjs/async-retryer.cjs +0 -285
  112. package/dist/cjs/async-retryer.cjs.map +0 -1
  113. package/dist/cjs/async-retryer.d.cts +0 -308
  114. package/dist/cjs/async-throttler.cjs +0 -261
  115. package/dist/cjs/async-throttler.cjs.map +0 -1
  116. package/dist/cjs/async-throttler.d.cts +0 -315
  117. package/dist/cjs/batcher.cjs +0 -130
  118. package/dist/cjs/batcher.cjs.map +0 -1
  119. package/dist/cjs/batcher.d.cts +0 -176
  120. package/dist/cjs/debouncer.cjs +0 -137
  121. package/dist/cjs/debouncer.cjs.map +0 -1
  122. package/dist/cjs/debouncer.d.cts +0 -162
  123. package/dist/cjs/event-client.cjs +0 -20
  124. package/dist/cjs/event-client.cjs.map +0 -1
  125. package/dist/cjs/event-client.d.cts +0 -45
  126. package/dist/cjs/index.cjs +0 -51
  127. package/dist/cjs/index.cjs.map +0 -1
  128. package/dist/cjs/index.d.cts +0 -15
  129. package/dist/cjs/queuer.cjs +0 -306
  130. package/dist/cjs/queuer.cjs.map +0 -1
  131. package/dist/cjs/queuer.d.cts +0 -340
  132. package/dist/cjs/rate-limiter.cjs +0 -179
  133. package/dist/cjs/rate-limiter.cjs.map +0 -1
  134. package/dist/cjs/throttler.cjs +0 -151
  135. package/dist/cjs/throttler.cjs.map +0 -1
  136. package/dist/cjs/throttler.d.cts +0 -202
  137. package/dist/cjs/types.d.cts +0 -9
  138. package/dist/cjs/utils.cjs +0 -11
  139. package/dist/cjs/utils.cjs.map +0 -1
  140. package/dist/cjs/utils.d.cts +0 -3
  141. package/dist/esm/async-batcher.d.ts +0 -340
  142. package/dist/esm/async-batcher.js +0 -220
  143. package/dist/esm/async-batcher.js.map +0 -1
  144. package/dist/esm/async-debouncer.d.ts +0 -295
  145. package/dist/esm/async-debouncer.js +0 -231
  146. package/dist/esm/async-debouncer.js.map +0 -1
  147. package/dist/esm/async-queuer.d.ts +0 -435
  148. package/dist/esm/async-queuer.js +0 -397
  149. package/dist/esm/async-queuer.js.map +0 -1
  150. package/dist/esm/async-rate-limiter.js +0 -252
  151. package/dist/esm/async-rate-limiter.js.map +0 -1
  152. package/dist/esm/async-retryer.d.ts +0 -308
  153. package/dist/esm/async-retryer.js +0 -285
  154. package/dist/esm/async-retryer.js.map +0 -1
  155. package/dist/esm/async-throttler.d.ts +0 -315
  156. package/dist/esm/async-throttler.js +0 -261
  157. package/dist/esm/async-throttler.js.map +0 -1
  158. package/dist/esm/batcher.d.ts +0 -176
  159. package/dist/esm/batcher.js +0 -130
  160. package/dist/esm/batcher.js.map +0 -1
  161. package/dist/esm/debouncer.d.ts +0 -162
  162. package/dist/esm/debouncer.js +0 -137
  163. package/dist/esm/debouncer.js.map +0 -1
  164. package/dist/esm/event-client.d.ts +0 -45
  165. package/dist/esm/event-client.js +0 -20
  166. package/dist/esm/event-client.js.map +0 -1
  167. package/dist/esm/index.d.ts +0 -15
  168. package/dist/esm/index.js.map +0 -1
  169. package/dist/esm/queuer.d.ts +0 -340
  170. package/dist/esm/queuer.js +0 -306
  171. package/dist/esm/queuer.js.map +0 -1
  172. package/dist/esm/rate-limiter.js +0 -179
  173. package/dist/esm/rate-limiter.js.map +0 -1
  174. package/dist/esm/throttler.d.ts +0 -202
  175. package/dist/esm/throttler.js +0 -151
  176. package/dist/esm/throttler.js.map +0 -1
  177. package/dist/esm/types.d.ts +0 -9
  178. package/dist/esm/utils.d.ts +0 -3
  179. package/dist/esm/utils.js +0 -11
  180. package/dist/esm/utils.js.map +0 -1
@@ -1,340 +0,0 @@
1
- import { Store } from '@tanstack/store';
2
- import { AsyncRetryer, AsyncRetryerOptions } from './async-retryer.cjs';
3
- import { OptionalKeys } from './types.cjs';
4
- export interface AsyncBatcherState<TValue> {
5
- /**
6
- * Number of batch executions that have resulted in errors
7
- */
8
- errorCount: number;
9
- /**
10
- * Number of batch executions that have been executed
11
- */
12
- executeCount: number;
13
- /**
14
- * Array of items that failed during batch processing
15
- */
16
- failedItems: Array<TValue>;
17
- /**
18
- * Whether the batcher has no items to process (items array is empty)
19
- */
20
- isEmpty: boolean;
21
- /**
22
- * Whether a batch is currently being processed asynchronously
23
- */
24
- isExecuting: boolean;
25
- /**
26
- * Whether the batcher is waiting for the timeout to trigger batch processing
27
- */
28
- isPending: boolean;
29
- /**
30
- * Array of items currently queued for batch processing
31
- */
32
- items: Array<TValue>;
33
- /**
34
- * The result from the most recent batch execution
35
- */
36
- lastResult: any;
37
- /**
38
- * Number of batch executions that have completed (either successfully or with errors)
39
- */
40
- settleCount: number;
41
- /**
42
- * Number of items currently in the batch queue
43
- */
44
- size: number;
45
- /**
46
- * Current processing status - 'idle' when not processing, 'pending' when waiting for timeout, 'executing' when processing, 'populated' when items are present, but no wait is configured
47
- */
48
- status: 'idle' | 'pending' | 'executing' | 'populated';
49
- /**
50
- * Number of batch executions that have completed successfully
51
- */
52
- successCount: number;
53
- /**
54
- * Total number of items that have failed processing across all batches
55
- */
56
- totalItemsFailed: number;
57
- /**
58
- * Total number of items that have been processed across all batches
59
- */
60
- totalItemsProcessed: number;
61
- }
62
- /**
63
- * Options for configuring an AsyncBatcher instance
64
- */
65
- export interface AsyncBatcherOptions<TValue> {
66
- /**
67
- * Options for configuring the underlying async retryer
68
- */
69
- asyncRetryerOptions?: AsyncRetryerOptions<(items: Array<TValue>) => Promise<any>>;
70
- /**
71
- * Custom function to determine if a batch should be processed
72
- * Return true to process the batch immediately
73
- */
74
- getShouldExecute?: (items: Array<TValue>, batcher: AsyncBatcher<TValue>) => boolean;
75
- /**
76
- * Initial state for the async batcher
77
- */
78
- initialState?: Partial<AsyncBatcherState<TValue>>;
79
- /**
80
- * Optional key to identify this async batcher instance.
81
- * If provided, the async batcher will be identified by this key in the devtools and PacerProvider if applicable.
82
- */
83
- key?: string;
84
- /**
85
- * Maximum number of items in a batch
86
- * @default Infinity
87
- */
88
- maxSize?: number;
89
- /**
90
- * Optional error handler for when the batch function throws.
91
- * If provided, the handler will be called with the error, the batch of items that failed, and batcher instance.
92
- * This can be used alongside throwOnError - the handler will be called before any error is thrown.
93
- */
94
- onError?: (error: Error, batch: Array<TValue>, batcher: AsyncBatcher<TValue>) => void;
95
- /**
96
- * Callback fired after items are added to the batcher
97
- */
98
- onItemsChange?: (batcher: AsyncBatcher<TValue>) => void;
99
- /**
100
- * Optional callback to call when a batch is settled (completed or failed)
101
- */
102
- onSettled?: (batch: Array<TValue>, batcher: AsyncBatcher<TValue>) => void;
103
- /**
104
- * Optional callback to call when a batch succeeds
105
- */
106
- onSuccess?: (result: any, batch: Array<TValue>, batcher: AsyncBatcher<TValue>) => void;
107
- /**
108
- * Whether the batcher should start processing immediately
109
- * @default true
110
- */
111
- started?: boolean;
112
- /**
113
- * Whether to throw errors when they occur.
114
- * Defaults to true if no onError handler is provided, false if an onError handler is provided.
115
- * Can be explicitly set to override these defaults.
116
- */
117
- throwOnError?: boolean;
118
- /**
119
- * Maximum time in milliseconds to wait before processing a batch.
120
- * If the wait duration has elapsed, the batch will be processed.
121
- * If not provided, the batch will not be triggered by a timeout.
122
- * @default Infinity
123
- */
124
- wait?: number | ((asyncBatcher: AsyncBatcher<TValue>) => number);
125
- }
126
- /**
127
- * Utility function for sharing common `AsyncBatcherOptions` options between different `AsyncBatcher` instances.
128
- *
129
- */
130
- export declare function asyncBatcherOptions<TValue = any, TOptions extends Partial<AsyncBatcherOptions<TValue>> = Partial<AsyncBatcherOptions<TValue>>>(options: TOptions): TOptions;
131
- type AsyncBatcherOptionsWithOptionalCallbacks<TValue> = OptionalKeys<Required<AsyncBatcherOptions<TValue>>, 'initialState' | 'onError' | 'onItemsChange' | 'onSettled' | 'onSuccess' | 'key'>;
132
- /**
133
- * A class that collects items and processes them in batches asynchronously.
134
- *
135
- * Async vs Sync Versions:
136
- * The async version provides advanced features over the sync Batcher:
137
- * - Returns promises that can be awaited for batch results
138
- * - Built-in retry support via AsyncRetryer integration
139
- * - Abort support to cancel in-flight batch executions
140
- * - Cancel support to prevent pending batches from starting
141
- * - Comprehensive error handling with onError callbacks and throwOnError control
142
- * - Detailed execution tracking (success/error/settle counts)
143
- *
144
- * The sync Batcher is lighter weight and simpler when you don't need async features,
145
- * return values, or execution control.
146
- *
147
- * What is Batching?
148
- * Batching is a technique for grouping multiple operations together to be processed as a single unit.
149
- *
150
- * The AsyncBatcher provides a flexible way to implement async batching with configurable:
151
- * - Maximum batch size (number of items per batch)
152
- * - Time-based batching (process after X milliseconds)
153
- * - Custom batch processing logic via getShouldExecute
154
- * - Event callbacks for monitoring batch operations
155
- * - Error handling for failed batch operations
156
- *
157
- * Error Handling:
158
- * - If an `onError` handler is provided, it will be called with the error, the batch of items that failed, and batcher instance
159
- * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown
160
- * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed
161
- * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown
162
- * - The error state can be checked using the AsyncBatcher instance
163
- *
164
- * State Management:
165
- * - Uses TanStack Store for reactive state management
166
- * - Use `initialState` to provide initial state values when creating the async batcher
167
- * - Use `onSuccess` callback to react to successful batch execution and implement custom logic
168
- * - Use `onError` callback to react to batch execution errors and implement custom error handling
169
- * - Use `onSettled` callback to react to batch execution completion (success or error) and implement custom logic
170
- * - Use `onExecute` callback to react to batch execution and implement custom logic
171
- * - Use `onItemsChange` callback to react to items being added or removed from the batcher
172
- * - The state includes total items processed, success/error counts, and execution status
173
- * - State can be accessed via `asyncBatcher.store.state` when using the class directly
174
- * - When using framework adapters (React/Solid), state is accessed from `asyncBatcher.state`
175
- *
176
- * @example
177
- * ```ts
178
- * const batcher = new AsyncBatcher<number>(
179
- * async (items) => {
180
- * const result = await processItems(items);
181
- * console.log('Processing batch:', items);
182
- * return result;
183
- * },
184
- * {
185
- * maxSize: 5,
186
- * wait: 2000,
187
- * onSuccess: (result) => console.log('Batch succeeded:', result),
188
- * onError: (error) => console.error('Batch failed:', error)
189
- * }
190
- * );
191
- *
192
- * batcher.addItem(1);
193
- * batcher.addItem(2);
194
- * // After 2 seconds or when 5 items are added, whichever comes first,
195
- * // the batch will be processed and the result will be available
196
- * // batcher.execute() // manually trigger a batch
197
- * ```
198
- */
199
- export declare class AsyncBatcher<TValue> {
200
- #private;
201
- fn: (items: Array<TValue>) => Promise<any>;
202
- readonly store: Store<Readonly<AsyncBatcherState<TValue>>>;
203
- key: string | undefined;
204
- options: AsyncBatcherOptionsWithOptionalCallbacks<TValue>;
205
- asyncRetryers: Map<number, AsyncRetryer<(items: Array<TValue>) => Promise<any>>>;
206
- constructor(fn: (items: Array<TValue>) => Promise<any>, initialOptions: AsyncBatcherOptions<TValue>);
207
- /**
208
- * Updates the async batcher options
209
- */
210
- setOptions: (newOptions: Partial<AsyncBatcherOptions<TValue>>) => void;
211
- /**
212
- * Adds an item to the async batcher
213
- * If the batch size is reached, timeout occurs, or shouldProcess returns true, the batch will be processed
214
- *
215
- * @returns The result from the batch function, or undefined if an error occurred and was handled by onError
216
- *
217
- * @throws The error from the batch function if no onError handler is configured or throwOnError is true
218
- */
219
- addItem: (item: TValue) => Promise<any>;
220
- /**
221
- * Processes the current batch of items immediately
222
- */
223
- flush: () => Promise<any>;
224
- /**
225
- * Returns a copy of all items in the async batcher
226
- */
227
- peekAllItems: () => Array<TValue>;
228
- peekFailedItems: () => Array<TValue>;
229
- /**
230
- * Removes all items from the async batcher
231
- */
232
- clear: () => void;
233
- /**
234
- * Returns the AbortSignal for a specific execution.
235
- * If no executeCount is provided, returns the signal for the most recent execution.
236
- * Returns null if no execution is found or not currently executing.
237
- *
238
- * @param executeCount - Optional specific execution to get signal for
239
- * @example
240
- * ```typescript
241
- * const batcher = new AsyncBatcher(
242
- * async (items: string[]) => {
243
- * const signal = batcher.getAbortSignal()
244
- * if (signal) {
245
- * const response = await fetch('/api/batch', {
246
- * method: 'POST',
247
- * body: JSON.stringify(items),
248
- * signal
249
- * })
250
- * return response.json()
251
- * }
252
- * },
253
- * { maxSize: 10, wait: 100 }
254
- * )
255
- * ```
256
- */
257
- getAbortSignal(executeCount?: number): AbortSignal | null;
258
- /**
259
- * Aborts all ongoing executions with the internal abort controllers.
260
- * Does NOT cancel any pending execution that have not started yet.
261
- * Does NOT clear out the items.
262
- */
263
- abort: () => void;
264
- /**
265
- * Cancels any pending execution that have not started yet.
266
- * Does NOT abort any execution already in progress.
267
- * Does NOT clear out the items.
268
- */
269
- cancel: () => void;
270
- /**
271
- * Resets the async batcher state to its default values
272
- */
273
- reset: () => void;
274
- }
275
- /**
276
- * Creates an async batcher that processes items in batches.
277
- *
278
- * Async vs Sync Versions:
279
- * The async version provides advanced features over the sync batch function:
280
- * - Returns promises that can be awaited for batch results
281
- * - Built-in retry support via AsyncRetryer integration
282
- * - Abort support to cancel in-flight batch executions
283
- * - Cancel support to prevent pending batches from starting
284
- * - Comprehensive error handling with onError callbacks and throwOnError control
285
- * - Detailed execution tracking (success/error/settle counts)
286
- *
287
- * The sync batch function is lighter weight and simpler when you don't need async features,
288
- * return values, or execution control.
289
- *
290
- * What is Batching?
291
- * Batching is a technique for grouping multiple operations together to be processed as a single unit.
292
- *
293
- * Configuration Options:
294
- * - `maxSize`: Maximum number of items per batch (default: Infinity)
295
- * - `wait`: Time to wait before processing batch (default: Infinity)
296
- * - `getShouldExecute`: Custom logic to trigger batch processing
297
- * - `asyncRetryerOptions`: Configure retry behavior for batch executions
298
- * - `started`: Whether to start processing immediately (default: true)
299
- *
300
- * Error Handling:
301
- * - If an `onError` handler is provided, it will be called with the error, the batch of items that failed, and batcher instance
302
- * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown
303
- * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed
304
- * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown
305
- * - The error state can be checked using the underlying AsyncBatcher instance
306
- *
307
- * State Management:
308
- * - Uses TanStack Store for reactive state management
309
- * - Use `initialState` to provide initial state values when creating the async batcher
310
- * - Use `onSuccess` callback to react to successful batch execution and implement custom logic
311
- * - Use `onError` callback to react to batch execution errors and implement custom error handling
312
- * - Use `onSettled` callback to react to batch execution completion (success or error) and implement custom logic
313
- * - Use `onItemsChange` callback to react to items being added or removed from the batcher
314
- * - The state includes total items processed, success/error counts, and execution status
315
- * - State can be accessed via the underlying AsyncBatcher instance's `store.state` property
316
- * - When using framework adapters (React/Solid), state is accessed from the hook's state property
317
- *
318
- * @example
319
- * ```ts
320
- * const batchItems = asyncBatch<number>(
321
- * async (items) => {
322
- * const result = await processApiCall(items);
323
- * console.log('Processing:', items);
324
- * return result;
325
- * },
326
- * {
327
- * maxSize: 3,
328
- * wait: 1000,
329
- * onSuccess: (result) => console.log('Batch succeeded:', result),
330
- * onError: (error) => console.error('Batch failed:', error)
331
- * }
332
- * );
333
- *
334
- * batchItems(1);
335
- * batchItems(2);
336
- * batchItems(3); // Triggers batch processing
337
- * ```
338
- */
339
- export declare function asyncBatch<TValue>(fn: (items: Array<TValue>) => Promise<any>, options: AsyncBatcherOptions<TValue>): (item: TValue) => Promise<any>;
340
- export {};
@@ -1,231 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const store = require("@tanstack/store");
4
- const asyncRetryer = require("./async-retryer.cjs");
5
- const utils = require("./utils.cjs");
6
- const eventClient = require("./event-client.cjs");
7
- function getDefaultAsyncDebouncerState() {
8
- return {
9
- canLeadingExecute: true,
10
- errorCount: 0,
11
- isExecuting: false,
12
- isPending: false,
13
- lastArgs: void 0,
14
- lastResult: void 0,
15
- maybeExecuteCount: 0,
16
- settleCount: 0,
17
- status: "idle",
18
- successCount: 0
19
- };
20
- }
21
- function asyncDebouncerOptions(options) {
22
- return options;
23
- }
24
- const defaultOptions = {
25
- asyncRetryerOptions: {
26
- maxAttempts: 1
27
- },
28
- enabled: true,
29
- leading: false,
30
- trailing: true,
31
- wait: 0
32
- };
33
- class AsyncDebouncer {
34
- constructor(fn, initialOptions) {
35
- this.fn = fn;
36
- this.store = new store.Store(getDefaultAsyncDebouncerState());
37
- this.asyncRetryers = /* @__PURE__ */ new Map();
38
- this.#timeoutId = null;
39
- this.#resolvePreviousPromise = null;
40
- this.setOptions = (newOptions) => {
41
- this.options = { ...this.options, ...newOptions };
42
- if (!this.#getEnabled()) {
43
- this.cancel();
44
- }
45
- };
46
- this.#setState = (newState) => {
47
- this.store.setState((state) => {
48
- const combinedState = {
49
- ...state,
50
- ...newState
51
- };
52
- const { isPending, isExecuting, settleCount } = combinedState;
53
- return {
54
- ...combinedState,
55
- status: !this.#getEnabled() ? "disabled" : isPending ? "pending" : isExecuting ? "executing" : settleCount > 0 ? "settled" : "idle"
56
- };
57
- });
58
- eventClient.emitChange("AsyncDebouncer", this);
59
- };
60
- this.#getEnabled = () => {
61
- return !!utils.parseFunctionOrValue(this.options.enabled, this);
62
- };
63
- this.#getWait = () => {
64
- return utils.parseFunctionOrValue(this.options.wait, this);
65
- };
66
- this.maybeExecute = async (...args) => {
67
- if (!this.#getEnabled()) return void 0;
68
- this.#cancelPendingExecution();
69
- this.#setState({
70
- lastArgs: args,
71
- maybeExecuteCount: this.store.state.maybeExecuteCount + 1
72
- });
73
- if (this.options.leading && this.store.state.canLeadingExecute) {
74
- this.#setState({ canLeadingExecute: false });
75
- await this.#execute(...args);
76
- return this.store.state.lastResult;
77
- }
78
- if (this.options.trailing && this.#getEnabled()) {
79
- this.#setState({ isPending: true });
80
- }
81
- return new Promise((resolve, reject) => {
82
- this.#resolvePreviousPromise = resolve;
83
- this.#timeoutId = setTimeout(async () => {
84
- if (this.options.trailing && this.store.state.lastArgs) {
85
- try {
86
- await this.#execute(...this.store.state.lastArgs);
87
- } catch (error) {
88
- reject(error);
89
- }
90
- }
91
- this.#setState({ canLeadingExecute: true });
92
- this.#resolvePreviousPromise = null;
93
- resolve(this.store.state.lastResult);
94
- }, this.#getWait());
95
- });
96
- };
97
- this.#execute = async (...args) => {
98
- if (!this.#getEnabled()) return void 0;
99
- const currentMaybeExecuteCount = this.store.state.maybeExecuteCount + 1;
100
- try {
101
- this.#setState({ isExecuting: true });
102
- const currentAsyncRetryer = new asyncRetryer.AsyncRetryer(this.fn, {
103
- ...this.options.asyncRetryerOptions,
104
- key: `${this.key}-retryer-${currentMaybeExecuteCount}`
105
- });
106
- this.asyncRetryers.set(currentMaybeExecuteCount, currentAsyncRetryer);
107
- const result = await currentAsyncRetryer.execute(...args);
108
- this.#setState({
109
- lastResult: result,
110
- successCount: this.store.state.successCount + 1
111
- });
112
- this.options.onSuccess?.(result, args, this);
113
- } catch (error) {
114
- this.#setState({
115
- errorCount: this.store.state.errorCount + 1
116
- });
117
- this.options.onError?.(error, args, this);
118
- if (this.options.throwOnError) {
119
- throw error;
120
- }
121
- } finally {
122
- this.asyncRetryers.delete(currentMaybeExecuteCount);
123
- this.#setState({
124
- isExecuting: false,
125
- isPending: false,
126
- lastArgs: void 0,
127
- settleCount: this.store.state.settleCount + 1
128
- });
129
- this.options.onSettled?.(args, this);
130
- }
131
- return this.store.state.lastResult;
132
- };
133
- this.flush = async () => {
134
- if (this.store.state.isPending && this.store.state.lastArgs) {
135
- const { lastArgs } = this.store.state;
136
- this.#cancelPendingExecution();
137
- return await this.#execute(...lastArgs);
138
- }
139
- return void 0;
140
- };
141
- this.#resolvePreviousPromiseInternal = () => {
142
- if (this.#resolvePreviousPromise) {
143
- this.#resolvePreviousPromise(this.store.state.lastResult);
144
- this.#resolvePreviousPromise = null;
145
- }
146
- };
147
- this.#clearTimeout = () => {
148
- if (this.#timeoutId) {
149
- clearTimeout(this.#timeoutId);
150
- this.#timeoutId = null;
151
- }
152
- };
153
- this.#cancelPendingExecution = () => {
154
- this.#clearTimeout();
155
- this.#resolvePreviousPromiseInternal();
156
- this.#setState({
157
- isPending: false,
158
- lastArgs: void 0
159
- });
160
- };
161
- this.abort = () => {
162
- this.asyncRetryers.forEach((retryer) => retryer.abort());
163
- this.asyncRetryers.clear();
164
- this.#setState({
165
- isExecuting: false
166
- });
167
- };
168
- this.cancel = () => {
169
- this.#cancelPendingExecution();
170
- this.#setState({ canLeadingExecute: true });
171
- };
172
- this.reset = () => {
173
- this.#setState(getDefaultAsyncDebouncerState());
174
- this.asyncRetryers.forEach((retryer) => retryer.reset());
175
- };
176
- this.key = initialOptions.key;
177
- this.options = {
178
- ...defaultOptions,
179
- ...initialOptions,
180
- throwOnError: initialOptions.throwOnError ?? !initialOptions.onError
181
- };
182
- this.#setState(this.options.initialState ?? {});
183
- eventClient.pacerEventClient.on("d-AsyncDebouncer", (event) => {
184
- if (event.payload.key !== this.key) return;
185
- this.#setState(event.payload.store.state);
186
- this.setOptions(event.payload.options);
187
- });
188
- }
189
- #timeoutId;
190
- #resolvePreviousPromise;
191
- #setState;
192
- #getEnabled;
193
- #getWait;
194
- #execute;
195
- #resolvePreviousPromiseInternal;
196
- #clearTimeout;
197
- #cancelPendingExecution;
198
- /**
199
- * Returns the AbortSignal for a specific execution.
200
- * If no maybeExecuteCount is provided, returns the signal for the most recent execution.
201
- * Returns null if no execution is found or not currently executing.
202
- *
203
- * @param maybeExecuteCount - Optional specific execution to get signal for
204
- * @example
205
- * ```typescript
206
- * const debouncer = new AsyncDebouncer(
207
- * async (searchTerm: string) => {
208
- * const signal = debouncer.getAbortSignal()
209
- * if (signal) {
210
- * const response = await fetch(`/api/search?q=${searchTerm}`, { signal })
211
- * return response.json()
212
- * }
213
- * },
214
- * { wait: 300 }
215
- * )
216
- * ```
217
- */
218
- getAbortSignal(maybeExecuteCount) {
219
- const count = maybeExecuteCount ?? this.store.state.maybeExecuteCount;
220
- const retryer = this.asyncRetryers.get(count);
221
- return retryer?.getAbortSignal() ?? null;
222
- }
223
- }
224
- function asyncDebounce(fn, initialOptions) {
225
- const asyncDebouncer = new AsyncDebouncer(fn, initialOptions);
226
- return asyncDebouncer.maybeExecute;
227
- }
228
- exports.AsyncDebouncer = AsyncDebouncer;
229
- exports.asyncDebounce = asyncDebounce;
230
- exports.asyncDebouncerOptions = asyncDebouncerOptions;
231
- //# sourceMappingURL=async-debouncer.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"async-debouncer.cjs","sources":["../../src/async-debouncer.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport { AsyncRetryer } from './async-retryer'\nimport { parseFunctionOrValue } from './utils'\nimport { emitChange, pacerEventClient } from './event-client'\nimport type { AsyncRetryerOptions } from './async-retryer'\nimport type { AnyAsyncFunction, OptionalKeys } from './types'\n\nexport interface AsyncDebouncerState<TFn extends AnyAsyncFunction> {\n /**\n * Whether the debouncer can execute on the leading edge of the timeout\n */\n canLeadingExecute: boolean\n /**\n * Number of function executions that have resulted in errors\n */\n errorCount: number\n /**\n * Whether the debounced function is currently executing asynchronously\n */\n isExecuting: boolean\n /**\n * Whether the debouncer is waiting for the timeout to trigger execution\n */\n isPending: boolean\n /**\n * The arguments from the most recent call to maybeExecute\n */\n lastArgs: Parameters<TFn> | undefined\n /**\n * The result from the most recent successful function execution\n */\n lastResult: ReturnType<TFn> | undefined\n /**\n * Number of times maybeExecute has been called (for reduction calculations)\n */\n maybeExecuteCount: number\n /**\n * Number of function executions that have completed (either successfully or with errors)\n */\n settleCount: number\n /**\n * Current execution status - 'idle' when not active, 'pending' when waiting, 'executing' when running, 'settled' when completed\n */\n status: 'disabled' | 'idle' | 'pending' | 'executing' | 'settled'\n /**\n * Number of function executions that have completed successfully\n */\n successCount: number\n}\n\nfunction getDefaultAsyncDebouncerState<\n TFn extends AnyAsyncFunction,\n>(): AsyncDebouncerState<TFn> {\n return {\n canLeadingExecute: true,\n errorCount: 0,\n isExecuting: false,\n isPending: false,\n lastArgs: undefined,\n lastResult: undefined,\n maybeExecuteCount: 0,\n settleCount: 0,\n status: 'idle',\n successCount: 0,\n }\n}\n\n/**\n * Options for configuring an async debounced function\n */\nexport interface AsyncDebouncerOptions<TFn extends AnyAsyncFunction> {\n /**\n * Options for configuring the underlying async retryer\n */\n asyncRetryerOptions?: AsyncRetryerOptions<TFn>\n /**\n * Whether the debouncer is enabled. When disabled, maybeExecute will not trigger any executions.\n * Can be a boolean or a function that returns a boolean.\n * Defaults to true.\n */\n enabled?: boolean | ((debouncer: AsyncDebouncer<TFn>) => boolean)\n /**\n * Initial state for the async debouncer\n */\n initialState?: Partial<AsyncDebouncerState<TFn>>\n /**\n * Optional key to identify this async debouncer instance.\n * If provided, the async debouncer will be identified by this key in the devtools and PacerProvider if applicable.\n */\n key?: string\n /**\n * Whether to execute on the leading edge of the timeout.\n * Defaults to false.\n */\n leading?: boolean\n /**\n * Optional error handler for when the debounced function throws.\n * If provided, the handler will be called with the error and debouncer instance.\n * This can be used alongside throwOnError - the handler will be called before any error is thrown.\n */\n onError?: (\n error: Error,\n args: Parameters<TFn>,\n debouncer: AsyncDebouncer<TFn>,\n ) => void\n /**\n * Optional callback to call when the debounced function is executed\n */\n onSettled?: (args: Parameters<TFn>, debouncer: AsyncDebouncer<TFn>) => void\n /**\n * Optional callback to call when the debounced function is executed\n */\n onSuccess?: (\n result: ReturnType<TFn>,\n args: Parameters<TFn>,\n debouncer: AsyncDebouncer<TFn>,\n ) => void\n /**\n * Whether to throw errors when they occur.\n * Defaults to true if no onError handler is provided, false if an onError handler is provided.\n * Can be explicitly set to override these defaults.\n */\n throwOnError?: boolean\n /**\n * Whether to execute on the trailing edge of the timeout.\n * Defaults to true.\n */\n trailing?: boolean\n /**\n * Delay in milliseconds to wait after the last call before executing.\n * Can be a number or a function that returns a number.\n * Defaults to 0ms\n */\n wait: number | ((debouncer: AsyncDebouncer<TFn>) => number)\n}\n\n/**\n * Utility function for sharing common `AsyncDebouncerOptions` options between different `AsyncDebouncer` instances.\n */\nexport function asyncDebouncerOptions<\n TFn extends AnyAsyncFunction = AnyAsyncFunction,\n TOptions extends Partial<AsyncDebouncerOptions<TFn>> = Partial<\n AsyncDebouncerOptions<TFn>\n >,\n>(options: TOptions): TOptions {\n return options\n}\n\ntype AsyncDebouncerOptionsWithOptionalCallbacks = OptionalKeys<\n AsyncDebouncerOptions<any>,\n 'initialState' | 'onError' | 'onSettled' | 'onSuccess' | 'key'\n>\n\nconst defaultOptions: AsyncDebouncerOptionsWithOptionalCallbacks = {\n asyncRetryerOptions: {\n maxAttempts: 1,\n },\n enabled: true,\n leading: false,\n trailing: true,\n wait: 0,\n}\n\n/**\n * A class that creates an async debounced function.\n *\n * Async vs Sync Versions:\n * The async version provides advanced features over the sync Debouncer:\n * - Returns promises that can be awaited for debounced function results\n * - Built-in retry support via AsyncRetryer integration\n * - Abort support to cancel in-flight executions\n * - Cancel support to prevent pending executions from starting\n * - Comprehensive error handling with onError callbacks and throwOnError control\n * - Detailed execution tracking (success/error/settle counts)\n *\n * The sync Debouncer is lighter weight and simpler when you don't need async features,\n * return values, or execution control.\n *\n * What is Debouncing?\n * Debouncing ensures that a function is only executed after a specified delay has passed since its last invocation.\n * Each new invocation resets the delay timer. This is useful for handling frequent events like window resizing\n * or input changes where you only want to execute the handler after the events have stopped occurring.\n *\n * Unlike throttling which allows execution at regular intervals, debouncing prevents any execution until\n * the function stops being called for the specified delay period.\n *\n * Error Handling:\n * - If an `onError` handler is provided, it will be called with the error and debouncer instance\n * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown\n * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed\n * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown\n * - The error state can be checked using the underlying store\n *\n * State Management:\n * - The debouncer uses a reactive store for state management\n * - Use `initialState` to provide initial state values when creating the async debouncer\n * - The state includes canLeadingExecute, error count, execution status, and success/settle counts\n * - State can be accessed via the `store` property and its `state` getter\n * - The store is reactive and will notify subscribers of state changes\n *\n * @example\n * ```ts\n * const asyncDebouncer = new AsyncDebouncer(async (value: string) => {\n * const results = await searchAPI(value);\n * return results; // Return value is preserved\n * }, {\n * wait: 500,\n * onError: (error) => {\n * console.error('Search failed:', error);\n * }\n * });\n *\n * // Called on each keystroke but only executes after 500ms of no typing\n * // Returns the API response directly\n * const results = await asyncDebouncer.maybeExecute(inputElement.value);\n * ```\n */\nexport class AsyncDebouncer<TFn extends AnyAsyncFunction> {\n readonly store: Store<Readonly<AsyncDebouncerState<TFn>>> = new Store<\n AsyncDebouncerState<TFn>\n >(getDefaultAsyncDebouncerState<TFn>())\n key: string | undefined\n options: AsyncDebouncerOptions<TFn>\n asyncRetryers = new Map<number, AsyncRetryer<TFn>>()\n #timeoutId: NodeJS.Timeout | null = null\n #resolvePreviousPromise:\n | ((value?: ReturnType<TFn> | undefined) => void)\n | null = null\n\n constructor(\n public fn: TFn,\n initialOptions: AsyncDebouncerOptions<TFn>,\n ) {\n this.key = initialOptions.key\n this.options = {\n ...defaultOptions,\n ...initialOptions,\n throwOnError: initialOptions.throwOnError ?? !initialOptions.onError,\n }\n this.#setState(this.options.initialState ?? {})\n\n pacerEventClient.on('d-AsyncDebouncer', (event) => {\n if (event.payload.key !== this.key) return\n this.#setState(event.payload.store.state as AsyncDebouncerState<TFn>)\n this.setOptions(event.payload.options)\n })\n }\n\n /**\n * Updates the async debouncer options\n */\n setOptions = (newOptions: Partial<AsyncDebouncerOptions<TFn>>): void => {\n this.options = { ...this.options, ...newOptions }\n\n // Cancel pending execution if the debouncer is disabled\n if (!this.#getEnabled()) {\n this.cancel()\n }\n }\n\n #setState = (newState: Partial<AsyncDebouncerState<TFn>>): void => {\n this.store.setState((state) => {\n const combinedState = {\n ...state,\n ...newState,\n }\n const { isPending, isExecuting, settleCount } = combinedState\n return {\n ...combinedState,\n status: !this.#getEnabled()\n ? 'disabled'\n : isPending\n ? 'pending'\n : isExecuting\n ? 'executing'\n : settleCount > 0\n ? 'settled'\n : 'idle',\n }\n })\n emitChange('AsyncDebouncer', this)\n }\n\n /**\n * Returns the current debouncer enabled state\n */\n #getEnabled = (): boolean => {\n return !!parseFunctionOrValue(this.options.enabled, this)\n }\n\n /**\n * Returns the current debouncer wait state\n */\n #getWait = (): number => {\n return parseFunctionOrValue(this.options.wait, this)\n }\n\n /**\n * Attempts to execute the debounced function.\n * If a call is already in progress, it will be queued.\n *\n * Error Handling:\n * - If the debounced function throws and no `onError` handler is configured,\n * the error will be thrown from this method.\n * - If an `onError` handler is configured, errors will be caught and passed to the handler,\n * and this method will return undefined.\n * - The error state can be checked using `getErrorCount()` and `getIsExecuting()`.\n *\n * @returns A promise that resolves with the function's return value, or undefined if an error occurred and was handled by onError\n * @throws The error from the debounced function if no onError handler is configured\n */\n maybeExecute = async (\n ...args: Parameters<TFn>\n ): Promise<ReturnType<TFn> | undefined> => {\n if (!this.#getEnabled()) return undefined\n this.#cancelPendingExecution()\n this.#setState({\n lastArgs: args,\n maybeExecuteCount: this.store.state.maybeExecuteCount + 1,\n })\n\n // Handle leading execution\n if (this.options.leading && this.store.state.canLeadingExecute) {\n this.#setState({ canLeadingExecute: false })\n await this.#execute(...args)\n return this.store.state.lastResult\n }\n\n // Handle trailing execution\n if (this.options.trailing && this.#getEnabled()) {\n this.#setState({ isPending: true })\n }\n\n return new Promise((resolve, reject) => {\n this.#resolvePreviousPromise = resolve\n // this.#rejectPreviousPromise = reject\n this.#timeoutId = setTimeout(async () => {\n // Execute trailing if enabled\n if (this.options.trailing && this.store.state.lastArgs) {\n try {\n await this.#execute(...this.store.state.lastArgs)\n } catch (error) {\n reject(error)\n }\n }\n\n // Reset state and resolve\n this.#setState({ canLeadingExecute: true })\n this.#resolvePreviousPromise = null\n resolve(this.store.state.lastResult)\n }, this.#getWait())\n })\n }\n\n #execute = async (\n ...args: Parameters<TFn>\n ): Promise<ReturnType<TFn> | undefined> => {\n if (!this.#getEnabled()) return undefined\n const currentMaybeExecuteCount = this.store.state.maybeExecuteCount + 1\n\n try {\n this.#setState({ isExecuting: true })\n const currentAsyncRetryer = new AsyncRetryer(this.fn, {\n ...this.options.asyncRetryerOptions,\n key: `${this.key}-retryer-${currentMaybeExecuteCount}`,\n })\n this.asyncRetryers.set(currentMaybeExecuteCount, currentAsyncRetryer)\n const result = await currentAsyncRetryer.execute(...args) // EXECUTE!\n this.#setState({\n lastResult: result,\n successCount: this.store.state.successCount + 1,\n })\n this.options.onSuccess?.(result as ReturnType<TFn>, args, this)\n } catch (error) {\n this.#setState({\n errorCount: this.store.state.errorCount + 1,\n })\n this.options.onError?.(error as Error, args, this)\n if (this.options.throwOnError) {\n throw error\n }\n } finally {\n this.asyncRetryers.delete(currentMaybeExecuteCount) // dispose retryer\n this.#setState({\n isExecuting: false,\n isPending: false,\n lastArgs: undefined,\n settleCount: this.store.state.settleCount + 1,\n })\n this.options.onSettled?.(args, this)\n }\n return this.store.state.lastResult\n }\n\n /**\n * Processes the current pending execution immediately\n */\n flush = async (): Promise<ReturnType<TFn> | undefined> => {\n if (this.store.state.isPending && this.store.state.lastArgs) {\n const { lastArgs } = this.store.state\n this.#cancelPendingExecution()\n return await this.#execute(...lastArgs)\n }\n return undefined\n }\n\n #resolvePreviousPromiseInternal = (): void => {\n if (this.#resolvePreviousPromise) {\n this.#resolvePreviousPromise(this.store.state.lastResult)\n this.#resolvePreviousPromise = null\n }\n }\n\n #clearTimeout = (): void => {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId)\n this.#timeoutId = null\n }\n }\n\n /**\n * Internal cancel without resetting the leading execute state\n */\n #cancelPendingExecution = (): void => {\n this.#clearTimeout()\n this.#resolvePreviousPromiseInternal()\n this.#setState({\n isPending: false,\n lastArgs: undefined,\n })\n }\n\n /**\n * Returns the AbortSignal for a specific execution.\n * If no maybeExecuteCount is provided, returns the signal for the most recent execution.\n * Returns null if no execution is found or not currently executing.\n *\n * @param maybeExecuteCount - Optional specific execution to get signal for\n * @example\n * ```typescript\n * const debouncer = new AsyncDebouncer(\n * async (searchTerm: string) => {\n * const signal = debouncer.getAbortSignal()\n * if (signal) {\n * const response = await fetch(`/api/search?q=${searchTerm}`, { signal })\n * return response.json()\n * }\n * },\n * { wait: 300 }\n * )\n * ```\n */\n getAbortSignal(maybeExecuteCount?: number): AbortSignal | null {\n const count = maybeExecuteCount ?? this.store.state.maybeExecuteCount\n const retryer = this.asyncRetryers.get(count)\n return retryer?.getAbortSignal() ?? null\n }\n\n /**\n * Aborts all ongoing executions with the internal abort controllers.\n * Does NOT cancel any pending execution that have not started yet.\n */\n abort = (): void => {\n this.asyncRetryers.forEach((retryer) => retryer.abort())\n this.asyncRetryers.clear()\n this.#setState({\n isExecuting: false,\n })\n }\n\n /**\n * Cancels any pending execution that have not started yet.\n * Does NOT abort any execution already in progress.\n */\n cancel = (): void => {\n this.#cancelPendingExecution()\n this.#setState({ canLeadingExecute: true })\n }\n\n /**\n * Resets the debouncer state to its default values\n */\n reset = (): void => {\n this.#setState(getDefaultAsyncDebouncerState<TFn>())\n this.asyncRetryers.forEach((retryer) => retryer.reset())\n }\n}\n\n/**\n * Creates an async debounced function that delays execution until after a specified wait time.\n * The debounced function will only execute once the wait period has elapsed without any new calls.\n * If called again during the wait period, the timer resets and a new wait period begins.\n *\n * Async vs Sync Versions:\n * The async version provides advanced features over the sync debounce function:\n * - Returns promises that can be awaited for debounced function results\n * - Built-in retry support via AsyncRetryer integration\n * - Abort support to cancel in-flight executions\n * - Cancel support to prevent pending executions from starting\n * - Comprehensive error handling with onError callbacks and throwOnError control\n * - Detailed execution tracking (success/error/settle counts)\n *\n * The sync debounce function is lighter weight and simpler when you don't need async features,\n * return values, or execution control.\n *\n * What is Debouncing?\n * Debouncing ensures that a function is only executed after a specified delay has passed since its last invocation.\n * Each new invocation resets the delay timer. This is useful for handling frequent events like window resizing\n * or input changes where you only want to execute the handler after the events have stopped occurring.\n *\n * Configuration Options:\n * - `wait`: Delay in milliseconds to wait after the last call (required)\n * - `leading`: Execute on the leading edge of the timeout (default: false)\n * - `trailing`: Execute on the trailing edge of the timeout (default: true)\n * - `enabled`: Whether the debouncer is enabled (default: true)\n * - `asyncRetryerOptions`: Configure retry behavior for executions\n *\n * Error Handling:\n * - If an `onError` handler is provided, it will be called with the error and debouncer instance\n * - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown\n * - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed\n * - The error state can be checked using the underlying AsyncDebouncer instance\n * - Both onError and throwOnError can be used together - the handler will be called before any error is thrown\n *\n * State Management:\n * - Uses TanStack Store for reactive state management\n * - Use `initialState` to provide initial state values when creating the async debouncer\n * - Use `onSuccess` callback to react to successful function execution and implement custom logic\n * - Use `onError` callback to react to function execution errors and implement custom error handling\n * - Use `onSettled` callback to react to function execution completion (success or error) and implement custom logic\n * - The state includes canLeadingExecute, error count, execution status, and success/settle counts\n * - State can be accessed via `asyncDebouncer.store.state` when using the class directly\n * - When using framework adapters (React/Solid), state is accessed from `asyncDebouncer.state`\n *\n * @example\n * ```ts\n * const debounced = asyncDebounce(async (value: string) => {\n * const result = await saveToAPI(value);\n * return result; // Return value is preserved\n * }, {\n * wait: 1000,\n * onError: (error) => {\n * console.error('API call failed:', error);\n * },\n * throwOnError: true // Will both log the error and throw it\n * });\n *\n * // Will only execute once, 1 second after the last call\n * // Returns the API response directly\n * const result = await debounced(\"third\");\n * ```\n */\nexport function asyncDebounce<TFn extends AnyAsyncFunction>(\n fn: TFn,\n initialOptions: AsyncDebouncerOptions<TFn>,\n) {\n const asyncDebouncer = new AsyncDebouncer(fn, initialOptions)\n return asyncDebouncer.maybeExecute\n}\n"],"names":["Store","emitChange","parseFunctionOrValue","AsyncRetryer","pacerEventClient"],"mappings":"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"}