@tanstack/pacer-lite 0.2.1 → 0.3.0

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 (41) hide show
  1. package/README.md +29 -14
  2. package/dist/lite-batcher.d.ts +4 -6
  3. package/dist/lite-batcher.js +72 -45
  4. package/dist/lite-debouncer.d.ts +5 -9
  5. package/dist/lite-debouncer.js +58 -40
  6. package/dist/lite-queuer.d.ts +5 -7
  7. package/dist/lite-queuer.js +170 -89
  8. package/dist/lite-rate-limiter.d.ts +5 -9
  9. package/dist/lite-rate-limiter.js +89 -63
  10. package/dist/lite-throttler.d.ts +5 -9
  11. package/dist/lite-throttler.js +63 -40
  12. package/dist/pacer/dist/types.d.ts +7 -0
  13. package/package.json +13 -33
  14. package/dist/index.cjs +0 -16
  15. package/dist/index.d.cts +0 -6
  16. package/dist/lite-batcher.cjs +0 -175
  17. package/dist/lite-batcher.cjs.map +0 -1
  18. package/dist/lite-batcher.d.cts +0 -184
  19. package/dist/lite-batcher.js.map +0 -1
  20. package/dist/lite-debouncer.cjs +0 -125
  21. package/dist/lite-debouncer.cjs.map +0 -1
  22. package/dist/lite-debouncer.d.cts +0 -127
  23. package/dist/lite-debouncer.js.map +0 -1
  24. package/dist/lite-queuer.cjs +0 -208
  25. package/dist/lite-queuer.cjs.map +0 -1
  26. package/dist/lite-queuer.d.cts +0 -243
  27. package/dist/lite-queuer.js.map +0 -1
  28. package/dist/lite-rate-limiter.cjs +0 -149
  29. package/dist/lite-rate-limiter.cjs.map +0 -1
  30. package/dist/lite-rate-limiter.d.cts +0 -149
  31. package/dist/lite-rate-limiter.js.map +0 -1
  32. package/dist/lite-throttler.cjs +0 -127
  33. package/dist/lite-throttler.cjs.map +0 -1
  34. package/dist/lite-throttler.d.cts +0 -134
  35. package/dist/lite-throttler.js.map +0 -1
  36. package/src/index.ts +0 -5
  37. package/src/lite-batcher.ts +0 -267
  38. package/src/lite-debouncer.ts +0 -184
  39. package/src/lite-queuer.ts +0 -434
  40. package/src/lite-rate-limiter.ts +0 -246
  41. package/src/lite-throttler.ts +0 -195
package/README.md CHANGED
@@ -1,5 +1,19 @@
1
1
  <div align="center">
2
- <img src="./media/header_pacer.png" >
2
+ <picture>
3
+ <source
4
+ media="(prefers-color-scheme: dark)"
5
+ srcset="https://tanstack.com/api/readme/pacer.png?theme=dark"
6
+ />
7
+ <source
8
+ media="(prefers-color-scheme: light)"
9
+ srcset="https://tanstack.com/api/readme/pacer.png"
10
+ />
11
+ <img
12
+ src="https://tanstack.com/api/readme/pacer.png"
13
+ alt="TanStack Pacer"
14
+ width="900"
15
+ />
16
+ </picture>
3
17
  </div>
4
18
 
5
19
  <br />
@@ -29,8 +43,9 @@
29
43
  </div>
30
44
 
31
45
  <div align="center">
32
-
46
+
33
47
  ### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)
48
+
34
49
  </div>
35
50
 
36
51
  # TanStack Pacer
@@ -86,12 +101,12 @@ A lightweight timing and scheduling library for debouncing, throttling, rate lim
86
101
  <br />
87
102
 
88
103
  > [!NOTE]
89
- > You may know **TanSack Pacer** by our adapter names, too!
104
+ > You may know **TanStack Pacer** by our adapter names, too!
90
105
  >
91
- > - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react/react-pacer)
92
- > - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact/preact-pacer)
93
- > - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid/solid-pacer)
94
- > - Angular Pacer - needs a contributor!
106
+ > - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react)
107
+ > - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact)
108
+ > - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid)
109
+ > - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular)
95
110
  > - Svelte Pacer - needs a contributor!
96
111
  > - Vue Pacer - needs a contributor!
97
112
 
@@ -106,21 +121,21 @@ A lightweight timing and scheduling library for debouncing, throttling, rate lim
106
121
 
107
122
  <table align="center">
108
123
  <tr>
109
- <td>
124
+ <td>
110
125
  <a href="https://www.coderabbit.ai/?via=tanstack&dub_id=aCcEEdAOqqutX6OS" >
111
126
  <picture>
112
- <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/coderabbit-dark-CMcuvjEy.svg" height="40" />
113
- <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/coderabbit-light-DVMJ2jHi.svg" height="40" />
114
- <img src="https://tanstack.com/assets/coderabbit-light-DVMJ2jHi.svg" height="40" alt="CodeRabbit" />
127
+ <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/coderabbit-dark-D643Zkrv.svg" />
128
+ <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" />
129
+ <img src="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" height="40" alt="CodeRabbit" />
115
130
  </picture>
116
131
  </a>
117
132
  </td>
118
133
  <td>
119
134
  <a href="https://www.cloudflare.com?utm_source=tanstack">
120
135
  <picture>
121
- <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/cloudflare-white-DQDB7UaL.svg" height="60" />
122
- <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/cloudflare-black-CPufaW0B.svg" height="60" />
123
- <img src="https://tanstack.com/assets/cloudflare-black-CPufaW0B.svg" height="60" alt="Cloudflare" />
136
+ <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" />
137
+ <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/cloudflare-black-6Ojsn8yh.svg" />
138
+ <img src="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" height="60" alt="Cloudflare" />
124
139
  </picture>
125
140
  </a>
126
141
  </td>
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Options for configuring a lite batcher instance
4
4
  */
5
- interface LiteBatcherOptions<TValue> {
5
+ export interface LiteBatcherOptions<TValue> {
6
6
  /**
7
7
  * Custom function to determine if a batch should be processed
8
8
  * Return true to process the batch immediately
@@ -103,7 +103,7 @@ interface LiteBatcherOptions<TValue> {
103
103
  * batcher.addItem({ name: 'urgent', urgent: true }); // Triggers immediate processing
104
104
  * ```
105
105
  */
106
- declare class LiteBatcher<TValue> {
106
+ export declare class LiteBatcher<TValue> {
107
107
  fn: (items: Array<TValue>) => void;
108
108
  options: LiteBatcherOptions<TValue>;
109
109
  private items;
@@ -178,7 +178,5 @@ declare class LiteBatcher<TValue> {
178
178
  * batchItems(3); // Triggers batch processing
179
179
  * ```
180
180
  */
181
- declare function liteBatch<TValue>(fn: (items: Array<TValue>) => void, options?: LiteBatcherOptions<TValue>): (item: TValue) => void;
182
- //#endregion
183
- export { LiteBatcher, LiteBatcherOptions, liteBatch };
184
- //# sourceMappingURL=lite-batcher.d.ts.map
181
+ export declare function liteBatch<TValue>(fn: (items: Array<TValue>) => void, options?: LiteBatcherOptions<TValue>): (item: TValue) => void;
182
+ //#endregion
@@ -69,52 +69,14 @@
69
69
  * ```
70
70
  */
71
71
  var LiteBatcher = class {
72
+ fn;
73
+ options;
74
+ items = [];
75
+ timeoutId = null;
76
+ _isPending = false;
72
77
  constructor(fn, options = {}) {
73
78
  this.fn = fn;
74
79
  this.options = options;
75
- this.items = [];
76
- this.timeoutId = null;
77
- this._isPending = false;
78
- this.addItem = (item) => {
79
- this.items.push(item);
80
- this._isPending = this.options.wait !== Infinity;
81
- this.options.onItemsChange?.(this);
82
- if (this.items.length >= this.options.maxSize || this.options.getShouldExecute(this.items, this)) this.execute();
83
- else if (this.options.wait !== Infinity) {
84
- this.clearTimeout();
85
- this.timeoutId = setTimeout(() => this.execute(), this.getWait());
86
- }
87
- };
88
- this.execute = () => {
89
- if (this.items.length === 0) return;
90
- const batch = this.peekAllItems();
91
- this.clear();
92
- this.fn(batch);
93
- this.options.onExecute?.(batch, this);
94
- };
95
- this.flush = () => {
96
- this.clearTimeout();
97
- this.execute();
98
- };
99
- this.peekAllItems = () => {
100
- return [...this.items];
101
- };
102
- this.clearTimeout = () => {
103
- if (this.timeoutId) {
104
- clearTimeout(this.timeoutId);
105
- this.timeoutId = null;
106
- }
107
- };
108
- this.clear = () => {
109
- const hadItems = this.items.length > 0;
110
- this.items = [];
111
- this._isPending = false;
112
- if (hadItems) this.options.onItemsChange?.(this);
113
- };
114
- this.cancel = () => {
115
- this.clearTimeout();
116
- this._isPending = false;
117
- };
118
80
  this.options.maxSize = this.options.maxSize ?? Infinity;
119
81
  this.options.started = this.options.started ?? true;
120
82
  this.options.wait = this.options.wait ?? Infinity;
@@ -142,6 +104,72 @@ var LiteBatcher = class {
142
104
  if (typeof this.options.wait === "function") return this.options.wait(this);
143
105
  return this.options.wait;
144
106
  }
107
+ /**
108
+ * Adds an item to the batcher
109
+ * If the batch size is reached, timeout occurs, or getShouldExecute returns true, the batch will be processed
110
+ */
111
+ addItem = (item) => {
112
+ this.items.push(item);
113
+ this._isPending = this.options.wait !== Infinity;
114
+ this.options.onItemsChange?.(this);
115
+ if (this.items.length >= this.options.maxSize || this.options.getShouldExecute(this.items, this)) this.execute();
116
+ else if (this.options.wait !== Infinity) {
117
+ this.clearTimeout();
118
+ this.timeoutId = setTimeout(() => this.execute(), this.getWait());
119
+ }
120
+ };
121
+ /**
122
+ * Processes the current batch of items.
123
+ * This method will automatically be triggered if the batcher is running and any of these conditions are met:
124
+ * - The number of items reaches maxSize
125
+ * - The wait duration has elapsed
126
+ * - The getShouldExecute function returns true upon adding an item
127
+ *
128
+ * You can also call this method manually to process the current batch at any time.
129
+ */
130
+ execute = () => {
131
+ if (this.items.length === 0) return;
132
+ const batch = this.peekAllItems();
133
+ this.clear();
134
+ this.fn(batch);
135
+ this.options.onExecute?.(batch, this);
136
+ };
137
+ /**
138
+ * Processes the current batch of items immediately
139
+ */
140
+ flush = () => {
141
+ this.clearTimeout();
142
+ this.execute();
143
+ };
144
+ /**
145
+ * Returns a copy of all items in the batcher
146
+ */
147
+ peekAllItems = () => {
148
+ return [...this.items];
149
+ };
150
+ clearTimeout = () => {
151
+ if (this.timeoutId) {
152
+ clearTimeout(this.timeoutId);
153
+ this.timeoutId = null;
154
+ }
155
+ };
156
+ /**
157
+ * Removes all items from the batcher
158
+ */
159
+ clear = () => {
160
+ const hadItems = this.items.length > 0;
161
+ this.items = [];
162
+ this._isPending = false;
163
+ if (hadItems) this.options.onItemsChange?.(this);
164
+ };
165
+ /**
166
+ * Cancels any pending execution that was scheduled.
167
+ * Does NOT clear out the items.
168
+ */
169
+ cancel = () => {
170
+ this.clearTimeout();
171
+ this._isPending = false;
172
+ };
145
173
  };
146
174
  /**
147
175
  * Creates a batcher that processes items in batches.
@@ -169,5 +197,4 @@ function liteBatch(fn, options = {}) {
169
197
  }
170
198
 
171
199
  //#endregion
172
- export { LiteBatcher, liteBatch };
173
- //# sourceMappingURL=lite-batcher.js.map
200
+ export { LiteBatcher, liteBatch };
@@ -1,11 +1,9 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
2
-
1
+ import { AnyFunction } from "./pacer/dist/types.js";
3
2
  //#region src/lite-debouncer.d.ts
4
-
5
3
  /**
6
4
  * Options for configuring a lite debounced function
7
5
  */
8
- interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {
6
+ export interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {
9
7
  /**
10
8
  * Whether to execute on the leading edge of the timeout.
11
9
  * The first call will execute immediately and the rest will wait the delay.
@@ -66,7 +64,7 @@ interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {
66
64
  * });
67
65
  * ```
68
66
  */
69
- declare class LiteDebouncer<TFn extends AnyFunction> {
67
+ export declare class LiteDebouncer<TFn extends AnyFunction> {
70
68
  fn: TFn;
71
69
  options: LiteDebouncerOptions<TFn>;
72
70
  private timeoutId;
@@ -121,7 +119,5 @@ declare class LiteDebouncer<TFn extends AnyFunction> {
121
119
  * }, { wait: 300, leading: true });
122
120
  * ```
123
121
  */
124
- declare function liteDebounce<TFn extends AnyFunction>(fn: TFn, options: LiteDebouncerOptions<TFn>): (...args: Parameters<TFn>) => void;
125
- //#endregion
126
- export { LiteDebouncer, LiteDebouncerOptions, liteDebounce };
127
- //# sourceMappingURL=lite-debouncer.d.ts.map
122
+ export declare function liteDebounce<TFn extends AnyFunction>(fn: TFn, options: LiteDebouncerOptions<TFn>): (...args: Parameters<TFn>) => void;
123
+ //#endregion
@@ -40,50 +40,69 @@
40
40
  * ```
41
41
  */
42
42
  var LiteDebouncer = class {
43
+ fn;
44
+ options;
45
+ timeoutId;
46
+ lastArgs;
47
+ canLeadingExecute = true;
43
48
  constructor(fn, options) {
44
49
  this.fn = fn;
45
50
  this.options = options;
46
- this.canLeadingExecute = true;
47
- this.maybeExecute = (...args) => {
48
- let didLeadingExecute = false;
49
- if (this.options.leading && this.canLeadingExecute) {
50
- this.canLeadingExecute = false;
51
- didLeadingExecute = true;
52
- this.fn(...args);
53
- this.options.onExecute?.(args, this);
54
- }
55
- this.lastArgs = args;
56
- if (this.timeoutId) clearTimeout(this.timeoutId);
57
- this.timeoutId = setTimeout(() => {
58
- this.canLeadingExecute = true;
59
- if (this.options.trailing && !didLeadingExecute && this.lastArgs) {
60
- this.fn(...this.lastArgs);
61
- this.options.onExecute?.(this.lastArgs, this);
62
- }
63
- this.lastArgs = void 0;
64
- }, this.options.wait);
65
- };
66
- this.flush = () => {
67
- if (this.timeoutId && this.lastArgs) {
68
- clearTimeout(this.timeoutId);
69
- this.timeoutId = void 0;
70
- const args = this.lastArgs;
71
- this.fn(...args);
72
- this.options.onExecute?.(args, this);
73
- this.lastArgs = void 0;
74
- this.canLeadingExecute = true;
75
- }
76
- };
77
- this.cancel = () => {
78
- if (this.timeoutId) {
79
- clearTimeout(this.timeoutId);
80
- this.timeoutId = void 0;
51
+ if (this.options.leading === void 0 && this.options.trailing === void 0) this.options.trailing = true;
52
+ }
53
+ /**
54
+ * Attempts to execute the debounced function.
55
+ * If leading is true and this is the first call, executes immediately.
56
+ * Otherwise, queues the execution for after the wait time.
57
+ * Each new call resets the timer.
58
+ */
59
+ maybeExecute = (...args) => {
60
+ let didLeadingExecute = false;
61
+ if (this.options.leading && this.canLeadingExecute) {
62
+ this.canLeadingExecute = false;
63
+ didLeadingExecute = true;
64
+ this.fn(...args);
65
+ this.options.onExecute?.(args, this);
66
+ }
67
+ this.lastArgs = args;
68
+ if (this.timeoutId) clearTimeout(this.timeoutId);
69
+ this.timeoutId = setTimeout(() => {
70
+ this.canLeadingExecute = true;
71
+ if (this.options.trailing && !didLeadingExecute && this.lastArgs) {
72
+ this.fn(...this.lastArgs);
73
+ this.options.onExecute?.(this.lastArgs, this);
81
74
  }
82
75
  this.lastArgs = void 0;
76
+ }, this.options.wait);
77
+ };
78
+ /**
79
+ * Processes the current pending execution immediately.
80
+ * If there's a pending execution, it will be executed right away
81
+ * and the timeout will be cleared.
82
+ */
83
+ flush = () => {
84
+ if (this.timeoutId && this.lastArgs) {
85
+ clearTimeout(this.timeoutId);
86
+ this.timeoutId = void 0;
87
+ const args = this.lastArgs;
88
+ this.fn(...args);
89
+ this.options.onExecute?.(args, this);
90
+ this.lastArgs = void 0;
83
91
  this.canLeadingExecute = true;
84
- };
85
- if (this.options.leading === void 0 && this.options.trailing === void 0) this.options.trailing = true;
86
- }
92
+ }
93
+ };
94
+ /**
95
+ * Cancels any pending execution.
96
+ * Clears the timeout and resets the internal state.
97
+ */
98
+ cancel = () => {
99
+ if (this.timeoutId) {
100
+ clearTimeout(this.timeoutId);
101
+ this.timeoutId = void 0;
102
+ }
103
+ this.lastArgs = void 0;
104
+ this.canLeadingExecute = true;
105
+ };
87
106
  };
88
107
  /**
89
108
  * Creates a lightweight debounced function that delays invoking the provided function until after a specified wait time.
@@ -119,5 +138,4 @@ function liteDebounce(fn, options) {
119
138
  }
120
139
 
121
140
  //#endregion
122
- export { LiteDebouncer, liteDebounce };
123
- //# sourceMappingURL=lite-debouncer.js.map
141
+ export { LiteDebouncer, liteDebounce };
@@ -5,11 +5,11 @@
5
5
  * - 'front': Operate on the front of the queue (FIFO for getNextItem)
6
6
  * - 'back': Operate on the back of the queue (LIFO for getNextItem)
7
7
  */
8
- type QueuePosition = 'front' | 'back';
8
+ export type QueuePosition = 'front' | 'back';
9
9
  /**
10
10
  * Options for configuring a lite queuer instance
11
11
  */
12
- interface LiteQueuerOptions<TValue> {
12
+ export interface LiteQueuerOptions<TValue> {
13
13
  /**
14
14
  * Default position to add items to the queue
15
15
  * @default 'back'
@@ -105,7 +105,7 @@ interface LiteQueuerOptions<TValue> {
105
105
  * // Processes high priority task first
106
106
  * ```
107
107
  */
108
- declare class LiteQueuer<TValue> {
108
+ export declare class LiteQueuer<TValue> {
109
109
  fn: (item: TValue) => void;
110
110
  options: LiteQueuerOptions<TValue>;
111
111
  private items;
@@ -237,7 +237,5 @@ declare class LiteQueuer<TValue> {
237
237
  * // Processes each item with 1 second delay between them
238
238
  * ```
239
239
  */
240
- declare function liteQueue<TValue>(fn: (item: TValue) => void, options?: LiteQueuerOptions<TValue>): (item: TValue) => boolean;
241
- //#endregion
242
- export { LiteQueuer, LiteQueuerOptions, QueuePosition, liteQueue };
243
- //# sourceMappingURL=lite-queuer.d.ts.map
240
+ export declare function liteQueue<TValue>(fn: (item: TValue) => void, options?: LiteQueuerOptions<TValue>): (item: TValue) => boolean;
241
+ //#endregion