@tanstack/pacer-lite 0.2.0 → 0.2.2

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
@@ -86,12 +86,12 @@ A lightweight timing and scheduling library for debouncing, throttling, rate lim
86
86
  <br />
87
87
 
88
88
  > [!NOTE]
89
- > You may know **TanSack Pacer** by our adapter names, too!
89
+ > You may know **TanStack Pacer** by our adapter names, too!
90
90
  >
91
91
  > - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react/react-pacer)
92
92
  > - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact/preact-pacer)
93
93
  > - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid/solid-pacer)
94
- > - Angular Pacer - needs a contributor!
94
+ > - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular/angular-pacer)
95
95
  > - Svelte Pacer - needs a contributor!
96
96
  > - Vue Pacer - needs a contributor!
97
97
 
@@ -106,21 +106,21 @@ A lightweight timing and scheduling library for debouncing, throttling, rate lim
106
106
 
107
107
  <table align="center">
108
108
  <tr>
109
- <td>
109
+ <td>
110
110
  <a href="https://www.coderabbit.ai/?via=tanstack&dub_id=aCcEEdAOqqutX6OS" >
111
111
  <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" />
112
+ <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/coderabbit-dark-D643Zkrv.svg" />
113
+ <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" />
114
+ <img src="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" height="40" alt="CodeRabbit" />
115
115
  </picture>
116
116
  </a>
117
117
  </td>
118
118
  <td>
119
119
  <a href="https://www.cloudflare.com?utm_source=tanstack">
120
120
  <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" />
121
+ <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" />
122
+ <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/cloudflare-black-6Ojsn8yh.svg" />
123
+ <img src="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" height="60" alt="Cloudflare" />
124
124
  </picture>
125
125
  </a>
126
126
  </td>
package/dist/index.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
  const require_lite_debouncer = require('./lite-debouncer.cjs');
2
3
  const require_lite_throttler = require('./lite-throttler.cjs');
3
4
  const require_lite_rate_limiter = require('./lite-rate-limiter.cjs');
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/lite-batcher.ts
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lite-batcher.cjs","names":["fn: (items: Array<TValue>) => void","options: LiteBatcherOptions<TValue>"],"sources":["../src/lite-batcher.ts"],"sourcesContent":["/**\n * Options for configuring a lite batcher instance\n */\nexport interface LiteBatcherOptions<TValue> {\n /**\n * Custom function to determine if a batch should be processed\n * Return true to process the batch immediately\n */\n getShouldExecute?: (\n items: Array<TValue>,\n batcher: LiteBatcher<TValue>,\n ) => boolean\n /**\n * Maximum number of items in a batch\n * @default Infinity\n */\n maxSize?: number\n /**\n * Callback fired after a batch is processed\n */\n onExecute?: (batch: Array<TValue>, batcher: LiteBatcher<TValue>) => void\n /**\n * Callback fired after items are added to the batcher\n */\n onItemsChange?: (batcher: LiteBatcher<TValue>) => void\n /**\n * Whether the batcher should start processing immediately\n * @default true\n */\n started?: boolean\n /**\n * Maximum time in milliseconds to wait before processing a batch.\n * If the wait duration has elapsed, the batch will be processed.\n * If not provided, the batch will not be triggered by a timeout.\n * @default Infinity\n */\n wait?: number | ((batcher: LiteBatcher<TValue>) => number)\n}\n\n/**\n * A lightweight class that collects items and processes them in batches.\n *\n * This is an alternative to the Batcher in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Batcher,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential batching functionality.\n *\n * Batching is a technique for grouping multiple operations together to be processed as a single unit.\n * This synchronous version is lighter weight and often all you need.\n *\n * The Batcher provides a flexible way to implement batching with configurable:\n * - Maximum batch size (number of items per batch)\n * - Time-based batching (process after X milliseconds)\n * - Custom batch processing logic via getShouldExecute\n *\n * Features included:\n * - Core batching functionality (addItem, flush, clear, cancel)\n * - Size-based batching (maxSize)\n * - Time-based batching (wait timeout)\n * - Custom condition batching (getShouldExecute)\n * - Manual processing controls\n * - Public mutable options\n * - Callback support for monitoring batch execution and state changes\n *\n * Features NOT included (compared to core Batcher):\n * - No TanStack Store state management\n * - No devtools integration\n * - No complex state tracking (execution counts, etc.)\n * - No reactive state management\n *\n * @example\n * ```ts\n * // Basic batching\n * const batcher = new LiteBatcher<number>(\n * (items) => console.log('Processing batch:', items),\n * {\n * maxSize: 5,\n * wait: 2000,\n * onExecute: (batch, batcher) => {\n * console.log('Batch executed with', batch.length, 'items');\n * },\n * onItemsChange: (batcher) => {\n * console.log('Batch size changed to:', batcher.size);\n * }\n * }\n * );\n *\n * batcher.addItem(1);\n * batcher.addItem(2);\n * // After 2 seconds or when 5 items are added, whichever comes first,\n * // the batch will be processed\n * ```\n *\n * @example\n * ```ts\n * // Custom condition batching\n * const batcher = new LiteBatcher<Task>(\n * (items) => processTasks(items),\n * {\n * getShouldExecute: (items) => items.some(task => task.urgent),\n * maxSize: 10,\n * }\n * );\n *\n * batcher.addItem({ name: 'normal', urgent: false });\n * batcher.addItem({ name: 'urgent', urgent: true }); // Triggers immediate processing\n * ```\n */\nexport class LiteBatcher<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private _isPending = false\n\n constructor(\n public fn: (items: Array<TValue>) => void,\n public options: LiteBatcherOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? Infinity\n this.options.getShouldExecute =\n this.options.getShouldExecute ?? (() => false)\n }\n\n /**\n * Number of items currently in the batch\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the batch has no items to process (items array is empty)\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the batcher is waiting for the timeout to trigger batch processing\n */\n get isPending(): boolean {\n return this._isPending\n }\n\n private getWait(): number {\n if (typeof this.options.wait === 'function') {\n return this.options.wait(this)\n }\n return this.options.wait!\n }\n\n /**\n * Adds an item to the batcher\n * If the batch size is reached, timeout occurs, or getShouldExecute returns true, the batch will be processed\n */\n addItem = (item: TValue): void => {\n this.items.push(item)\n this._isPending = this.options.wait !== Infinity\n this.options.onItemsChange?.(this)\n\n const shouldProcess =\n this.items.length >= this.options.maxSize! ||\n this.options.getShouldExecute!(this.items, this)\n\n if (shouldProcess) {\n this.execute()\n } else if (this.options.wait !== Infinity) {\n this.clearTimeout() // clear any pending timeout to replace it with a new one\n this.timeoutId = setTimeout(() => this.execute(), this.getWait())\n }\n }\n\n /**\n * Processes the current batch of items.\n * This method will automatically be triggered if the batcher is running and any of these conditions are met:\n * - The number of items reaches maxSize\n * - The wait duration has elapsed\n * - The getShouldExecute function returns true upon adding an item\n *\n * You can also call this method manually to process the current batch at any time.\n */\n private execute = (): void => {\n if (this.items.length === 0) {\n return\n }\n\n const batch = this.peekAllItems() // copy of the items to be processed (to prevent race conditions)\n this.clear() // Clear items before processing to prevent race conditions\n\n this.fn(batch) // EXECUTE\n this.options.onExecute?.(batch, this)\n }\n\n /**\n * Processes the current batch of items immediately\n */\n flush = (): void => {\n this.clearTimeout() // clear any pending timeout\n this.execute() // execute immediately\n }\n\n /**\n * Returns a copy of all items in the batcher\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Removes all items from the batcher\n */\n clear = (): void => {\n const hadItems = this.items.length > 0\n this.items = []\n this._isPending = false\n if (hadItems) {\n this.options.onItemsChange?.(this)\n }\n }\n\n /**\n * Cancels any pending execution that was scheduled.\n * Does NOT clear out the items.\n */\n cancel = (): void => {\n this.clearTimeout()\n this._isPending = false\n }\n}\n\n/**\n * Creates a batcher that processes items in batches.\n *\n * This is an alternative to the batch function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a batcher with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const batchItems = liteBatch<number>(\n * (items) => console.log('Processing:', items),\n * {\n * maxSize: 3,\n * }\n * );\n *\n * batchItems(1);\n * batchItems(2);\n * batchItems(3); // Triggers batch processing\n * ```\n */\nexport function liteBatch<TValue>(\n fn: (items: Array<TValue>) => void,\n options: LiteBatcherOptions<TValue> = {},\n): (item: TValue) => void {\n const batcher = new LiteBatcher<TValue>(fn, options)\n return batcher.addItem\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,IAAa,cAAb,MAAiC;CAK/B,YACE,AAAOA,IACP,AAAOC,UAAsC,EAAE,EAC/C;EAFO;EACA;eANsB,EAAE;mBACU;oBACtB;kBA8CV,SAAuB;AAChC,QAAK,MAAM,KAAK,KAAK;AACrB,QAAK,aAAa,KAAK,QAAQ,SAAS;AACxC,QAAK,QAAQ,gBAAgB,KAAK;AAMlC,OAHE,KAAK,MAAM,UAAU,KAAK,QAAQ,WAClC,KAAK,QAAQ,iBAAkB,KAAK,OAAO,KAAK,CAGhD,MAAK,SAAS;YACL,KAAK,QAAQ,SAAS,UAAU;AACzC,SAAK,cAAc;AACnB,SAAK,YAAY,iBAAiB,KAAK,SAAS,EAAE,KAAK,SAAS,CAAC;;;uBAavC;AAC5B,OAAI,KAAK,MAAM,WAAW,EACxB;GAGF,MAAM,QAAQ,KAAK,cAAc;AACjC,QAAK,OAAO;AAEZ,QAAK,GAAG,MAAM;AACd,QAAK,QAAQ,YAAY,OAAO,KAAK;;qBAMnB;AAClB,QAAK,cAAc;AACnB,QAAK,SAAS;;4BAMoB;AAClC,UAAO,CAAC,GAAG,KAAK,MAAM;;4BAGW;AACjC,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;;qBAOD;GAClB,MAAM,WAAW,KAAK,MAAM,SAAS;AACrC,QAAK,QAAQ,EAAE;AACf,QAAK,aAAa;AAClB,OAAI,SACF,MAAK,QAAQ,gBAAgB,KAAK;;sBAQjB;AACnB,QAAK,cAAc;AACnB,QAAK,aAAa;;AArHlB,OAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;AAC/C,OAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;AAC/C,OAAK,QAAQ,OAAO,KAAK,QAAQ,QAAQ;AACzC,OAAK,QAAQ,mBACX,KAAK,QAAQ,2BAA2B;;;;;CAM5C,IAAI,OAAe;AACjB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAI,UAAmB;AACrB,SAAO,KAAK,MAAM,WAAW;;;;;CAM/B,IAAI,YAAqB;AACvB,SAAO,KAAK;;CAGd,AAAQ,UAAkB;AACxB,MAAI,OAAO,KAAK,QAAQ,SAAS,WAC/B,QAAO,KAAK,QAAQ,KAAK,KAAK;AAEhC,SAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AA8GxB,SAAgB,UACd,IACA,UAAsC,EAAE,EAChB;AAExB,QADgB,IAAI,YAAoB,IAAI,QAAQ,CACrC"}
1
+ {"version":3,"file":"lite-batcher.cjs","names":[],"sources":["../src/lite-batcher.ts"],"sourcesContent":["/**\n * Options for configuring a lite batcher instance\n */\nexport interface LiteBatcherOptions<TValue> {\n /**\n * Custom function to determine if a batch should be processed\n * Return true to process the batch immediately\n */\n getShouldExecute?: (\n items: Array<TValue>,\n batcher: LiteBatcher<TValue>,\n ) => boolean\n /**\n * Maximum number of items in a batch\n * @default Infinity\n */\n maxSize?: number\n /**\n * Callback fired after a batch is processed\n */\n onExecute?: (batch: Array<TValue>, batcher: LiteBatcher<TValue>) => void\n /**\n * Callback fired after items are added to the batcher\n */\n onItemsChange?: (batcher: LiteBatcher<TValue>) => void\n /**\n * Whether the batcher should start processing immediately\n * @default true\n */\n started?: boolean\n /**\n * Maximum time in milliseconds to wait before processing a batch.\n * If the wait duration has elapsed, the batch will be processed.\n * If not provided, the batch will not be triggered by a timeout.\n * @default Infinity\n */\n wait?: number | ((batcher: LiteBatcher<TValue>) => number)\n}\n\n/**\n * A lightweight class that collects items and processes them in batches.\n *\n * This is an alternative to the Batcher in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Batcher,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential batching functionality.\n *\n * Batching is a technique for grouping multiple operations together to be processed as a single unit.\n * This synchronous version is lighter weight and often all you need.\n *\n * The Batcher provides a flexible way to implement batching with configurable:\n * - Maximum batch size (number of items per batch)\n * - Time-based batching (process after X milliseconds)\n * - Custom batch processing logic via getShouldExecute\n *\n * Features included:\n * - Core batching functionality (addItem, flush, clear, cancel)\n * - Size-based batching (maxSize)\n * - Time-based batching (wait timeout)\n * - Custom condition batching (getShouldExecute)\n * - Manual processing controls\n * - Public mutable options\n * - Callback support for monitoring batch execution and state changes\n *\n * Features NOT included (compared to core Batcher):\n * - No TanStack Store state management\n * - No devtools integration\n * - No complex state tracking (execution counts, etc.)\n * - No reactive state management\n *\n * @example\n * ```ts\n * // Basic batching\n * const batcher = new LiteBatcher<number>(\n * (items) => console.log('Processing batch:', items),\n * {\n * maxSize: 5,\n * wait: 2000,\n * onExecute: (batch, batcher) => {\n * console.log('Batch executed with', batch.length, 'items');\n * },\n * onItemsChange: (batcher) => {\n * console.log('Batch size changed to:', batcher.size);\n * }\n * }\n * );\n *\n * batcher.addItem(1);\n * batcher.addItem(2);\n * // After 2 seconds or when 5 items are added, whichever comes first,\n * // the batch will be processed\n * ```\n *\n * @example\n * ```ts\n * // Custom condition batching\n * const batcher = new LiteBatcher<Task>(\n * (items) => processTasks(items),\n * {\n * getShouldExecute: (items) => items.some(task => task.urgent),\n * maxSize: 10,\n * }\n * );\n *\n * batcher.addItem({ name: 'normal', urgent: false });\n * batcher.addItem({ name: 'urgent', urgent: true }); // Triggers immediate processing\n * ```\n */\nexport class LiteBatcher<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private _isPending = false\n\n constructor(\n public fn: (items: Array<TValue>) => void,\n public options: LiteBatcherOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? Infinity\n this.options.getShouldExecute =\n this.options.getShouldExecute ?? (() => false)\n }\n\n /**\n * Number of items currently in the batch\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the batch has no items to process (items array is empty)\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the batcher is waiting for the timeout to trigger batch processing\n */\n get isPending(): boolean {\n return this._isPending\n }\n\n private getWait(): number {\n if (typeof this.options.wait === 'function') {\n return this.options.wait(this)\n }\n return this.options.wait!\n }\n\n /**\n * Adds an item to the batcher\n * If the batch size is reached, timeout occurs, or getShouldExecute returns true, the batch will be processed\n */\n addItem = (item: TValue): void => {\n this.items.push(item)\n this._isPending = this.options.wait !== Infinity\n this.options.onItemsChange?.(this)\n\n const shouldProcess =\n this.items.length >= this.options.maxSize! ||\n this.options.getShouldExecute!(this.items, this)\n\n if (shouldProcess) {\n this.execute()\n } else if (this.options.wait !== Infinity) {\n this.clearTimeout() // clear any pending timeout to replace it with a new one\n this.timeoutId = setTimeout(() => this.execute(), this.getWait())\n }\n }\n\n /**\n * Processes the current batch of items.\n * This method will automatically be triggered if the batcher is running and any of these conditions are met:\n * - The number of items reaches maxSize\n * - The wait duration has elapsed\n * - The getShouldExecute function returns true upon adding an item\n *\n * You can also call this method manually to process the current batch at any time.\n */\n private execute = (): void => {\n if (this.items.length === 0) {\n return\n }\n\n const batch = this.peekAllItems() // copy of the items to be processed (to prevent race conditions)\n this.clear() // Clear items before processing to prevent race conditions\n\n this.fn(batch) // EXECUTE\n this.options.onExecute?.(batch, this)\n }\n\n /**\n * Processes the current batch of items immediately\n */\n flush = (): void => {\n this.clearTimeout() // clear any pending timeout\n this.execute() // execute immediately\n }\n\n /**\n * Returns a copy of all items in the batcher\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Removes all items from the batcher\n */\n clear = (): void => {\n const hadItems = this.items.length > 0\n this.items = []\n this._isPending = false\n if (hadItems) {\n this.options.onItemsChange?.(this)\n }\n }\n\n /**\n * Cancels any pending execution that was scheduled.\n * Does NOT clear out the items.\n */\n cancel = (): void => {\n this.clearTimeout()\n this._isPending = false\n }\n}\n\n/**\n * Creates a batcher that processes items in batches.\n *\n * This is an alternative to the batch function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a batcher with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const batchItems = liteBatch<number>(\n * (items) => console.log('Processing:', items),\n * {\n * maxSize: 3,\n * }\n * );\n *\n * batchItems(1);\n * batchItems(2);\n * batchItems(3); // Triggers batch processing\n * ```\n */\nexport function liteBatch<TValue>(\n fn: (items: Array<TValue>) => void,\n options: LiteBatcherOptions<TValue> = {},\n): (item: TValue) => void {\n const batcher = new LiteBatcher<TValue>(fn, options)\n return batcher.addItem\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,IAAa,cAAb,MAAiC;CAK/B,YACE,AAAO,IACP,AAAO,UAAsC,EAAE,EAC/C;EAFO;EACA;eANsB,EAAE;mBACU;oBACtB;kBA8CV,SAAuB;GAChC,KAAK,MAAM,KAAK,KAAK;GACrB,KAAK,aAAa,KAAK,QAAQ,SAAS;GACxC,KAAK,QAAQ,gBAAgB,KAAK;GAMlC,IAHE,KAAK,MAAM,UAAU,KAAK,QAAQ,WAClC,KAAK,QAAQ,iBAAkB,KAAK,OAAO,KAAK,EAGhD,KAAK,SAAS;QACT,IAAI,KAAK,QAAQ,SAAS,UAAU;IACzC,KAAK,cAAc;IACnB,KAAK,YAAY,iBAAiB,KAAK,SAAS,EAAE,KAAK,SAAS,CAAC;;;uBAavC;GAC5B,IAAI,KAAK,MAAM,WAAW,GACxB;GAGF,MAAM,QAAQ,KAAK,cAAc;GACjC,KAAK,OAAO;GAEZ,KAAK,GAAG,MAAM;GACd,KAAK,QAAQ,YAAY,OAAO,KAAK;;qBAMnB;GAClB,KAAK,cAAc;GACnB,KAAK,SAAS;;4BAMoB;GAClC,OAAO,CAAC,GAAG,KAAK,MAAM;;4BAGW;GACjC,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;;qBAOD;GAClB,MAAM,WAAW,KAAK,MAAM,SAAS;GACrC,KAAK,QAAQ,EAAE;GACf,KAAK,aAAa;GAClB,IAAI,UACF,KAAK,QAAQ,gBAAgB,KAAK;;sBAQjB;GACnB,KAAK,cAAc;GACnB,KAAK,aAAa;;EArHlB,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;EAC/C,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;EAC/C,KAAK,QAAQ,OAAO,KAAK,QAAQ,QAAQ;EACzC,KAAK,QAAQ,mBACX,KAAK,QAAQ,2BAA2B;;;;;CAM5C,IAAI,OAAe;EACjB,OAAO,KAAK,MAAM;;;;;CAMpB,IAAI,UAAmB;EACrB,OAAO,KAAK,MAAM,WAAW;;;;;CAM/B,IAAI,YAAqB;EACvB,OAAO,KAAK;;CAGd,AAAQ,UAAkB;EACxB,IAAI,OAAO,KAAK,QAAQ,SAAS,YAC/B,OAAO,KAAK,QAAQ,KAAK,KAAK;EAEhC,OAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AA8GxB,SAAgB,UACd,IACA,UAAsC,EAAE,EAChB;CAExB,OAAO,IADa,YAAoB,IAAI,QAC9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"lite-batcher.js","names":["fn: (items: Array<TValue>) => void","options: LiteBatcherOptions<TValue>"],"sources":["../src/lite-batcher.ts"],"sourcesContent":["/**\n * Options for configuring a lite batcher instance\n */\nexport interface LiteBatcherOptions<TValue> {\n /**\n * Custom function to determine if a batch should be processed\n * Return true to process the batch immediately\n */\n getShouldExecute?: (\n items: Array<TValue>,\n batcher: LiteBatcher<TValue>,\n ) => boolean\n /**\n * Maximum number of items in a batch\n * @default Infinity\n */\n maxSize?: number\n /**\n * Callback fired after a batch is processed\n */\n onExecute?: (batch: Array<TValue>, batcher: LiteBatcher<TValue>) => void\n /**\n * Callback fired after items are added to the batcher\n */\n onItemsChange?: (batcher: LiteBatcher<TValue>) => void\n /**\n * Whether the batcher should start processing immediately\n * @default true\n */\n started?: boolean\n /**\n * Maximum time in milliseconds to wait before processing a batch.\n * If the wait duration has elapsed, the batch will be processed.\n * If not provided, the batch will not be triggered by a timeout.\n * @default Infinity\n */\n wait?: number | ((batcher: LiteBatcher<TValue>) => number)\n}\n\n/**\n * A lightweight class that collects items and processes them in batches.\n *\n * This is an alternative to the Batcher in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Batcher,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential batching functionality.\n *\n * Batching is a technique for grouping multiple operations together to be processed as a single unit.\n * This synchronous version is lighter weight and often all you need.\n *\n * The Batcher provides a flexible way to implement batching with configurable:\n * - Maximum batch size (number of items per batch)\n * - Time-based batching (process after X milliseconds)\n * - Custom batch processing logic via getShouldExecute\n *\n * Features included:\n * - Core batching functionality (addItem, flush, clear, cancel)\n * - Size-based batching (maxSize)\n * - Time-based batching (wait timeout)\n * - Custom condition batching (getShouldExecute)\n * - Manual processing controls\n * - Public mutable options\n * - Callback support for monitoring batch execution and state changes\n *\n * Features NOT included (compared to core Batcher):\n * - No TanStack Store state management\n * - No devtools integration\n * - No complex state tracking (execution counts, etc.)\n * - No reactive state management\n *\n * @example\n * ```ts\n * // Basic batching\n * const batcher = new LiteBatcher<number>(\n * (items) => console.log('Processing batch:', items),\n * {\n * maxSize: 5,\n * wait: 2000,\n * onExecute: (batch, batcher) => {\n * console.log('Batch executed with', batch.length, 'items');\n * },\n * onItemsChange: (batcher) => {\n * console.log('Batch size changed to:', batcher.size);\n * }\n * }\n * );\n *\n * batcher.addItem(1);\n * batcher.addItem(2);\n * // After 2 seconds or when 5 items are added, whichever comes first,\n * // the batch will be processed\n * ```\n *\n * @example\n * ```ts\n * // Custom condition batching\n * const batcher = new LiteBatcher<Task>(\n * (items) => processTasks(items),\n * {\n * getShouldExecute: (items) => items.some(task => task.urgent),\n * maxSize: 10,\n * }\n * );\n *\n * batcher.addItem({ name: 'normal', urgent: false });\n * batcher.addItem({ name: 'urgent', urgent: true }); // Triggers immediate processing\n * ```\n */\nexport class LiteBatcher<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private _isPending = false\n\n constructor(\n public fn: (items: Array<TValue>) => void,\n public options: LiteBatcherOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? Infinity\n this.options.getShouldExecute =\n this.options.getShouldExecute ?? (() => false)\n }\n\n /**\n * Number of items currently in the batch\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the batch has no items to process (items array is empty)\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the batcher is waiting for the timeout to trigger batch processing\n */\n get isPending(): boolean {\n return this._isPending\n }\n\n private getWait(): number {\n if (typeof this.options.wait === 'function') {\n return this.options.wait(this)\n }\n return this.options.wait!\n }\n\n /**\n * Adds an item to the batcher\n * If the batch size is reached, timeout occurs, or getShouldExecute returns true, the batch will be processed\n */\n addItem = (item: TValue): void => {\n this.items.push(item)\n this._isPending = this.options.wait !== Infinity\n this.options.onItemsChange?.(this)\n\n const shouldProcess =\n this.items.length >= this.options.maxSize! ||\n this.options.getShouldExecute!(this.items, this)\n\n if (shouldProcess) {\n this.execute()\n } else if (this.options.wait !== Infinity) {\n this.clearTimeout() // clear any pending timeout to replace it with a new one\n this.timeoutId = setTimeout(() => this.execute(), this.getWait())\n }\n }\n\n /**\n * Processes the current batch of items.\n * This method will automatically be triggered if the batcher is running and any of these conditions are met:\n * - The number of items reaches maxSize\n * - The wait duration has elapsed\n * - The getShouldExecute function returns true upon adding an item\n *\n * You can also call this method manually to process the current batch at any time.\n */\n private execute = (): void => {\n if (this.items.length === 0) {\n return\n }\n\n const batch = this.peekAllItems() // copy of the items to be processed (to prevent race conditions)\n this.clear() // Clear items before processing to prevent race conditions\n\n this.fn(batch) // EXECUTE\n this.options.onExecute?.(batch, this)\n }\n\n /**\n * Processes the current batch of items immediately\n */\n flush = (): void => {\n this.clearTimeout() // clear any pending timeout\n this.execute() // execute immediately\n }\n\n /**\n * Returns a copy of all items in the batcher\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Removes all items from the batcher\n */\n clear = (): void => {\n const hadItems = this.items.length > 0\n this.items = []\n this._isPending = false\n if (hadItems) {\n this.options.onItemsChange?.(this)\n }\n }\n\n /**\n * Cancels any pending execution that was scheduled.\n * Does NOT clear out the items.\n */\n cancel = (): void => {\n this.clearTimeout()\n this._isPending = false\n }\n}\n\n/**\n * Creates a batcher that processes items in batches.\n *\n * This is an alternative to the batch function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a batcher with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const batchItems = liteBatch<number>(\n * (items) => console.log('Processing:', items),\n * {\n * maxSize: 3,\n * }\n * );\n *\n * batchItems(1);\n * batchItems(2);\n * batchItems(3); // Triggers batch processing\n * ```\n */\nexport function liteBatch<TValue>(\n fn: (items: Array<TValue>) => void,\n options: LiteBatcherOptions<TValue> = {},\n): (item: TValue) => void {\n const batcher = new LiteBatcher<TValue>(fn, options)\n return batcher.addItem\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,IAAa,cAAb,MAAiC;CAK/B,YACE,AAAOA,IACP,AAAOC,UAAsC,EAAE,EAC/C;EAFO;EACA;eANsB,EAAE;mBACU;oBACtB;kBA8CV,SAAuB;AAChC,QAAK,MAAM,KAAK,KAAK;AACrB,QAAK,aAAa,KAAK,QAAQ,SAAS;AACxC,QAAK,QAAQ,gBAAgB,KAAK;AAMlC,OAHE,KAAK,MAAM,UAAU,KAAK,QAAQ,WAClC,KAAK,QAAQ,iBAAkB,KAAK,OAAO,KAAK,CAGhD,MAAK,SAAS;YACL,KAAK,QAAQ,SAAS,UAAU;AACzC,SAAK,cAAc;AACnB,SAAK,YAAY,iBAAiB,KAAK,SAAS,EAAE,KAAK,SAAS,CAAC;;;uBAavC;AAC5B,OAAI,KAAK,MAAM,WAAW,EACxB;GAGF,MAAM,QAAQ,KAAK,cAAc;AACjC,QAAK,OAAO;AAEZ,QAAK,GAAG,MAAM;AACd,QAAK,QAAQ,YAAY,OAAO,KAAK;;qBAMnB;AAClB,QAAK,cAAc;AACnB,QAAK,SAAS;;4BAMoB;AAClC,UAAO,CAAC,GAAG,KAAK,MAAM;;4BAGW;AACjC,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;;qBAOD;GAClB,MAAM,WAAW,KAAK,MAAM,SAAS;AACrC,QAAK,QAAQ,EAAE;AACf,QAAK,aAAa;AAClB,OAAI,SACF,MAAK,QAAQ,gBAAgB,KAAK;;sBAQjB;AACnB,QAAK,cAAc;AACnB,QAAK,aAAa;;AArHlB,OAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;AAC/C,OAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;AAC/C,OAAK,QAAQ,OAAO,KAAK,QAAQ,QAAQ;AACzC,OAAK,QAAQ,mBACX,KAAK,QAAQ,2BAA2B;;;;;CAM5C,IAAI,OAAe;AACjB,SAAO,KAAK,MAAM;;;;;CAMpB,IAAI,UAAmB;AACrB,SAAO,KAAK,MAAM,WAAW;;;;;CAM/B,IAAI,YAAqB;AACvB,SAAO,KAAK;;CAGd,AAAQ,UAAkB;AACxB,MAAI,OAAO,KAAK,QAAQ,SAAS,WAC/B,QAAO,KAAK,QAAQ,KAAK,KAAK;AAEhC,SAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AA8GxB,SAAgB,UACd,IACA,UAAsC,EAAE,EAChB;AAExB,QADgB,IAAI,YAAoB,IAAI,QAAQ,CACrC"}
1
+ {"version":3,"file":"lite-batcher.js","names":[],"sources":["../src/lite-batcher.ts"],"sourcesContent":["/**\n * Options for configuring a lite batcher instance\n */\nexport interface LiteBatcherOptions<TValue> {\n /**\n * Custom function to determine if a batch should be processed\n * Return true to process the batch immediately\n */\n getShouldExecute?: (\n items: Array<TValue>,\n batcher: LiteBatcher<TValue>,\n ) => boolean\n /**\n * Maximum number of items in a batch\n * @default Infinity\n */\n maxSize?: number\n /**\n * Callback fired after a batch is processed\n */\n onExecute?: (batch: Array<TValue>, batcher: LiteBatcher<TValue>) => void\n /**\n * Callback fired after items are added to the batcher\n */\n onItemsChange?: (batcher: LiteBatcher<TValue>) => void\n /**\n * Whether the batcher should start processing immediately\n * @default true\n */\n started?: boolean\n /**\n * Maximum time in milliseconds to wait before processing a batch.\n * If the wait duration has elapsed, the batch will be processed.\n * If not provided, the batch will not be triggered by a timeout.\n * @default Infinity\n */\n wait?: number | ((batcher: LiteBatcher<TValue>) => number)\n}\n\n/**\n * A lightweight class that collects items and processes them in batches.\n *\n * This is an alternative to the Batcher in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Batcher,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential batching functionality.\n *\n * Batching is a technique for grouping multiple operations together to be processed as a single unit.\n * This synchronous version is lighter weight and often all you need.\n *\n * The Batcher provides a flexible way to implement batching with configurable:\n * - Maximum batch size (number of items per batch)\n * - Time-based batching (process after X milliseconds)\n * - Custom batch processing logic via getShouldExecute\n *\n * Features included:\n * - Core batching functionality (addItem, flush, clear, cancel)\n * - Size-based batching (maxSize)\n * - Time-based batching (wait timeout)\n * - Custom condition batching (getShouldExecute)\n * - Manual processing controls\n * - Public mutable options\n * - Callback support for monitoring batch execution and state changes\n *\n * Features NOT included (compared to core Batcher):\n * - No TanStack Store state management\n * - No devtools integration\n * - No complex state tracking (execution counts, etc.)\n * - No reactive state management\n *\n * @example\n * ```ts\n * // Basic batching\n * const batcher = new LiteBatcher<number>(\n * (items) => console.log('Processing batch:', items),\n * {\n * maxSize: 5,\n * wait: 2000,\n * onExecute: (batch, batcher) => {\n * console.log('Batch executed with', batch.length, 'items');\n * },\n * onItemsChange: (batcher) => {\n * console.log('Batch size changed to:', batcher.size);\n * }\n * }\n * );\n *\n * batcher.addItem(1);\n * batcher.addItem(2);\n * // After 2 seconds or when 5 items are added, whichever comes first,\n * // the batch will be processed\n * ```\n *\n * @example\n * ```ts\n * // Custom condition batching\n * const batcher = new LiteBatcher<Task>(\n * (items) => processTasks(items),\n * {\n * getShouldExecute: (items) => items.some(task => task.urgent),\n * maxSize: 10,\n * }\n * );\n *\n * batcher.addItem({ name: 'normal', urgent: false });\n * batcher.addItem({ name: 'urgent', urgent: true }); // Triggers immediate processing\n * ```\n */\nexport class LiteBatcher<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private _isPending = false\n\n constructor(\n public fn: (items: Array<TValue>) => void,\n public options: LiteBatcherOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? Infinity\n this.options.getShouldExecute =\n this.options.getShouldExecute ?? (() => false)\n }\n\n /**\n * Number of items currently in the batch\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the batch has no items to process (items array is empty)\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the batcher is waiting for the timeout to trigger batch processing\n */\n get isPending(): boolean {\n return this._isPending\n }\n\n private getWait(): number {\n if (typeof this.options.wait === 'function') {\n return this.options.wait(this)\n }\n return this.options.wait!\n }\n\n /**\n * Adds an item to the batcher\n * If the batch size is reached, timeout occurs, or getShouldExecute returns true, the batch will be processed\n */\n addItem = (item: TValue): void => {\n this.items.push(item)\n this._isPending = this.options.wait !== Infinity\n this.options.onItemsChange?.(this)\n\n const shouldProcess =\n this.items.length >= this.options.maxSize! ||\n this.options.getShouldExecute!(this.items, this)\n\n if (shouldProcess) {\n this.execute()\n } else if (this.options.wait !== Infinity) {\n this.clearTimeout() // clear any pending timeout to replace it with a new one\n this.timeoutId = setTimeout(() => this.execute(), this.getWait())\n }\n }\n\n /**\n * Processes the current batch of items.\n * This method will automatically be triggered if the batcher is running and any of these conditions are met:\n * - The number of items reaches maxSize\n * - The wait duration has elapsed\n * - The getShouldExecute function returns true upon adding an item\n *\n * You can also call this method manually to process the current batch at any time.\n */\n private execute = (): void => {\n if (this.items.length === 0) {\n return\n }\n\n const batch = this.peekAllItems() // copy of the items to be processed (to prevent race conditions)\n this.clear() // Clear items before processing to prevent race conditions\n\n this.fn(batch) // EXECUTE\n this.options.onExecute?.(batch, this)\n }\n\n /**\n * Processes the current batch of items immediately\n */\n flush = (): void => {\n this.clearTimeout() // clear any pending timeout\n this.execute() // execute immediately\n }\n\n /**\n * Returns a copy of all items in the batcher\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Removes all items from the batcher\n */\n clear = (): void => {\n const hadItems = this.items.length > 0\n this.items = []\n this._isPending = false\n if (hadItems) {\n this.options.onItemsChange?.(this)\n }\n }\n\n /**\n * Cancels any pending execution that was scheduled.\n * Does NOT clear out the items.\n */\n cancel = (): void => {\n this.clearTimeout()\n this._isPending = false\n }\n}\n\n/**\n * Creates a batcher that processes items in batches.\n *\n * This is an alternative to the batch function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a batcher with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const batchItems = liteBatch<number>(\n * (items) => console.log('Processing:', items),\n * {\n * maxSize: 3,\n * }\n * );\n *\n * batchItems(1);\n * batchItems(2);\n * batchItems(3); // Triggers batch processing\n * ```\n */\nexport function liteBatch<TValue>(\n fn: (items: Array<TValue>) => void,\n options: LiteBatcherOptions<TValue> = {},\n): (item: TValue) => void {\n const batcher = new LiteBatcher<TValue>(fn, options)\n return batcher.addItem\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,IAAa,cAAb,MAAiC;CAK/B,YACE,AAAO,IACP,AAAO,UAAsC,EAAE,EAC/C;EAFO;EACA;eANsB,EAAE;mBACU;oBACtB;kBA8CV,SAAuB;GAChC,KAAK,MAAM,KAAK,KAAK;GACrB,KAAK,aAAa,KAAK,QAAQ,SAAS;GACxC,KAAK,QAAQ,gBAAgB,KAAK;GAMlC,IAHE,KAAK,MAAM,UAAU,KAAK,QAAQ,WAClC,KAAK,QAAQ,iBAAkB,KAAK,OAAO,KAAK,EAGhD,KAAK,SAAS;QACT,IAAI,KAAK,QAAQ,SAAS,UAAU;IACzC,KAAK,cAAc;IACnB,KAAK,YAAY,iBAAiB,KAAK,SAAS,EAAE,KAAK,SAAS,CAAC;;;uBAavC;GAC5B,IAAI,KAAK,MAAM,WAAW,GACxB;GAGF,MAAM,QAAQ,KAAK,cAAc;GACjC,KAAK,OAAO;GAEZ,KAAK,GAAG,MAAM;GACd,KAAK,QAAQ,YAAY,OAAO,KAAK;;qBAMnB;GAClB,KAAK,cAAc;GACnB,KAAK,SAAS;;4BAMoB;GAClC,OAAO,CAAC,GAAG,KAAK,MAAM;;4BAGW;GACjC,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;;qBAOD;GAClB,MAAM,WAAW,KAAK,MAAM,SAAS;GACrC,KAAK,QAAQ,EAAE;GACf,KAAK,aAAa;GAClB,IAAI,UACF,KAAK,QAAQ,gBAAgB,KAAK;;sBAQjB;GACnB,KAAK,cAAc;GACnB,KAAK,aAAa;;EArHlB,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;EAC/C,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW;EAC/C,KAAK,QAAQ,OAAO,KAAK,QAAQ,QAAQ;EACzC,KAAK,QAAQ,mBACX,KAAK,QAAQ,2BAA2B;;;;;CAM5C,IAAI,OAAe;EACjB,OAAO,KAAK,MAAM;;;;;CAMpB,IAAI,UAAmB;EACrB,OAAO,KAAK,MAAM,WAAW;;;;;CAM/B,IAAI,YAAqB;EACvB,OAAO,KAAK;;CAGd,AAAQ,UAAkB;EACxB,IAAI,OAAO,KAAK,QAAQ,SAAS,YAC/B,OAAO,KAAK,QAAQ,KAAK,KAAK;EAEhC,OAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;AA8GxB,SAAgB,UACd,IACA,UAAsC,EAAE,EAChB;CAExB,OAAO,IADa,YAAoB,IAAI,QAC9B,CAAC"}
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/lite-debouncer.ts
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lite-debouncer.cjs","names":["fn: TFn","options: LiteDebouncerOptions<TFn>"],"sources":["../src/lite-debouncer.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite debounced function\n */\nexport interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * The first call will execute immediately and the rest will wait the delay.\n * Defaults to false.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, debouncer: LiteDebouncer<TFn>) => void\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 before executing the function.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a debounced function.\n *\n * This is an alternative to the Debouncer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Debouncer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential debouncing functionality.\n *\n * Debouncing ensures that a function is only executed after a certain amount of time has passed\n * since its last invocation. This is useful for handling frequent events like window resizing,\n * scroll events, or input changes where you want to limit the rate of execution.\n *\n * The debounced function can be configured to execute either at the start of the delay period\n * (leading edge) or at the end (trailing edge, default). Each new call during the wait period\n * will reset the timer.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const debouncer = new LiteDebouncer((value: string) => {\n * saveToDatabase(value);\n * }, {\n * wait: 500,\n * onExecute: (args, debouncer) => {\n * console.log('Saved value:', args[0]);\n * }\n * });\n *\n * // Will only save after 500ms of no new input\n * inputElement.addEventListener('input', () => {\n * debouncer.maybeExecute(inputElement.value);\n * });\n * ```\n */\nexport class LiteDebouncer<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private canLeadingExecute = true\n\n constructor(\n public fn: TFn,\n public options: LiteDebouncerOptions<TFn>,\n ) {\n // Default trailing to true if neither leading nor trailing is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the debounced function.\n * If leading is true and this is the first call, executes immediately.\n * Otherwise, queues the execution for after the wait time.\n * Each new call resets the timer.\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n let didLeadingExecute = false\n\n if (this.options.leading && this.canLeadingExecute) {\n this.canLeadingExecute = false\n didLeadingExecute = true\n this.fn(...args)\n this.options.onExecute?.(args, this)\n }\n\n this.lastArgs = args\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n }\n\n this.timeoutId = setTimeout(() => {\n this.canLeadingExecute = true\n if (this.options.trailing && !didLeadingExecute && this.lastArgs) {\n this.fn(...this.lastArgs)\n this.options.onExecute?.(this.lastArgs, this)\n }\n this.lastArgs = undefined\n }, this.options.wait)\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.timeoutId && this.lastArgs) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n const args = this.lastArgs\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n }\n\n /**\n * Cancels any pending execution.\n * Clears the timeout and resets the internal state.\n */\n cancel = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n}\n\n/**\n * Creates a lightweight debounced function that delays invoking the provided function until after a specified wait time.\n * Multiple calls during the wait period will cancel previous pending invocations and reset the timer.\n *\n * This is an alternative to the debounce function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a debouncer with no external dependencies, devtools integration, or reactive state.\n *\n * If leading option is true, the function will execute immediately on the first call, then wait the delay\n * before allowing another execution.\n *\n * @example\n * ```ts\n * const debouncedSave = liteDebounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debouncedSave);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then waits\n * const debouncedSearch = liteDebounce((query: string) => {\n * performSearch(query);\n * }, { wait: 300, leading: true });\n * ```\n */\nexport function liteDebounce<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteDebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new LiteDebouncer(fn, options)\n return debouncer.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,IAAa,gBAAb,MAAoD;CAKlD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;2BAJmB;uBAqBZ,GAAG,SAAgC;GACjD,IAAI,oBAAoB;AAExB,OAAI,KAAK,QAAQ,WAAW,KAAK,mBAAmB;AAClD,SAAK,oBAAoB;AACzB,wBAAoB;AACpB,SAAK,GAAG,GAAG,KAAK;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK;;AAGtC,QAAK,WAAW;AAEhB,OAAI,KAAK,UACP,cAAa,KAAK,UAAU;AAG9B,QAAK,YAAY,iBAAiB;AAChC,SAAK,oBAAoB;AACzB,QAAI,KAAK,QAAQ,YAAY,CAAC,qBAAqB,KAAK,UAAU;AAChE,UAAK,GAAG,GAAG,KAAK,SAAS;AACzB,UAAK,QAAQ,YAAY,KAAK,UAAU,KAAK;;AAE/C,SAAK,WAAW;MACf,KAAK,QAAQ,KAAK;;qBAQH;AAClB,OAAI,KAAK,aAAa,KAAK,UAAU;AACnC,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;IACjB,MAAM,OAAO,KAAK;AAClB,SAAK,GAAG,GAAG,KAAK;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,SAAK,WAAW;AAChB,SAAK,oBAAoB;;;sBAQR;AACnB,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;AAEnB,QAAK,WAAW;AAChB,QAAK,oBAAoB;;AAnEzB,MACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,OAE1B,MAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgG9B,SAAgB,aACd,IACA,SACoC;AAEpC,QADkB,IAAI,cAAc,IAAI,QAAQ,CAC/B"}
1
+ {"version":3,"file":"lite-debouncer.cjs","names":[],"sources":["../src/lite-debouncer.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite debounced function\n */\nexport interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * The first call will execute immediately and the rest will wait the delay.\n * Defaults to false.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, debouncer: LiteDebouncer<TFn>) => void\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 before executing the function.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a debounced function.\n *\n * This is an alternative to the Debouncer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Debouncer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential debouncing functionality.\n *\n * Debouncing ensures that a function is only executed after a certain amount of time has passed\n * since its last invocation. This is useful for handling frequent events like window resizing,\n * scroll events, or input changes where you want to limit the rate of execution.\n *\n * The debounced function can be configured to execute either at the start of the delay period\n * (leading edge) or at the end (trailing edge, default). Each new call during the wait period\n * will reset the timer.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const debouncer = new LiteDebouncer((value: string) => {\n * saveToDatabase(value);\n * }, {\n * wait: 500,\n * onExecute: (args, debouncer) => {\n * console.log('Saved value:', args[0]);\n * }\n * });\n *\n * // Will only save after 500ms of no new input\n * inputElement.addEventListener('input', () => {\n * debouncer.maybeExecute(inputElement.value);\n * });\n * ```\n */\nexport class LiteDebouncer<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private canLeadingExecute = true\n\n constructor(\n public fn: TFn,\n public options: LiteDebouncerOptions<TFn>,\n ) {\n // Default trailing to true if neither leading nor trailing is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the debounced function.\n * If leading is true and this is the first call, executes immediately.\n * Otherwise, queues the execution for after the wait time.\n * Each new call resets the timer.\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n let didLeadingExecute = false\n\n if (this.options.leading && this.canLeadingExecute) {\n this.canLeadingExecute = false\n didLeadingExecute = true\n this.fn(...args)\n this.options.onExecute?.(args, this)\n }\n\n this.lastArgs = args\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n }\n\n this.timeoutId = setTimeout(() => {\n this.canLeadingExecute = true\n if (this.options.trailing && !didLeadingExecute && this.lastArgs) {\n this.fn(...this.lastArgs)\n this.options.onExecute?.(this.lastArgs, this)\n }\n this.lastArgs = undefined\n }, this.options.wait)\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.timeoutId && this.lastArgs) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n const args = this.lastArgs\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n }\n\n /**\n * Cancels any pending execution.\n * Clears the timeout and resets the internal state.\n */\n cancel = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n}\n\n/**\n * Creates a lightweight debounced function that delays invoking the provided function until after a specified wait time.\n * Multiple calls during the wait period will cancel previous pending invocations and reset the timer.\n *\n * This is an alternative to the debounce function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a debouncer with no external dependencies, devtools integration, or reactive state.\n *\n * If leading option is true, the function will execute immediately on the first call, then wait the delay\n * before allowing another execution.\n *\n * @example\n * ```ts\n * const debouncedSave = liteDebounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debouncedSave);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then waits\n * const debouncedSearch = liteDebounce((query: string) => {\n * performSearch(query);\n * }, { wait: 300, leading: true });\n * ```\n */\nexport function liteDebounce<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteDebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new LiteDebouncer(fn, options)\n return debouncer.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,IAAa,gBAAb,MAAoD;CAKlD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;2BAJmB;uBAqBZ,GAAG,SAAgC;GACjD,IAAI,oBAAoB;GAExB,IAAI,KAAK,QAAQ,WAAW,KAAK,mBAAmB;IAClD,KAAK,oBAAoB;IACzB,oBAAoB;IACpB,KAAK,GAAG,GAAG,KAAK;IAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;;GAGtC,KAAK,WAAW;GAEhB,IAAI,KAAK,WACP,aAAa,KAAK,UAAU;GAG9B,KAAK,YAAY,iBAAiB;IAChC,KAAK,oBAAoB;IACzB,IAAI,KAAK,QAAQ,YAAY,CAAC,qBAAqB,KAAK,UAAU;KAChE,KAAK,GAAG,GAAG,KAAK,SAAS;KACzB,KAAK,QAAQ,YAAY,KAAK,UAAU,KAAK;;IAE/C,KAAK,WAAW;MACf,KAAK,QAAQ,KAAK;;qBAQH;GAClB,IAAI,KAAK,aAAa,KAAK,UAAU;IACnC,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;IACjB,MAAM,OAAO,KAAK;IAClB,KAAK,GAAG,GAAG,KAAK;IAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;IACpC,KAAK,WAAW;IAChB,KAAK,oBAAoB;;;sBAQR;GACnB,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;GAEnB,KAAK,WAAW;GAChB,KAAK,oBAAoB;;EAnEzB,IACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAE1B,KAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgG9B,SAAgB,aACd,IACA,SACoC;CAEpC,OAAO,IADe,cAAc,IAAI,QACxB,CAAC"}
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.cjs";
2
2
 
3
3
  //#region src/lite-debouncer.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite debounced function
7
6
  */
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.js";
2
2
 
3
3
  //#region src/lite-debouncer.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite debounced function
7
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"lite-debouncer.js","names":["fn: TFn","options: LiteDebouncerOptions<TFn>"],"sources":["../src/lite-debouncer.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite debounced function\n */\nexport interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * The first call will execute immediately and the rest will wait the delay.\n * Defaults to false.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, debouncer: LiteDebouncer<TFn>) => void\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 before executing the function.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a debounced function.\n *\n * This is an alternative to the Debouncer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Debouncer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential debouncing functionality.\n *\n * Debouncing ensures that a function is only executed after a certain amount of time has passed\n * since its last invocation. This is useful for handling frequent events like window resizing,\n * scroll events, or input changes where you want to limit the rate of execution.\n *\n * The debounced function can be configured to execute either at the start of the delay period\n * (leading edge) or at the end (trailing edge, default). Each new call during the wait period\n * will reset the timer.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const debouncer = new LiteDebouncer((value: string) => {\n * saveToDatabase(value);\n * }, {\n * wait: 500,\n * onExecute: (args, debouncer) => {\n * console.log('Saved value:', args[0]);\n * }\n * });\n *\n * // Will only save after 500ms of no new input\n * inputElement.addEventListener('input', () => {\n * debouncer.maybeExecute(inputElement.value);\n * });\n * ```\n */\nexport class LiteDebouncer<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private canLeadingExecute = true\n\n constructor(\n public fn: TFn,\n public options: LiteDebouncerOptions<TFn>,\n ) {\n // Default trailing to true if neither leading nor trailing is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the debounced function.\n * If leading is true and this is the first call, executes immediately.\n * Otherwise, queues the execution for after the wait time.\n * Each new call resets the timer.\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n let didLeadingExecute = false\n\n if (this.options.leading && this.canLeadingExecute) {\n this.canLeadingExecute = false\n didLeadingExecute = true\n this.fn(...args)\n this.options.onExecute?.(args, this)\n }\n\n this.lastArgs = args\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n }\n\n this.timeoutId = setTimeout(() => {\n this.canLeadingExecute = true\n if (this.options.trailing && !didLeadingExecute && this.lastArgs) {\n this.fn(...this.lastArgs)\n this.options.onExecute?.(this.lastArgs, this)\n }\n this.lastArgs = undefined\n }, this.options.wait)\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.timeoutId && this.lastArgs) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n const args = this.lastArgs\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n }\n\n /**\n * Cancels any pending execution.\n * Clears the timeout and resets the internal state.\n */\n cancel = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n}\n\n/**\n * Creates a lightweight debounced function that delays invoking the provided function until after a specified wait time.\n * Multiple calls during the wait period will cancel previous pending invocations and reset the timer.\n *\n * This is an alternative to the debounce function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a debouncer with no external dependencies, devtools integration, or reactive state.\n *\n * If leading option is true, the function will execute immediately on the first call, then wait the delay\n * before allowing another execution.\n *\n * @example\n * ```ts\n * const debouncedSave = liteDebounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debouncedSave);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then waits\n * const debouncedSearch = liteDebounce((query: string) => {\n * performSearch(query);\n * }, { wait: 300, leading: true });\n * ```\n */\nexport function liteDebounce<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteDebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new LiteDebouncer(fn, options)\n return debouncer.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,IAAa,gBAAb,MAAoD;CAKlD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;2BAJmB;uBAqBZ,GAAG,SAAgC;GACjD,IAAI,oBAAoB;AAExB,OAAI,KAAK,QAAQ,WAAW,KAAK,mBAAmB;AAClD,SAAK,oBAAoB;AACzB,wBAAoB;AACpB,SAAK,GAAG,GAAG,KAAK;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK;;AAGtC,QAAK,WAAW;AAEhB,OAAI,KAAK,UACP,cAAa,KAAK,UAAU;AAG9B,QAAK,YAAY,iBAAiB;AAChC,SAAK,oBAAoB;AACzB,QAAI,KAAK,QAAQ,YAAY,CAAC,qBAAqB,KAAK,UAAU;AAChE,UAAK,GAAG,GAAG,KAAK,SAAS;AACzB,UAAK,QAAQ,YAAY,KAAK,UAAU,KAAK;;AAE/C,SAAK,WAAW;MACf,KAAK,QAAQ,KAAK;;qBAQH;AAClB,OAAI,KAAK,aAAa,KAAK,UAAU;AACnC,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;IACjB,MAAM,OAAO,KAAK;AAClB,SAAK,GAAG,GAAG,KAAK;AAChB,SAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,SAAK,WAAW;AAChB,SAAK,oBAAoB;;;sBAQR;AACnB,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;AAEnB,QAAK,WAAW;AAChB,QAAK,oBAAoB;;AAnEzB,MACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,OAE1B,MAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgG9B,SAAgB,aACd,IACA,SACoC;AAEpC,QADkB,IAAI,cAAc,IAAI,QAAQ,CAC/B"}
1
+ {"version":3,"file":"lite-debouncer.js","names":[],"sources":["../src/lite-debouncer.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite debounced function\n */\nexport interface LiteDebouncerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * The first call will execute immediately and the rest will wait the delay.\n * Defaults to false.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, debouncer: LiteDebouncer<TFn>) => void\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 before executing the function.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a debounced function.\n *\n * This is an alternative to the Debouncer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Debouncer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential debouncing functionality.\n *\n * Debouncing ensures that a function is only executed after a certain amount of time has passed\n * since its last invocation. This is useful for handling frequent events like window resizing,\n * scroll events, or input changes where you want to limit the rate of execution.\n *\n * The debounced function can be configured to execute either at the start of the delay period\n * (leading edge) or at the end (trailing edge, default). Each new call during the wait period\n * will reset the timer.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const debouncer = new LiteDebouncer((value: string) => {\n * saveToDatabase(value);\n * }, {\n * wait: 500,\n * onExecute: (args, debouncer) => {\n * console.log('Saved value:', args[0]);\n * }\n * });\n *\n * // Will only save after 500ms of no new input\n * inputElement.addEventListener('input', () => {\n * debouncer.maybeExecute(inputElement.value);\n * });\n * ```\n */\nexport class LiteDebouncer<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private canLeadingExecute = true\n\n constructor(\n public fn: TFn,\n public options: LiteDebouncerOptions<TFn>,\n ) {\n // Default trailing to true if neither leading nor trailing is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the debounced function.\n * If leading is true and this is the first call, executes immediately.\n * Otherwise, queues the execution for after the wait time.\n * Each new call resets the timer.\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n let didLeadingExecute = false\n\n if (this.options.leading && this.canLeadingExecute) {\n this.canLeadingExecute = false\n didLeadingExecute = true\n this.fn(...args)\n this.options.onExecute?.(args, this)\n }\n\n this.lastArgs = args\n\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n }\n\n this.timeoutId = setTimeout(() => {\n this.canLeadingExecute = true\n if (this.options.trailing && !didLeadingExecute && this.lastArgs) {\n this.fn(...this.lastArgs)\n this.options.onExecute?.(this.lastArgs, this)\n }\n this.lastArgs = undefined\n }, this.options.wait)\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.timeoutId && this.lastArgs) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n const args = this.lastArgs\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n }\n\n /**\n * Cancels any pending execution.\n * Clears the timeout and resets the internal state.\n */\n cancel = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n this.lastArgs = undefined\n this.canLeadingExecute = true\n }\n}\n\n/**\n * Creates a lightweight debounced function that delays invoking the provided function until after a specified wait time.\n * Multiple calls during the wait period will cancel previous pending invocations and reset the timer.\n *\n * This is an alternative to the debounce function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a debouncer with no external dependencies, devtools integration, or reactive state.\n *\n * If leading option is true, the function will execute immediately on the first call, then wait the delay\n * before allowing another execution.\n *\n * @example\n * ```ts\n * const debouncedSave = liteDebounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debouncedSave);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then waits\n * const debouncedSearch = liteDebounce((query: string) => {\n * performSearch(query);\n * }, { wait: 300, leading: true });\n * ```\n */\nexport function liteDebounce<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteDebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new LiteDebouncer(fn, options)\n return debouncer.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,IAAa,gBAAb,MAAoD;CAKlD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;2BAJmB;uBAqBZ,GAAG,SAAgC;GACjD,IAAI,oBAAoB;GAExB,IAAI,KAAK,QAAQ,WAAW,KAAK,mBAAmB;IAClD,KAAK,oBAAoB;IACzB,oBAAoB;IACpB,KAAK,GAAG,GAAG,KAAK;IAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;;GAGtC,KAAK,WAAW;GAEhB,IAAI,KAAK,WACP,aAAa,KAAK,UAAU;GAG9B,KAAK,YAAY,iBAAiB;IAChC,KAAK,oBAAoB;IACzB,IAAI,KAAK,QAAQ,YAAY,CAAC,qBAAqB,KAAK,UAAU;KAChE,KAAK,GAAG,GAAG,KAAK,SAAS;KACzB,KAAK,QAAQ,YAAY,KAAK,UAAU,KAAK;;IAE/C,KAAK,WAAW;MACf,KAAK,QAAQ,KAAK;;qBAQH;GAClB,IAAI,KAAK,aAAa,KAAK,UAAU;IACnC,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;IACjB,MAAM,OAAO,KAAK;IAClB,KAAK,GAAG,GAAG,KAAK;IAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;IACpC,KAAK,WAAW;IAChB,KAAK,oBAAoB;;;sBAQR;GACnB,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;GAEnB,KAAK,WAAW;GAChB,KAAK,oBAAoB;;EAnEzB,IACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAE1B,KAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgG9B,SAAgB,aACd,IACA,SACoC;CAEpC,OAAO,IADe,cAAc,IAAI,QACxB,CAAC"}
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/lite-queuer.ts
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lite-queuer.cjs","names":["fn: (item: TValue) => void","options: LiteQueuerOptions<TValue>","item: TValue | undefined"],"sources":["../src/lite-queuer.ts"],"sourcesContent":["/**\n * Position type for addItem and getNextItem operations.\n *\n * - 'front': Operate on the front of the queue (FIFO for getNextItem)\n * - 'back': Operate on the back of the queue (LIFO for getNextItem)\n */\nexport type QueuePosition = 'front' | 'back'\n\n/**\n * Options for configuring a lite queuer instance\n */\nexport interface LiteQueuerOptions<TValue> {\n /**\n * Default position to add items to the queue\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queue\n * Higher priority items will be processed first\n * Return undefined for items that should use positional ordering\n */\n getPriority?: (item: TValue) => number | undefined\n /**\n * Initial items to populate the queue with\n */\n initialItems?: Array<TValue>\n /**\n * Maximum number of items allowed in the queue\n */\n maxSize?: number\n /**\n * Whether the queuer should start processing items immediately\n * @default true\n */\n started?: boolean\n /**\n * Time in milliseconds to wait between processing items\n * @default 0\n */\n wait?: number\n}\n\n/**\n * A lightweight class that creates a queue for processing items.\n *\n * This is an alternative to the Queuer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Queuer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential queueing functionality.\n *\n * The queuer supports FIFO (First In First Out), LIFO (Last In First Out), and priority-based\n * processing of items. Items can be processed automatically with configurable wait times\n * between executions, or processed manually using the execute methods.\n *\n * Features included:\n * - Automatic or manual processing of items\n * - FIFO, LIFO, and priority-based ordering\n * - Queue size limits with item rejection\n * - Configurable wait times between processing\n * - Batch processing capabilities\n * - Start/stop processing control\n * - Callback support for monitoring execution, rejection, and state change events\n *\n * Features NOT included (compared to core Queuer):\n * - No TanStack Store state management\n * - No devtools integration\n * - No item expiration functionality (no onExpire callback)\n * - No dynamic options updates (setOptions)\n * - No detailed state tracking (execution counts, etc.)\n *\n * Queue behavior:\n * - Default: FIFO (add to back, process from front)\n * - LIFO: Configure addItemsTo: 'back', getItemsFrom: 'back'\n * - Priority: Provide getPriority function; higher values processed first\n *\n * @example\n * ```ts\n * // Basic FIFO queue\n * const queue = new LiteQueuer((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 100 });\n *\n * queue.addItem('task1');\n * queue.addItem('task2');\n * // Processes: task1, then task2 after 100ms delay\n * ```\n *\n * @example\n * ```ts\n * // Priority queue\n * const priorityQueue = new LiteQueuer((item: Task) => {\n * processTask(item);\n * }, {\n * getPriority: task => task.priority,\n * wait: 500\n * });\n *\n * priorityQueue.addItem({ name: 'low', priority: 1 });\n * priorityQueue.addItem({ name: 'high', priority: 10 });\n * // Processes high priority task first\n * ```\n */\nexport class LiteQueuer<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private isRunning = true\n private pendingTick = false\n\n constructor(\n public fn: (item: TValue) => void,\n public options: LiteQueuerOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.addItemsTo = this.options.addItemsTo ?? 'back'\n this.options.getItemsFrom = this.options.getItemsFrom ?? 'front'\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? 0\n\n this.isRunning = this.options.started\n\n // Add initial items if provided\n if (this.options.initialItems) {\n for (const item of this.options.initialItems) {\n this.addItem(item, this.options.addItemsTo, false)\n }\n }\n\n // Start processing if enabled and has items\n if (this.isRunning && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Number of items currently in the queue\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the queue is empty\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the queue is currently running (auto-processing items)\n */\n get isQueueRunning(): boolean {\n return this.isRunning\n }\n\n /**\n * Adds an item to the queue. If the queue is full, the item is rejected.\n * Items can be inserted at the front or back, and priority ordering is applied if getPriority is configured.\n *\n * Returns true if the item was added, false if the queue is full.\n *\n * @example\n * ```ts\n * queue.addItem('task1'); // Add to default position (back)\n * queue.addItem('task2', 'front'); // Add to front\n * ```\n */\n addItem = (\n item: TValue,\n position: QueuePosition = this.options.addItemsTo!,\n startProcessing: boolean = true,\n ): boolean => {\n // Check size limit\n if (this.items.length >= this.options.maxSize!) {\n return false\n }\n\n // Handle priority insertion\n if (this.options.getPriority) {\n const priority = this.options.getPriority(item)\n if (priority !== undefined) {\n // Find insertion point for priority\n const insertIndex = this.items.findIndex((existing) => {\n const existingPriority = this.options.getPriority!(existing)\n // Treat undefined priority as negative infinity for comparison\n const effectivePriority = existingPriority ?? -Infinity\n return effectivePriority < priority\n })\n\n if (insertIndex === -1) {\n this.items.push(item)\n } else {\n this.items.splice(insertIndex, 0, item)\n }\n } else {\n // No priority, use position\n this.insertAtPosition(item, position)\n }\n } else {\n // No priority function, use position\n this.insertAtPosition(item, position)\n }\n\n // Start processing if running and not already processing\n if (startProcessing && this.isRunning && !this.pendingTick) {\n this.tick()\n }\n\n return true\n }\n\n private insertAtPosition = (item: TValue, position: QueuePosition): void => {\n if (position === 'front') {\n this.items.unshift(item)\n } else {\n this.items.push(item)\n }\n }\n\n /**\n * Removes and returns the next item from the queue without executing the function.\n * Use for manual queue management. Normally, use execute() to process items.\n *\n * @example\n * ```ts\n * const nextItem = queue.getNextItem(); // Get from default position (front)\n * const lastItem = queue.getNextItem('back'); // Get from back (LIFO)\n * ```\n */\n getNextItem = (\n position: QueuePosition = this.options.getItemsFrom!,\n ): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n let item: TValue | undefined\n\n // When priority function is provided, always get from front (highest priority)\n if (this.options.getPriority || position === 'front') {\n item = this.items.shift()\n } else {\n item = this.items.pop()\n }\n\n return item\n }\n\n /**\n * Removes and returns the next item from the queue and processes it using the provided function.\n *\n * @example\n * ```ts\n * queue.execute(); // Execute from default position\n * queue.execute('back'); // Execute from back (LIFO)\n * ```\n */\n execute = (position?: QueuePosition): TValue | undefined => {\n const item = this.getNextItem(position)\n if (item !== undefined) {\n this.fn(item)\n }\n return item\n }\n\n /**\n * Internal method that processes items in the queue with wait intervals\n */\n private tick = (): void => {\n if (!this.isRunning) {\n this.pendingTick = false\n return\n }\n\n this.pendingTick = true\n\n // Process items while queue is not empty\n while (this.items.length > 0) {\n const item = this.execute(this.options.getItemsFrom)\n if (item === undefined) {\n break\n }\n\n const wait = this.options.wait!\n if (wait > 0) {\n // Schedule next processing after wait time\n this.timeoutId = setTimeout(() => this.tick(), wait)\n return\n }\n\n // No wait time, continue processing immediately\n }\n\n this.pendingTick = false\n }\n\n /**\n * Starts processing items in the queue. If already running, does nothing.\n */\n start = (): void => {\n this.isRunning = true\n if (!this.pendingTick && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Stops processing items in the queue. Does not clear the queue.\n */\n stop = (): void => {\n this.clearTimeout()\n this.isRunning = false\n this.pendingTick = false\n }\n\n /**\n * Clears any pending timeout\n */\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Returns the next item in the queue without removing it.\n *\n * @example\n * ```ts\n * const next = queue.peekNextItem(); // Peek at front\n * const last = queue.peekNextItem('back'); // Peek at back\n * ```\n */\n peekNextItem = (position: QueuePosition = 'front'): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n if (this.options.getPriority || position === 'front') {\n return this.items[0]\n } else {\n return this.items[this.items.length - 1]\n }\n }\n\n /**\n * Returns a copy of all items in the queue.\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n /**\n * Processes a specified number of items immediately with no wait time.\n * If no numberOfItems is provided, all items will be processed.\n *\n * @example\n * ```ts\n * queue.flush(); // Process all items immediately\n * queue.flush(3); // Process next 3 items immediately\n * ```\n */\n flush = (\n numberOfItems: number = this.items.length,\n position?: QueuePosition,\n ): void => {\n this.clearTimeout() // Clear any pending timeout\n for (let i = 0; i < numberOfItems && this.items.length > 0; i++) {\n this.execute(position)\n }\n // Restart normal processing if still running and has items\n if (this.isRunning && this.items.length > 0 && !this.pendingTick) {\n this.tick()\n }\n }\n\n /**\n * Processes all items in the queue as a batch using the provided function.\n * The queue is cleared after processing.\n *\n * @example\n * ```ts\n * queue.flushAsBatch((items) => {\n * console.log('Processing batch:', items);\n * // Process all items together\n * });\n * ```\n */\n flushAsBatch = (batchFunction: (items: Array<TValue>) => void): void => {\n const items = this.peekAllItems()\n this.clear()\n batchFunction(items)\n }\n\n /**\n * Removes all items from the queue. Does not affect items being processed.\n */\n clear = (): void => {\n this.items = []\n }\n}\n\n/**\n * Creates a lightweight queue that processes items using the provided function.\n *\n * This is an alternative to the queue function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a queuer with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const processItem = liteQueue((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 1000 });\n *\n * processItem('task1');\n * processItem('task2');\n * // Processes each item with 1 second delay between them\n * ```\n */\nexport function liteQueue<TValue>(\n fn: (item: TValue) => void,\n options: LiteQueuerOptions<TValue> = {},\n): (item: TValue) => boolean {\n const queuer = new LiteQueuer(fn, options)\n return (item: TValue) => queuer.addItem(item)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lite-queuer.cjs","names":[],"sources":["../src/lite-queuer.ts"],"sourcesContent":["/**\n * Position type for addItem and getNextItem operations.\n *\n * - 'front': Operate on the front of the queue (FIFO for getNextItem)\n * - 'back': Operate on the back of the queue (LIFO for getNextItem)\n */\nexport type QueuePosition = 'front' | 'back'\n\n/**\n * Options for configuring a lite queuer instance\n */\nexport interface LiteQueuerOptions<TValue> {\n /**\n * Default position to add items to the queue\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queue\n * Higher priority items will be processed first\n * Return undefined for items that should use positional ordering\n */\n getPriority?: (item: TValue) => number | undefined\n /**\n * Initial items to populate the queue with\n */\n initialItems?: Array<TValue>\n /**\n * Maximum number of items allowed in the queue\n */\n maxSize?: number\n /**\n * Whether the queuer should start processing items immediately\n * @default true\n */\n started?: boolean\n /**\n * Time in milliseconds to wait between processing items\n * @default 0\n */\n wait?: number\n}\n\n/**\n * A lightweight class that creates a queue for processing items.\n *\n * This is an alternative to the Queuer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Queuer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential queueing functionality.\n *\n * The queuer supports FIFO (First In First Out), LIFO (Last In First Out), and priority-based\n * processing of items. Items can be processed automatically with configurable wait times\n * between executions, or processed manually using the execute methods.\n *\n * Features included:\n * - Automatic or manual processing of items\n * - FIFO, LIFO, and priority-based ordering\n * - Queue size limits with item rejection\n * - Configurable wait times between processing\n * - Batch processing capabilities\n * - Start/stop processing control\n * - Callback support for monitoring execution, rejection, and state change events\n *\n * Features NOT included (compared to core Queuer):\n * - No TanStack Store state management\n * - No devtools integration\n * - No item expiration functionality (no onExpire callback)\n * - No dynamic options updates (setOptions)\n * - No detailed state tracking (execution counts, etc.)\n *\n * Queue behavior:\n * - Default: FIFO (add to back, process from front)\n * - LIFO: Configure addItemsTo: 'back', getItemsFrom: 'back'\n * - Priority: Provide getPriority function; higher values processed first\n *\n * @example\n * ```ts\n * // Basic FIFO queue\n * const queue = new LiteQueuer((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 100 });\n *\n * queue.addItem('task1');\n * queue.addItem('task2');\n * // Processes: task1, then task2 after 100ms delay\n * ```\n *\n * @example\n * ```ts\n * // Priority queue\n * const priorityQueue = new LiteQueuer((item: Task) => {\n * processTask(item);\n * }, {\n * getPriority: task => task.priority,\n * wait: 500\n * });\n *\n * priorityQueue.addItem({ name: 'low', priority: 1 });\n * priorityQueue.addItem({ name: 'high', priority: 10 });\n * // Processes high priority task first\n * ```\n */\nexport class LiteQueuer<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private isRunning = true\n private pendingTick = false\n\n constructor(\n public fn: (item: TValue) => void,\n public options: LiteQueuerOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.addItemsTo = this.options.addItemsTo ?? 'back'\n this.options.getItemsFrom = this.options.getItemsFrom ?? 'front'\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? 0\n\n this.isRunning = this.options.started\n\n // Add initial items if provided\n if (this.options.initialItems) {\n for (const item of this.options.initialItems) {\n this.addItem(item, this.options.addItemsTo, false)\n }\n }\n\n // Start processing if enabled and has items\n if (this.isRunning && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Number of items currently in the queue\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the queue is empty\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the queue is currently running (auto-processing items)\n */\n get isQueueRunning(): boolean {\n return this.isRunning\n }\n\n /**\n * Adds an item to the queue. If the queue is full, the item is rejected.\n * Items can be inserted at the front or back, and priority ordering is applied if getPriority is configured.\n *\n * Returns true if the item was added, false if the queue is full.\n *\n * @example\n * ```ts\n * queue.addItem('task1'); // Add to default position (back)\n * queue.addItem('task2', 'front'); // Add to front\n * ```\n */\n addItem = (\n item: TValue,\n position: QueuePosition = this.options.addItemsTo!,\n startProcessing: boolean = true,\n ): boolean => {\n // Check size limit\n if (this.items.length >= this.options.maxSize!) {\n return false\n }\n\n // Handle priority insertion\n if (this.options.getPriority) {\n const priority = this.options.getPriority(item)\n if (priority !== undefined) {\n // Find insertion point for priority\n const insertIndex = this.items.findIndex((existing) => {\n const existingPriority = this.options.getPriority!(existing)\n // Treat undefined priority as negative infinity for comparison\n const effectivePriority = existingPriority ?? -Infinity\n return effectivePriority < priority\n })\n\n if (insertIndex === -1) {\n this.items.push(item)\n } else {\n this.items.splice(insertIndex, 0, item)\n }\n } else {\n // No priority, use position\n this.insertAtPosition(item, position)\n }\n } else {\n // No priority function, use position\n this.insertAtPosition(item, position)\n }\n\n // Start processing if running and not already processing\n if (startProcessing && this.isRunning && !this.pendingTick) {\n this.tick()\n }\n\n return true\n }\n\n private insertAtPosition = (item: TValue, position: QueuePosition): void => {\n if (position === 'front') {\n this.items.unshift(item)\n } else {\n this.items.push(item)\n }\n }\n\n /**\n * Removes and returns the next item from the queue without executing the function.\n * Use for manual queue management. Normally, use execute() to process items.\n *\n * @example\n * ```ts\n * const nextItem = queue.getNextItem(); // Get from default position (front)\n * const lastItem = queue.getNextItem('back'); // Get from back (LIFO)\n * ```\n */\n getNextItem = (\n position: QueuePosition = this.options.getItemsFrom!,\n ): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n let item: TValue | undefined\n\n // When priority function is provided, always get from front (highest priority)\n if (this.options.getPriority || position === 'front') {\n item = this.items.shift()\n } else {\n item = this.items.pop()\n }\n\n return item\n }\n\n /**\n * Removes and returns the next item from the queue and processes it using the provided function.\n *\n * @example\n * ```ts\n * queue.execute(); // Execute from default position\n * queue.execute('back'); // Execute from back (LIFO)\n * ```\n */\n execute = (position?: QueuePosition): TValue | undefined => {\n const item = this.getNextItem(position)\n if (item !== undefined) {\n this.fn(item)\n }\n return item\n }\n\n /**\n * Internal method that processes items in the queue with wait intervals\n */\n private tick = (): void => {\n if (!this.isRunning) {\n this.pendingTick = false\n return\n }\n\n this.pendingTick = true\n\n // Process items while queue is not empty\n while (this.items.length > 0) {\n const item = this.execute(this.options.getItemsFrom)\n if (item === undefined) {\n break\n }\n\n const wait = this.options.wait!\n if (wait > 0) {\n // Schedule next processing after wait time\n this.timeoutId = setTimeout(() => this.tick(), wait)\n return\n }\n\n // No wait time, continue processing immediately\n }\n\n this.pendingTick = false\n }\n\n /**\n * Starts processing items in the queue. If already running, does nothing.\n */\n start = (): void => {\n this.isRunning = true\n if (!this.pendingTick && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Stops processing items in the queue. Does not clear the queue.\n */\n stop = (): void => {\n this.clearTimeout()\n this.isRunning = false\n this.pendingTick = false\n }\n\n /**\n * Clears any pending timeout\n */\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Returns the next item in the queue without removing it.\n *\n * @example\n * ```ts\n * const next = queue.peekNextItem(); // Peek at front\n * const last = queue.peekNextItem('back'); // Peek at back\n * ```\n */\n peekNextItem = (position: QueuePosition = 'front'): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n if (this.options.getPriority || position === 'front') {\n return this.items[0]\n } else {\n return this.items[this.items.length - 1]\n }\n }\n\n /**\n * Returns a copy of all items in the queue.\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n /**\n * Processes a specified number of items immediately with no wait time.\n * If no numberOfItems is provided, all items will be processed.\n *\n * @example\n * ```ts\n * queue.flush(); // Process all items immediately\n * queue.flush(3); // Process next 3 items immediately\n * ```\n */\n flush = (\n numberOfItems: number = this.items.length,\n position?: QueuePosition,\n ): void => {\n this.clearTimeout() // Clear any pending timeout\n for (let i = 0; i < numberOfItems && this.items.length > 0; i++) {\n this.execute(position)\n }\n // Restart normal processing if still running and has items\n if (this.isRunning && this.items.length > 0 && !this.pendingTick) {\n this.tick()\n }\n }\n\n /**\n * Processes all items in the queue as a batch using the provided function.\n * The queue is cleared after processing.\n *\n * @example\n * ```ts\n * queue.flushAsBatch((items) => {\n * console.log('Processing batch:', items);\n * // Process all items together\n * });\n * ```\n */\n flushAsBatch = (batchFunction: (items: Array<TValue>) => void): void => {\n const items = this.peekAllItems()\n this.clear()\n batchFunction(items)\n }\n\n /**\n * Removes all items from the queue. Does not affect items being processed.\n */\n clear = (): void => {\n this.items = []\n }\n}\n\n/**\n * Creates a lightweight queue that processes items using the provided function.\n *\n * This is an alternative to the queue function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a queuer with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const processItem = liteQueue((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 1000 });\n *\n * processItem('task1');\n * processItem('task2');\n * // Processes each item with 1 second delay between them\n * ```\n */\nexport function liteQueue<TValue>(\n fn: (item: TValue) => void,\n options: LiteQueuerOptions<TValue> = {},\n): (item: TValue) => boolean {\n const queuer = new LiteQueuer(fn, options)\n return (item: TValue) => queuer.addItem(item)\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lite-queuer.js","names":["fn: (item: TValue) => void","options: LiteQueuerOptions<TValue>","item: TValue | undefined"],"sources":["../src/lite-queuer.ts"],"sourcesContent":["/**\n * Position type for addItem and getNextItem operations.\n *\n * - 'front': Operate on the front of the queue (FIFO for getNextItem)\n * - 'back': Operate on the back of the queue (LIFO for getNextItem)\n */\nexport type QueuePosition = 'front' | 'back'\n\n/**\n * Options for configuring a lite queuer instance\n */\nexport interface LiteQueuerOptions<TValue> {\n /**\n * Default position to add items to the queue\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queue\n * Higher priority items will be processed first\n * Return undefined for items that should use positional ordering\n */\n getPriority?: (item: TValue) => number | undefined\n /**\n * Initial items to populate the queue with\n */\n initialItems?: Array<TValue>\n /**\n * Maximum number of items allowed in the queue\n */\n maxSize?: number\n /**\n * Whether the queuer should start processing items immediately\n * @default true\n */\n started?: boolean\n /**\n * Time in milliseconds to wait between processing items\n * @default 0\n */\n wait?: number\n}\n\n/**\n * A lightweight class that creates a queue for processing items.\n *\n * This is an alternative to the Queuer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Queuer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential queueing functionality.\n *\n * The queuer supports FIFO (First In First Out), LIFO (Last In First Out), and priority-based\n * processing of items. Items can be processed automatically with configurable wait times\n * between executions, or processed manually using the execute methods.\n *\n * Features included:\n * - Automatic or manual processing of items\n * - FIFO, LIFO, and priority-based ordering\n * - Queue size limits with item rejection\n * - Configurable wait times between processing\n * - Batch processing capabilities\n * - Start/stop processing control\n * - Callback support for monitoring execution, rejection, and state change events\n *\n * Features NOT included (compared to core Queuer):\n * - No TanStack Store state management\n * - No devtools integration\n * - No item expiration functionality (no onExpire callback)\n * - No dynamic options updates (setOptions)\n * - No detailed state tracking (execution counts, etc.)\n *\n * Queue behavior:\n * - Default: FIFO (add to back, process from front)\n * - LIFO: Configure addItemsTo: 'back', getItemsFrom: 'back'\n * - Priority: Provide getPriority function; higher values processed first\n *\n * @example\n * ```ts\n * // Basic FIFO queue\n * const queue = new LiteQueuer((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 100 });\n *\n * queue.addItem('task1');\n * queue.addItem('task2');\n * // Processes: task1, then task2 after 100ms delay\n * ```\n *\n * @example\n * ```ts\n * // Priority queue\n * const priorityQueue = new LiteQueuer((item: Task) => {\n * processTask(item);\n * }, {\n * getPriority: task => task.priority,\n * wait: 500\n * });\n *\n * priorityQueue.addItem({ name: 'low', priority: 1 });\n * priorityQueue.addItem({ name: 'high', priority: 10 });\n * // Processes high priority task first\n * ```\n */\nexport class LiteQueuer<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private isRunning = true\n private pendingTick = false\n\n constructor(\n public fn: (item: TValue) => void,\n public options: LiteQueuerOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.addItemsTo = this.options.addItemsTo ?? 'back'\n this.options.getItemsFrom = this.options.getItemsFrom ?? 'front'\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? 0\n\n this.isRunning = this.options.started\n\n // Add initial items if provided\n if (this.options.initialItems) {\n for (const item of this.options.initialItems) {\n this.addItem(item, this.options.addItemsTo, false)\n }\n }\n\n // Start processing if enabled and has items\n if (this.isRunning && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Number of items currently in the queue\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the queue is empty\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the queue is currently running (auto-processing items)\n */\n get isQueueRunning(): boolean {\n return this.isRunning\n }\n\n /**\n * Adds an item to the queue. If the queue is full, the item is rejected.\n * Items can be inserted at the front or back, and priority ordering is applied if getPriority is configured.\n *\n * Returns true if the item was added, false if the queue is full.\n *\n * @example\n * ```ts\n * queue.addItem('task1'); // Add to default position (back)\n * queue.addItem('task2', 'front'); // Add to front\n * ```\n */\n addItem = (\n item: TValue,\n position: QueuePosition = this.options.addItemsTo!,\n startProcessing: boolean = true,\n ): boolean => {\n // Check size limit\n if (this.items.length >= this.options.maxSize!) {\n return false\n }\n\n // Handle priority insertion\n if (this.options.getPriority) {\n const priority = this.options.getPriority(item)\n if (priority !== undefined) {\n // Find insertion point for priority\n const insertIndex = this.items.findIndex((existing) => {\n const existingPriority = this.options.getPriority!(existing)\n // Treat undefined priority as negative infinity for comparison\n const effectivePriority = existingPriority ?? -Infinity\n return effectivePriority < priority\n })\n\n if (insertIndex === -1) {\n this.items.push(item)\n } else {\n this.items.splice(insertIndex, 0, item)\n }\n } else {\n // No priority, use position\n this.insertAtPosition(item, position)\n }\n } else {\n // No priority function, use position\n this.insertAtPosition(item, position)\n }\n\n // Start processing if running and not already processing\n if (startProcessing && this.isRunning && !this.pendingTick) {\n this.tick()\n }\n\n return true\n }\n\n private insertAtPosition = (item: TValue, position: QueuePosition): void => {\n if (position === 'front') {\n this.items.unshift(item)\n } else {\n this.items.push(item)\n }\n }\n\n /**\n * Removes and returns the next item from the queue without executing the function.\n * Use for manual queue management. Normally, use execute() to process items.\n *\n * @example\n * ```ts\n * const nextItem = queue.getNextItem(); // Get from default position (front)\n * const lastItem = queue.getNextItem('back'); // Get from back (LIFO)\n * ```\n */\n getNextItem = (\n position: QueuePosition = this.options.getItemsFrom!,\n ): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n let item: TValue | undefined\n\n // When priority function is provided, always get from front (highest priority)\n if (this.options.getPriority || position === 'front') {\n item = this.items.shift()\n } else {\n item = this.items.pop()\n }\n\n return item\n }\n\n /**\n * Removes and returns the next item from the queue and processes it using the provided function.\n *\n * @example\n * ```ts\n * queue.execute(); // Execute from default position\n * queue.execute('back'); // Execute from back (LIFO)\n * ```\n */\n execute = (position?: QueuePosition): TValue | undefined => {\n const item = this.getNextItem(position)\n if (item !== undefined) {\n this.fn(item)\n }\n return item\n }\n\n /**\n * Internal method that processes items in the queue with wait intervals\n */\n private tick = (): void => {\n if (!this.isRunning) {\n this.pendingTick = false\n return\n }\n\n this.pendingTick = true\n\n // Process items while queue is not empty\n while (this.items.length > 0) {\n const item = this.execute(this.options.getItemsFrom)\n if (item === undefined) {\n break\n }\n\n const wait = this.options.wait!\n if (wait > 0) {\n // Schedule next processing after wait time\n this.timeoutId = setTimeout(() => this.tick(), wait)\n return\n }\n\n // No wait time, continue processing immediately\n }\n\n this.pendingTick = false\n }\n\n /**\n * Starts processing items in the queue. If already running, does nothing.\n */\n start = (): void => {\n this.isRunning = true\n if (!this.pendingTick && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Stops processing items in the queue. Does not clear the queue.\n */\n stop = (): void => {\n this.clearTimeout()\n this.isRunning = false\n this.pendingTick = false\n }\n\n /**\n * Clears any pending timeout\n */\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Returns the next item in the queue without removing it.\n *\n * @example\n * ```ts\n * const next = queue.peekNextItem(); // Peek at front\n * const last = queue.peekNextItem('back'); // Peek at back\n * ```\n */\n peekNextItem = (position: QueuePosition = 'front'): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n if (this.options.getPriority || position === 'front') {\n return this.items[0]\n } else {\n return this.items[this.items.length - 1]\n }\n }\n\n /**\n * Returns a copy of all items in the queue.\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n /**\n * Processes a specified number of items immediately with no wait time.\n * If no numberOfItems is provided, all items will be processed.\n *\n * @example\n * ```ts\n * queue.flush(); // Process all items immediately\n * queue.flush(3); // Process next 3 items immediately\n * ```\n */\n flush = (\n numberOfItems: number = this.items.length,\n position?: QueuePosition,\n ): void => {\n this.clearTimeout() // Clear any pending timeout\n for (let i = 0; i < numberOfItems && this.items.length > 0; i++) {\n this.execute(position)\n }\n // Restart normal processing if still running and has items\n if (this.isRunning && this.items.length > 0 && !this.pendingTick) {\n this.tick()\n }\n }\n\n /**\n * Processes all items in the queue as a batch using the provided function.\n * The queue is cleared after processing.\n *\n * @example\n * ```ts\n * queue.flushAsBatch((items) => {\n * console.log('Processing batch:', items);\n * // Process all items together\n * });\n * ```\n */\n flushAsBatch = (batchFunction: (items: Array<TValue>) => void): void => {\n const items = this.peekAllItems()\n this.clear()\n batchFunction(items)\n }\n\n /**\n * Removes all items from the queue. Does not affect items being processed.\n */\n clear = (): void => {\n this.items = []\n }\n}\n\n/**\n * Creates a lightweight queue that processes items using the provided function.\n *\n * This is an alternative to the queue function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a queuer with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const processItem = liteQueue((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 1000 });\n *\n * processItem('task1');\n * processItem('task2');\n * // Processes each item with 1 second delay between them\n * ```\n */\nexport function liteQueue<TValue>(\n fn: (item: TValue) => void,\n options: LiteQueuerOptions<TValue> = {},\n): (item: TValue) => boolean {\n const queuer = new LiteQueuer(fn, options)\n return (item: TValue) => queuer.addItem(item)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lite-queuer.js","names":[],"sources":["../src/lite-queuer.ts"],"sourcesContent":["/**\n * Position type for addItem and getNextItem operations.\n *\n * - 'front': Operate on the front of the queue (FIFO for getNextItem)\n * - 'back': Operate on the back of the queue (LIFO for getNextItem)\n */\nexport type QueuePosition = 'front' | 'back'\n\n/**\n * Options for configuring a lite queuer instance\n */\nexport interface LiteQueuerOptions<TValue> {\n /**\n * Default position to add items to the queue\n * @default 'back'\n */\n addItemsTo?: QueuePosition\n /**\n * Default position to get items from during processing\n * @default 'front'\n */\n getItemsFrom?: QueuePosition\n /**\n * Function to determine priority of items in the queue\n * Higher priority items will be processed first\n * Return undefined for items that should use positional ordering\n */\n getPriority?: (item: TValue) => number | undefined\n /**\n * Initial items to populate the queue with\n */\n initialItems?: Array<TValue>\n /**\n * Maximum number of items allowed in the queue\n */\n maxSize?: number\n /**\n * Whether the queuer should start processing items immediately\n * @default true\n */\n started?: boolean\n /**\n * Time in milliseconds to wait between processing items\n * @default 0\n */\n wait?: number\n}\n\n/**\n * A lightweight class that creates a queue for processing items.\n *\n * This is an alternative to the Queuer in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Queuer,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * no callbacks, and provides only essential queueing functionality.\n *\n * The queuer supports FIFO (First In First Out), LIFO (Last In First Out), and priority-based\n * processing of items. Items can be processed automatically with configurable wait times\n * between executions, or processed manually using the execute methods.\n *\n * Features included:\n * - Automatic or manual processing of items\n * - FIFO, LIFO, and priority-based ordering\n * - Queue size limits with item rejection\n * - Configurable wait times between processing\n * - Batch processing capabilities\n * - Start/stop processing control\n * - Callback support for monitoring execution, rejection, and state change events\n *\n * Features NOT included (compared to core Queuer):\n * - No TanStack Store state management\n * - No devtools integration\n * - No item expiration functionality (no onExpire callback)\n * - No dynamic options updates (setOptions)\n * - No detailed state tracking (execution counts, etc.)\n *\n * Queue behavior:\n * - Default: FIFO (add to back, process from front)\n * - LIFO: Configure addItemsTo: 'back', getItemsFrom: 'back'\n * - Priority: Provide getPriority function; higher values processed first\n *\n * @example\n * ```ts\n * // Basic FIFO queue\n * const queue = new LiteQueuer((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 100 });\n *\n * queue.addItem('task1');\n * queue.addItem('task2');\n * // Processes: task1, then task2 after 100ms delay\n * ```\n *\n * @example\n * ```ts\n * // Priority queue\n * const priorityQueue = new LiteQueuer((item: Task) => {\n * processTask(item);\n * }, {\n * getPriority: task => task.priority,\n * wait: 500\n * });\n *\n * priorityQueue.addItem({ name: 'low', priority: 1 });\n * priorityQueue.addItem({ name: 'high', priority: 10 });\n * // Processes high priority task first\n * ```\n */\nexport class LiteQueuer<TValue> {\n private items: Array<TValue> = []\n private timeoutId: NodeJS.Timeout | null = null\n private isRunning = true\n private pendingTick = false\n\n constructor(\n public fn: (item: TValue) => void,\n public options: LiteQueuerOptions<TValue> = {},\n ) {\n // Set defaults\n this.options.addItemsTo = this.options.addItemsTo ?? 'back'\n this.options.getItemsFrom = this.options.getItemsFrom ?? 'front'\n this.options.maxSize = this.options.maxSize ?? Infinity\n this.options.started = this.options.started ?? true\n this.options.wait = this.options.wait ?? 0\n\n this.isRunning = this.options.started\n\n // Add initial items if provided\n if (this.options.initialItems) {\n for (const item of this.options.initialItems) {\n this.addItem(item, this.options.addItemsTo, false)\n }\n }\n\n // Start processing if enabled and has items\n if (this.isRunning && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Number of items currently in the queue\n */\n get size(): number {\n return this.items.length\n }\n\n /**\n * Whether the queue is empty\n */\n get isEmpty(): boolean {\n return this.items.length === 0\n }\n\n /**\n * Whether the queue is currently running (auto-processing items)\n */\n get isQueueRunning(): boolean {\n return this.isRunning\n }\n\n /**\n * Adds an item to the queue. If the queue is full, the item is rejected.\n * Items can be inserted at the front or back, and priority ordering is applied if getPriority is configured.\n *\n * Returns true if the item was added, false if the queue is full.\n *\n * @example\n * ```ts\n * queue.addItem('task1'); // Add to default position (back)\n * queue.addItem('task2', 'front'); // Add to front\n * ```\n */\n addItem = (\n item: TValue,\n position: QueuePosition = this.options.addItemsTo!,\n startProcessing: boolean = true,\n ): boolean => {\n // Check size limit\n if (this.items.length >= this.options.maxSize!) {\n return false\n }\n\n // Handle priority insertion\n if (this.options.getPriority) {\n const priority = this.options.getPriority(item)\n if (priority !== undefined) {\n // Find insertion point for priority\n const insertIndex = this.items.findIndex((existing) => {\n const existingPriority = this.options.getPriority!(existing)\n // Treat undefined priority as negative infinity for comparison\n const effectivePriority = existingPriority ?? -Infinity\n return effectivePriority < priority\n })\n\n if (insertIndex === -1) {\n this.items.push(item)\n } else {\n this.items.splice(insertIndex, 0, item)\n }\n } else {\n // No priority, use position\n this.insertAtPosition(item, position)\n }\n } else {\n // No priority function, use position\n this.insertAtPosition(item, position)\n }\n\n // Start processing if running and not already processing\n if (startProcessing && this.isRunning && !this.pendingTick) {\n this.tick()\n }\n\n return true\n }\n\n private insertAtPosition = (item: TValue, position: QueuePosition): void => {\n if (position === 'front') {\n this.items.unshift(item)\n } else {\n this.items.push(item)\n }\n }\n\n /**\n * Removes and returns the next item from the queue without executing the function.\n * Use for manual queue management. Normally, use execute() to process items.\n *\n * @example\n * ```ts\n * const nextItem = queue.getNextItem(); // Get from default position (front)\n * const lastItem = queue.getNextItem('back'); // Get from back (LIFO)\n * ```\n */\n getNextItem = (\n position: QueuePosition = this.options.getItemsFrom!,\n ): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n let item: TValue | undefined\n\n // When priority function is provided, always get from front (highest priority)\n if (this.options.getPriority || position === 'front') {\n item = this.items.shift()\n } else {\n item = this.items.pop()\n }\n\n return item\n }\n\n /**\n * Removes and returns the next item from the queue and processes it using the provided function.\n *\n * @example\n * ```ts\n * queue.execute(); // Execute from default position\n * queue.execute('back'); // Execute from back (LIFO)\n * ```\n */\n execute = (position?: QueuePosition): TValue | undefined => {\n const item = this.getNextItem(position)\n if (item !== undefined) {\n this.fn(item)\n }\n return item\n }\n\n /**\n * Internal method that processes items in the queue with wait intervals\n */\n private tick = (): void => {\n if (!this.isRunning) {\n this.pendingTick = false\n return\n }\n\n this.pendingTick = true\n\n // Process items while queue is not empty\n while (this.items.length > 0) {\n const item = this.execute(this.options.getItemsFrom)\n if (item === undefined) {\n break\n }\n\n const wait = this.options.wait!\n if (wait > 0) {\n // Schedule next processing after wait time\n this.timeoutId = setTimeout(() => this.tick(), wait)\n return\n }\n\n // No wait time, continue processing immediately\n }\n\n this.pendingTick = false\n }\n\n /**\n * Starts processing items in the queue. If already running, does nothing.\n */\n start = (): void => {\n this.isRunning = true\n if (!this.pendingTick && this.items.length > 0) {\n this.tick()\n }\n }\n\n /**\n * Stops processing items in the queue. Does not clear the queue.\n */\n stop = (): void => {\n this.clearTimeout()\n this.isRunning = false\n this.pendingTick = false\n }\n\n /**\n * Clears any pending timeout\n */\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n }\n\n /**\n * Returns the next item in the queue without removing it.\n *\n * @example\n * ```ts\n * const next = queue.peekNextItem(); // Peek at front\n * const last = queue.peekNextItem('back'); // Peek at back\n * ```\n */\n peekNextItem = (position: QueuePosition = 'front'): TValue | undefined => {\n if (this.items.length === 0) {\n return undefined\n }\n\n if (this.options.getPriority || position === 'front') {\n return this.items[0]\n } else {\n return this.items[this.items.length - 1]\n }\n }\n\n /**\n * Returns a copy of all items in the queue.\n */\n peekAllItems = (): Array<TValue> => {\n return [...this.items]\n }\n\n /**\n * Processes a specified number of items immediately with no wait time.\n * If no numberOfItems is provided, all items will be processed.\n *\n * @example\n * ```ts\n * queue.flush(); // Process all items immediately\n * queue.flush(3); // Process next 3 items immediately\n * ```\n */\n flush = (\n numberOfItems: number = this.items.length,\n position?: QueuePosition,\n ): void => {\n this.clearTimeout() // Clear any pending timeout\n for (let i = 0; i < numberOfItems && this.items.length > 0; i++) {\n this.execute(position)\n }\n // Restart normal processing if still running and has items\n if (this.isRunning && this.items.length > 0 && !this.pendingTick) {\n this.tick()\n }\n }\n\n /**\n * Processes all items in the queue as a batch using the provided function.\n * The queue is cleared after processing.\n *\n * @example\n * ```ts\n * queue.flushAsBatch((items) => {\n * console.log('Processing batch:', items);\n * // Process all items together\n * });\n * ```\n */\n flushAsBatch = (batchFunction: (items: Array<TValue>) => void): void => {\n const items = this.peekAllItems()\n this.clear()\n batchFunction(items)\n }\n\n /**\n * Removes all items from the queue. Does not affect items being processed.\n */\n clear = (): void => {\n this.items = []\n }\n}\n\n/**\n * Creates a lightweight queue that processes items using the provided function.\n *\n * This is an alternative to the queue function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a queuer with no external dependencies, devtools integration, or reactive state.\n *\n * @example\n * ```ts\n * const processItem = liteQueue((item: string) => {\n * console.log('Processing:', item);\n * }, { wait: 1000 });\n *\n * processItem('task1');\n * processItem('task2');\n * // Processes each item with 1 second delay between them\n * ```\n */\nexport function liteQueue<TValue>(\n fn: (item: TValue) => void,\n options: LiteQueuerOptions<TValue> = {},\n): (item: TValue) => boolean {\n const queuer = new LiteQueuer(fn, options)\n return (item: TValue) => queuer.addItem(item)\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/lite-rate-limiter.ts
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lite-rate-limiter.cjs","names":["fn: TFn","options: LiteRateLimiterOptions<TFn>"],"sources":["../src/lite-rate-limiter.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite rate-limited function\n */\nexport interface LiteRateLimiterOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Maximum number of executions allowed within the time window.\n */\n limit: number\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Optional callback function that is called when an execution is rejected due to rate limiting\n */\n onReject?: (rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Time window in milliseconds within which the limit applies.\n */\n window: number\n /**\n * Type of window to use for rate limiting\n * - 'fixed': Uses a fixed window that resets after the window period\n * - 'sliding': Uses a sliding window that allows executions as old ones expire\n * Defaults to 'fixed'\n */\n windowType?: 'fixed' | 'sliding'\n}\n\n/**\n * A lightweight class that creates a rate-limited function.\n *\n * This is an alternative to the RateLimiter in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core RateLimiter,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential rate limiting functionality.\n *\n * Rate limiting allows a function to execute up to a limit within a time window,\n * then blocks all subsequent calls until the window passes. This can lead to \"bursty\" behavior where\n * all executions happen immediately, followed by a complete block.\n *\n * The rate limiter supports two types of windows:\n * - 'fixed': A strict window that resets after the window period. All executions within the window count\n * towards the limit, and the window resets completely after the period.\n * - 'sliding': A rolling window that allows executions as old ones expire. This provides a more\n * consistent rate of execution over time.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, getRemainingInWindow, getMsUntilNextWindow, reset)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter((id: string) => {\n * api.getData(id);\n * }, { limit: 5, window: 1000 });\n *\n * // First 5 calls will execute, then block until window resets\n * if (rateLimiter.maybeExecute('123')) {\n * console.log('API call made');\n * } else {\n * console.log('Rate limited - try again in', rateLimiter.getMsUntilNextWindow(), 'ms');\n * }\n * ```\n */\nexport class LiteRateLimiter<TFn extends AnyFunction> {\n private executionTimes: Array<number> = []\n private timeoutIds: Set<NodeJS.Timeout> = new Set()\n\n constructor(\n public fn: TFn,\n public options: LiteRateLimiterOptions<TFn>,\n ) {\n // Default windowType to 'fixed' if not specified\n if (this.options.windowType === undefined) {\n this.options.windowType = 'fixed'\n }\n }\n\n /**\n * Attempts to execute the rate-limited function if within the configured limits.\n * Returns true if executed, false if rejected due to rate limiting.\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter(fn, { limit: 5, window: 1000 });\n *\n * // First 5 calls return true\n * rateLimiter.maybeExecute('arg1', 'arg2'); // true\n *\n * // Additional calls within the window return false\n * rateLimiter.maybeExecute('arg1', 'arg2'); // false\n * ```\n */\n maybeExecute = (...args: Parameters<TFn>): boolean => {\n this.cleanupOldExecutions()\n\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n\n if (relevantExecutionTimes.length < this.options.limit) {\n this.execute(...args)\n return true\n }\n\n this.options.onReject?.(this)\n return false\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.executionTimes.push(now)\n this.setCleanupTimeout(now)\n }\n\n private getExecutionTimesInWindow = (): Array<number> => {\n if (this.options.windowType === 'sliding') {\n // For sliding window, return all executions within the current window\n return this.executionTimes.filter(\n (time) => time > Date.now() - this.options.window,\n )\n } else {\n // For fixed window, return all executions in the current window\n if (this.executionTimes.length === 0) {\n return []\n }\n const oldestExecution = Math.min(...this.executionTimes)\n const windowStart = oldestExecution\n const windowEnd = windowStart + this.options.window\n const now = Date.now()\n\n // If the window has expired, return empty array\n if (now > windowEnd) {\n return []\n }\n\n // Otherwise, return all executions in the current window\n return this.executionTimes.filter(\n (time) => time >= windowStart && time <= windowEnd,\n )\n }\n }\n\n private setCleanupTimeout = (executionTime: number): void => {\n if (\n this.options.windowType === 'sliding' ||\n this.timeoutIds.size === 0 // new fixed window\n ) {\n const now = Date.now()\n const timeUntilExpiration = executionTime - now + this.options.window + 1\n const timeoutId = setTimeout(() => {\n this.cleanupOldExecutions()\n this.clearTimeout(timeoutId)\n }, timeUntilExpiration)\n this.timeoutIds.add(timeoutId)\n }\n }\n\n private clearTimeout = (timeoutId: NodeJS.Timeout): void => {\n clearTimeout(timeoutId)\n this.timeoutIds.delete(timeoutId)\n }\n\n private clearTimeouts = (): void => {\n this.timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId))\n this.timeoutIds.clear()\n }\n\n private cleanupOldExecutions = (): void => {\n this.executionTimes = this.getExecutionTimesInWindow()\n }\n\n /**\n * Returns the number of remaining executions allowed in the current window.\n */\n getRemainingInWindow = (): number => {\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n return Math.max(0, this.options.limit - relevantExecutionTimes.length)\n }\n\n /**\n * Returns the number of milliseconds until the next execution will be possible.\n * Returns 0 if executions are currently allowed.\n */\n getMsUntilNextWindow = (): number => {\n if (this.getRemainingInWindow() > 0) {\n return 0\n }\n const oldestExecution = this.executionTimes[0] ?? Infinity\n return oldestExecution + this.options.window - Date.now()\n }\n\n /**\n * Resets the rate limiter state, clearing all execution history.\n */\n reset = (): void => {\n this.executionTimes = []\n this.clearTimeouts()\n }\n}\n\n/**\n * Creates a lightweight rate-limited function that will execute the provided function up to a maximum number of times within a time window.\n *\n * This is an alternative to the rateLimit function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a rate limiter with no external dependencies, devtools integration, or reactive state.\n *\n * Rate limiting allows all executions until the limit is reached, then blocks all subsequent calls until the window resets.\n * This differs from throttling (which ensures even spacing) and debouncing (which waits for pauses).\n *\n * @example\n * ```ts\n * const rateLimitedApi = liteRateLimit(makeApiCall, {\n * limit: 5,\n * window: 60000, // 1 minute\n * windowType: 'sliding'\n * });\n *\n * // First 5 calls execute immediately\n * // Additional calls are rejected until window allows\n * rateLimitedApi();\n * ```\n *\n * @example\n * ```ts\n * // Fixed window - all 10 calls happen in first second, then 10 second wait\n * const rateLimitedFixed = liteRateLimit(logEvent, {\n * limit: 10,\n * window: 10000,\n * windowType: 'fixed'\n * });\n * ```\n */\nexport function liteRateLimit<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteRateLimiterOptions<TFn>,\n): (...args: Parameters<TFn>) => boolean {\n const rateLimiter = new LiteRateLimiter(fn, options)\n return rateLimiter.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,kBAAb,MAAsD;CAIpD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;wBAL+B,EAAE;oCACA,IAAI,KAAK;uBA2BnC,GAAG,SAAmC;AACpD,QAAK,sBAAsB;AAI3B,OAF+B,KAAK,2BAA2B,CAEpC,SAAS,KAAK,QAAQ,OAAO;AACtD,SAAK,QAAQ,GAAG,KAAK;AACrB,WAAO;;AAGT,QAAK,QAAQ,WAAW,KAAK;AAC7B,UAAO;;kBAGU,GAAG,SAAgC;GACpD,MAAM,MAAM,KAAK,KAAK;AACtB,QAAK,GAAG,GAAG,KAAK;AAChB,QAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,QAAK,eAAe,KAAK,IAAI;AAC7B,QAAK,kBAAkB,IAAI;;yCAG4B;AACvD,OAAI,KAAK,QAAQ,eAAe,UAE9B,QAAO,KAAK,eAAe,QACxB,SAAS,OAAO,KAAK,KAAK,GAAG,KAAK,QAAQ,OAC5C;QACI;AAEL,QAAI,KAAK,eAAe,WAAW,EACjC,QAAO,EAAE;IAGX,MAAM,cADkB,KAAK,IAAI,GAAG,KAAK,eAAe;IAExD,MAAM,YAAY,cAAc,KAAK,QAAQ;AAI7C,QAHY,KAAK,KAAK,GAGZ,UACR,QAAO,EAAE;AAIX,WAAO,KAAK,eAAe,QACxB,SAAS,QAAQ,eAAe,QAAQ,UAC1C;;;4BAIwB,kBAAgC;AAC3D,OACE,KAAK,QAAQ,eAAe,aAC5B,KAAK,WAAW,SAAS,GACzB;IAEA,MAAM,sBAAsB,gBADhB,KAAK,KAAK,GAC4B,KAAK,QAAQ,SAAS;IACxE,MAAM,YAAY,iBAAiB;AACjC,UAAK,sBAAsB;AAC3B,UAAK,aAAa,UAAU;OAC3B,oBAAoB;AACvB,SAAK,WAAW,IAAI,UAAU;;;uBAIV,cAAoC;AAC1D,gBAAa,UAAU;AACvB,QAAK,WAAW,OAAO,UAAU;;6BAGC;AAClC,QAAK,WAAW,SAAS,cAAc,aAAa,UAAU,CAAC;AAC/D,QAAK,WAAW,OAAO;;oCAGkB;AACzC,QAAK,iBAAiB,KAAK,2BAA2B;;oCAMnB;GACnC,MAAM,yBAAyB,KAAK,2BAA2B;AAC/D,UAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,uBAAuB,OAAO;;oCAOnC;AACnC,OAAI,KAAK,sBAAsB,GAAG,EAChC,QAAO;AAGT,WADwB,KAAK,eAAe,MAAM,YACzB,KAAK,QAAQ,SAAS,KAAK,KAAK;;qBAMvC;AAClB,QAAK,iBAAiB,EAAE;AACxB,QAAK,eAAe;;AA5HpB,MAAI,KAAK,QAAQ,eAAe,OAC9B,MAAK,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgKhC,SAAgB,cACd,IACA,SACuC;AAEvC,QADoB,IAAI,gBAAgB,IAAI,QAAQ,CACjC"}
1
+ {"version":3,"file":"lite-rate-limiter.cjs","names":[],"sources":["../src/lite-rate-limiter.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite rate-limited function\n */\nexport interface LiteRateLimiterOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Maximum number of executions allowed within the time window.\n */\n limit: number\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Optional callback function that is called when an execution is rejected due to rate limiting\n */\n onReject?: (rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Time window in milliseconds within which the limit applies.\n */\n window: number\n /**\n * Type of window to use for rate limiting\n * - 'fixed': Uses a fixed window that resets after the window period\n * - 'sliding': Uses a sliding window that allows executions as old ones expire\n * Defaults to 'fixed'\n */\n windowType?: 'fixed' | 'sliding'\n}\n\n/**\n * A lightweight class that creates a rate-limited function.\n *\n * This is an alternative to the RateLimiter in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core RateLimiter,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential rate limiting functionality.\n *\n * Rate limiting allows a function to execute up to a limit within a time window,\n * then blocks all subsequent calls until the window passes. This can lead to \"bursty\" behavior where\n * all executions happen immediately, followed by a complete block.\n *\n * The rate limiter supports two types of windows:\n * - 'fixed': A strict window that resets after the window period. All executions within the window count\n * towards the limit, and the window resets completely after the period.\n * - 'sliding': A rolling window that allows executions as old ones expire. This provides a more\n * consistent rate of execution over time.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, getRemainingInWindow, getMsUntilNextWindow, reset)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter((id: string) => {\n * api.getData(id);\n * }, { limit: 5, window: 1000 });\n *\n * // First 5 calls will execute, then block until window resets\n * if (rateLimiter.maybeExecute('123')) {\n * console.log('API call made');\n * } else {\n * console.log('Rate limited - try again in', rateLimiter.getMsUntilNextWindow(), 'ms');\n * }\n * ```\n */\nexport class LiteRateLimiter<TFn extends AnyFunction> {\n private executionTimes: Array<number> = []\n private timeoutIds: Set<NodeJS.Timeout> = new Set()\n\n constructor(\n public fn: TFn,\n public options: LiteRateLimiterOptions<TFn>,\n ) {\n // Default windowType to 'fixed' if not specified\n if (this.options.windowType === undefined) {\n this.options.windowType = 'fixed'\n }\n }\n\n /**\n * Attempts to execute the rate-limited function if within the configured limits.\n * Returns true if executed, false if rejected due to rate limiting.\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter(fn, { limit: 5, window: 1000 });\n *\n * // First 5 calls return true\n * rateLimiter.maybeExecute('arg1', 'arg2'); // true\n *\n * // Additional calls within the window return false\n * rateLimiter.maybeExecute('arg1', 'arg2'); // false\n * ```\n */\n maybeExecute = (...args: Parameters<TFn>): boolean => {\n this.cleanupOldExecutions()\n\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n\n if (relevantExecutionTimes.length < this.options.limit) {\n this.execute(...args)\n return true\n }\n\n this.options.onReject?.(this)\n return false\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.executionTimes.push(now)\n this.setCleanupTimeout(now)\n }\n\n private getExecutionTimesInWindow = (): Array<number> => {\n if (this.options.windowType === 'sliding') {\n // For sliding window, return all executions within the current window\n return this.executionTimes.filter(\n (time) => time > Date.now() - this.options.window,\n )\n } else {\n // For fixed window, return all executions in the current window\n if (this.executionTimes.length === 0) {\n return []\n }\n const oldestExecution = Math.min(...this.executionTimes)\n const windowStart = oldestExecution\n const windowEnd = windowStart + this.options.window\n const now = Date.now()\n\n // If the window has expired, return empty array\n if (now > windowEnd) {\n return []\n }\n\n // Otherwise, return all executions in the current window\n return this.executionTimes.filter(\n (time) => time >= windowStart && time <= windowEnd,\n )\n }\n }\n\n private setCleanupTimeout = (executionTime: number): void => {\n if (\n this.options.windowType === 'sliding' ||\n this.timeoutIds.size === 0 // new fixed window\n ) {\n const now = Date.now()\n const timeUntilExpiration = executionTime - now + this.options.window + 1\n const timeoutId = setTimeout(() => {\n this.cleanupOldExecutions()\n this.clearTimeout(timeoutId)\n }, timeUntilExpiration)\n this.timeoutIds.add(timeoutId)\n }\n }\n\n private clearTimeout = (timeoutId: NodeJS.Timeout): void => {\n clearTimeout(timeoutId)\n this.timeoutIds.delete(timeoutId)\n }\n\n private clearTimeouts = (): void => {\n this.timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId))\n this.timeoutIds.clear()\n }\n\n private cleanupOldExecutions = (): void => {\n this.executionTimes = this.getExecutionTimesInWindow()\n }\n\n /**\n * Returns the number of remaining executions allowed in the current window.\n */\n getRemainingInWindow = (): number => {\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n return Math.max(0, this.options.limit - relevantExecutionTimes.length)\n }\n\n /**\n * Returns the number of milliseconds until the next execution will be possible.\n * Returns 0 if executions are currently allowed.\n */\n getMsUntilNextWindow = (): number => {\n if (this.getRemainingInWindow() > 0) {\n return 0\n }\n const oldestExecution = this.executionTimes[0] ?? Infinity\n return oldestExecution + this.options.window - Date.now()\n }\n\n /**\n * Resets the rate limiter state, clearing all execution history.\n */\n reset = (): void => {\n this.executionTimes = []\n this.clearTimeouts()\n }\n}\n\n/**\n * Creates a lightweight rate-limited function that will execute the provided function up to a maximum number of times within a time window.\n *\n * This is an alternative to the rateLimit function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a rate limiter with no external dependencies, devtools integration, or reactive state.\n *\n * Rate limiting allows all executions until the limit is reached, then blocks all subsequent calls until the window resets.\n * This differs from throttling (which ensures even spacing) and debouncing (which waits for pauses).\n *\n * @example\n * ```ts\n * const rateLimitedApi = liteRateLimit(makeApiCall, {\n * limit: 5,\n * window: 60000, // 1 minute\n * windowType: 'sliding'\n * });\n *\n * // First 5 calls execute immediately\n * // Additional calls are rejected until window allows\n * rateLimitedApi();\n * ```\n *\n * @example\n * ```ts\n * // Fixed window - all 10 calls happen in first second, then 10 second wait\n * const rateLimitedFixed = liteRateLimit(logEvent, {\n * limit: 10,\n * window: 10000,\n * windowType: 'fixed'\n * });\n * ```\n */\nexport function liteRateLimit<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteRateLimiterOptions<TFn>,\n): (...args: Parameters<TFn>) => boolean {\n const rateLimiter = new LiteRateLimiter(fn, options)\n return rateLimiter.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,kBAAb,MAAsD;CAIpD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;wBAL+B,EAAE;oCACA,IAAI,KAAK;uBA2BnC,GAAG,SAAmC;GACpD,KAAK,sBAAsB;GAI3B,IAF+B,KAAK,2BAEV,CAAC,SAAS,KAAK,QAAQ,OAAO;IACtD,KAAK,QAAQ,GAAG,KAAK;IACrB,OAAO;;GAGT,KAAK,QAAQ,WAAW,KAAK;GAC7B,OAAO;;kBAGU,GAAG,SAAgC;GACpD,MAAM,MAAM,KAAK,KAAK;GACtB,KAAK,GAAG,GAAG,KAAK;GAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;GACpC,KAAK,eAAe,KAAK,IAAI;GAC7B,KAAK,kBAAkB,IAAI;;yCAG4B;GACvD,IAAI,KAAK,QAAQ,eAAe,WAE9B,OAAO,KAAK,eAAe,QACxB,SAAS,OAAO,KAAK,KAAK,GAAG,KAAK,QAAQ,OAC5C;QACI;IAEL,IAAI,KAAK,eAAe,WAAW,GACjC,OAAO,EAAE;IAGX,MAAM,cADkB,KAAK,IAAI,GAAG,KAAK,eACN;IACnC,MAAM,YAAY,cAAc,KAAK,QAAQ;IAI7C,IAHY,KAAK,KAGV,GAAG,WACR,OAAO,EAAE;IAIX,OAAO,KAAK,eAAe,QACxB,SAAS,QAAQ,eAAe,QAAQ,UAC1C;;;4BAIwB,kBAAgC;GAC3D,IACE,KAAK,QAAQ,eAAe,aAC5B,KAAK,WAAW,SAAS,GACzB;IAEA,MAAM,sBAAsB,gBADhB,KAAK,KAC8B,GAAG,KAAK,QAAQ,SAAS;IACxE,MAAM,YAAY,iBAAiB;KACjC,KAAK,sBAAsB;KAC3B,KAAK,aAAa,UAAU;OAC3B,oBAAoB;IACvB,KAAK,WAAW,IAAI,UAAU;;;uBAIV,cAAoC;GAC1D,aAAa,UAAU;GACvB,KAAK,WAAW,OAAO,UAAU;;6BAGC;GAClC,KAAK,WAAW,SAAS,cAAc,aAAa,UAAU,CAAC;GAC/D,KAAK,WAAW,OAAO;;oCAGkB;GACzC,KAAK,iBAAiB,KAAK,2BAA2B;;oCAMnB;GACnC,MAAM,yBAAyB,KAAK,2BAA2B;GAC/D,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,uBAAuB,OAAO;;oCAOnC;GACnC,IAAI,KAAK,sBAAsB,GAAG,GAChC,OAAO;GAGT,QADwB,KAAK,eAAe,MAAM,YACzB,KAAK,QAAQ,SAAS,KAAK,KAAK;;qBAMvC;GAClB,KAAK,iBAAiB,EAAE;GACxB,KAAK,eAAe;;EA5HpB,IAAI,KAAK,QAAQ,eAAe,QAC9B,KAAK,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgKhC,SAAgB,cACd,IACA,SACuC;CAEvC,OAAO,IADiB,gBAAgB,IAAI,QAC1B,CAAC"}
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.cjs";
2
2
 
3
3
  //#region src/lite-rate-limiter.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite rate-limited function
7
6
  */
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.js";
2
2
 
3
3
  //#region src/lite-rate-limiter.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite rate-limited function
7
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"lite-rate-limiter.js","names":["fn: TFn","options: LiteRateLimiterOptions<TFn>"],"sources":["../src/lite-rate-limiter.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite rate-limited function\n */\nexport interface LiteRateLimiterOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Maximum number of executions allowed within the time window.\n */\n limit: number\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Optional callback function that is called when an execution is rejected due to rate limiting\n */\n onReject?: (rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Time window in milliseconds within which the limit applies.\n */\n window: number\n /**\n * Type of window to use for rate limiting\n * - 'fixed': Uses a fixed window that resets after the window period\n * - 'sliding': Uses a sliding window that allows executions as old ones expire\n * Defaults to 'fixed'\n */\n windowType?: 'fixed' | 'sliding'\n}\n\n/**\n * A lightweight class that creates a rate-limited function.\n *\n * This is an alternative to the RateLimiter in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core RateLimiter,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential rate limiting functionality.\n *\n * Rate limiting allows a function to execute up to a limit within a time window,\n * then blocks all subsequent calls until the window passes. This can lead to \"bursty\" behavior where\n * all executions happen immediately, followed by a complete block.\n *\n * The rate limiter supports two types of windows:\n * - 'fixed': A strict window that resets after the window period. All executions within the window count\n * towards the limit, and the window resets completely after the period.\n * - 'sliding': A rolling window that allows executions as old ones expire. This provides a more\n * consistent rate of execution over time.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, getRemainingInWindow, getMsUntilNextWindow, reset)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter((id: string) => {\n * api.getData(id);\n * }, { limit: 5, window: 1000 });\n *\n * // First 5 calls will execute, then block until window resets\n * if (rateLimiter.maybeExecute('123')) {\n * console.log('API call made');\n * } else {\n * console.log('Rate limited - try again in', rateLimiter.getMsUntilNextWindow(), 'ms');\n * }\n * ```\n */\nexport class LiteRateLimiter<TFn extends AnyFunction> {\n private executionTimes: Array<number> = []\n private timeoutIds: Set<NodeJS.Timeout> = new Set()\n\n constructor(\n public fn: TFn,\n public options: LiteRateLimiterOptions<TFn>,\n ) {\n // Default windowType to 'fixed' if not specified\n if (this.options.windowType === undefined) {\n this.options.windowType = 'fixed'\n }\n }\n\n /**\n * Attempts to execute the rate-limited function if within the configured limits.\n * Returns true if executed, false if rejected due to rate limiting.\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter(fn, { limit: 5, window: 1000 });\n *\n * // First 5 calls return true\n * rateLimiter.maybeExecute('arg1', 'arg2'); // true\n *\n * // Additional calls within the window return false\n * rateLimiter.maybeExecute('arg1', 'arg2'); // false\n * ```\n */\n maybeExecute = (...args: Parameters<TFn>): boolean => {\n this.cleanupOldExecutions()\n\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n\n if (relevantExecutionTimes.length < this.options.limit) {\n this.execute(...args)\n return true\n }\n\n this.options.onReject?.(this)\n return false\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.executionTimes.push(now)\n this.setCleanupTimeout(now)\n }\n\n private getExecutionTimesInWindow = (): Array<number> => {\n if (this.options.windowType === 'sliding') {\n // For sliding window, return all executions within the current window\n return this.executionTimes.filter(\n (time) => time > Date.now() - this.options.window,\n )\n } else {\n // For fixed window, return all executions in the current window\n if (this.executionTimes.length === 0) {\n return []\n }\n const oldestExecution = Math.min(...this.executionTimes)\n const windowStart = oldestExecution\n const windowEnd = windowStart + this.options.window\n const now = Date.now()\n\n // If the window has expired, return empty array\n if (now > windowEnd) {\n return []\n }\n\n // Otherwise, return all executions in the current window\n return this.executionTimes.filter(\n (time) => time >= windowStart && time <= windowEnd,\n )\n }\n }\n\n private setCleanupTimeout = (executionTime: number): void => {\n if (\n this.options.windowType === 'sliding' ||\n this.timeoutIds.size === 0 // new fixed window\n ) {\n const now = Date.now()\n const timeUntilExpiration = executionTime - now + this.options.window + 1\n const timeoutId = setTimeout(() => {\n this.cleanupOldExecutions()\n this.clearTimeout(timeoutId)\n }, timeUntilExpiration)\n this.timeoutIds.add(timeoutId)\n }\n }\n\n private clearTimeout = (timeoutId: NodeJS.Timeout): void => {\n clearTimeout(timeoutId)\n this.timeoutIds.delete(timeoutId)\n }\n\n private clearTimeouts = (): void => {\n this.timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId))\n this.timeoutIds.clear()\n }\n\n private cleanupOldExecutions = (): void => {\n this.executionTimes = this.getExecutionTimesInWindow()\n }\n\n /**\n * Returns the number of remaining executions allowed in the current window.\n */\n getRemainingInWindow = (): number => {\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n return Math.max(0, this.options.limit - relevantExecutionTimes.length)\n }\n\n /**\n * Returns the number of milliseconds until the next execution will be possible.\n * Returns 0 if executions are currently allowed.\n */\n getMsUntilNextWindow = (): number => {\n if (this.getRemainingInWindow() > 0) {\n return 0\n }\n const oldestExecution = this.executionTimes[0] ?? Infinity\n return oldestExecution + this.options.window - Date.now()\n }\n\n /**\n * Resets the rate limiter state, clearing all execution history.\n */\n reset = (): void => {\n this.executionTimes = []\n this.clearTimeouts()\n }\n}\n\n/**\n * Creates a lightweight rate-limited function that will execute the provided function up to a maximum number of times within a time window.\n *\n * This is an alternative to the rateLimit function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a rate limiter with no external dependencies, devtools integration, or reactive state.\n *\n * Rate limiting allows all executions until the limit is reached, then blocks all subsequent calls until the window resets.\n * This differs from throttling (which ensures even spacing) and debouncing (which waits for pauses).\n *\n * @example\n * ```ts\n * const rateLimitedApi = liteRateLimit(makeApiCall, {\n * limit: 5,\n * window: 60000, // 1 minute\n * windowType: 'sliding'\n * });\n *\n * // First 5 calls execute immediately\n * // Additional calls are rejected until window allows\n * rateLimitedApi();\n * ```\n *\n * @example\n * ```ts\n * // Fixed window - all 10 calls happen in first second, then 10 second wait\n * const rateLimitedFixed = liteRateLimit(logEvent, {\n * limit: 10,\n * window: 10000,\n * windowType: 'fixed'\n * });\n * ```\n */\nexport function liteRateLimit<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteRateLimiterOptions<TFn>,\n): (...args: Parameters<TFn>) => boolean {\n const rateLimiter = new LiteRateLimiter(fn, options)\n return rateLimiter.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,kBAAb,MAAsD;CAIpD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;wBAL+B,EAAE;oCACA,IAAI,KAAK;uBA2BnC,GAAG,SAAmC;AACpD,QAAK,sBAAsB;AAI3B,OAF+B,KAAK,2BAA2B,CAEpC,SAAS,KAAK,QAAQ,OAAO;AACtD,SAAK,QAAQ,GAAG,KAAK;AACrB,WAAO;;AAGT,QAAK,QAAQ,WAAW,KAAK;AAC7B,UAAO;;kBAGU,GAAG,SAAgC;GACpD,MAAM,MAAM,KAAK,KAAK;AACtB,QAAK,GAAG,GAAG,KAAK;AAChB,QAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,QAAK,eAAe,KAAK,IAAI;AAC7B,QAAK,kBAAkB,IAAI;;yCAG4B;AACvD,OAAI,KAAK,QAAQ,eAAe,UAE9B,QAAO,KAAK,eAAe,QACxB,SAAS,OAAO,KAAK,KAAK,GAAG,KAAK,QAAQ,OAC5C;QACI;AAEL,QAAI,KAAK,eAAe,WAAW,EACjC,QAAO,EAAE;IAGX,MAAM,cADkB,KAAK,IAAI,GAAG,KAAK,eAAe;IAExD,MAAM,YAAY,cAAc,KAAK,QAAQ;AAI7C,QAHY,KAAK,KAAK,GAGZ,UACR,QAAO,EAAE;AAIX,WAAO,KAAK,eAAe,QACxB,SAAS,QAAQ,eAAe,QAAQ,UAC1C;;;4BAIwB,kBAAgC;AAC3D,OACE,KAAK,QAAQ,eAAe,aAC5B,KAAK,WAAW,SAAS,GACzB;IAEA,MAAM,sBAAsB,gBADhB,KAAK,KAAK,GAC4B,KAAK,QAAQ,SAAS;IACxE,MAAM,YAAY,iBAAiB;AACjC,UAAK,sBAAsB;AAC3B,UAAK,aAAa,UAAU;OAC3B,oBAAoB;AACvB,SAAK,WAAW,IAAI,UAAU;;;uBAIV,cAAoC;AAC1D,gBAAa,UAAU;AACvB,QAAK,WAAW,OAAO,UAAU;;6BAGC;AAClC,QAAK,WAAW,SAAS,cAAc,aAAa,UAAU,CAAC;AAC/D,QAAK,WAAW,OAAO;;oCAGkB;AACzC,QAAK,iBAAiB,KAAK,2BAA2B;;oCAMnB;GACnC,MAAM,yBAAyB,KAAK,2BAA2B;AAC/D,UAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,uBAAuB,OAAO;;oCAOnC;AACnC,OAAI,KAAK,sBAAsB,GAAG,EAChC,QAAO;AAGT,WADwB,KAAK,eAAe,MAAM,YACzB,KAAK,QAAQ,SAAS,KAAK,KAAK;;qBAMvC;AAClB,QAAK,iBAAiB,EAAE;AACxB,QAAK,eAAe;;AA5HpB,MAAI,KAAK,QAAQ,eAAe,OAC9B,MAAK,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgKhC,SAAgB,cACd,IACA,SACuC;AAEvC,QADoB,IAAI,gBAAgB,IAAI,QAAQ,CACjC"}
1
+ {"version":3,"file":"lite-rate-limiter.js","names":[],"sources":["../src/lite-rate-limiter.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite rate-limited function\n */\nexport interface LiteRateLimiterOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Maximum number of executions allowed within the time window.\n */\n limit: number\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Optional callback function that is called when an execution is rejected due to rate limiting\n */\n onReject?: (rateLimiter: LiteRateLimiter<TFn>) => void\n /**\n * Time window in milliseconds within which the limit applies.\n */\n window: number\n /**\n * Type of window to use for rate limiting\n * - 'fixed': Uses a fixed window that resets after the window period\n * - 'sliding': Uses a sliding window that allows executions as old ones expire\n * Defaults to 'fixed'\n */\n windowType?: 'fixed' | 'sliding'\n}\n\n/**\n * A lightweight class that creates a rate-limited function.\n *\n * This is an alternative to the RateLimiter in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core RateLimiter,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential rate limiting functionality.\n *\n * Rate limiting allows a function to execute up to a limit within a time window,\n * then blocks all subsequent calls until the window passes. This can lead to \"bursty\" behavior where\n * all executions happen immediately, followed by a complete block.\n *\n * The rate limiter supports two types of windows:\n * - 'fixed': A strict window that resets after the window period. All executions within the window count\n * towards the limit, and the window resets completely after the period.\n * - 'sliding': A rolling window that allows executions as old ones expire. This provides a more\n * consistent rate of execution over time.\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, getRemainingInWindow, getMsUntilNextWindow, reset)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter((id: string) => {\n * api.getData(id);\n * }, { limit: 5, window: 1000 });\n *\n * // First 5 calls will execute, then block until window resets\n * if (rateLimiter.maybeExecute('123')) {\n * console.log('API call made');\n * } else {\n * console.log('Rate limited - try again in', rateLimiter.getMsUntilNextWindow(), 'ms');\n * }\n * ```\n */\nexport class LiteRateLimiter<TFn extends AnyFunction> {\n private executionTimes: Array<number> = []\n private timeoutIds: Set<NodeJS.Timeout> = new Set()\n\n constructor(\n public fn: TFn,\n public options: LiteRateLimiterOptions<TFn>,\n ) {\n // Default windowType to 'fixed' if not specified\n if (this.options.windowType === undefined) {\n this.options.windowType = 'fixed'\n }\n }\n\n /**\n * Attempts to execute the rate-limited function if within the configured limits.\n * Returns true if executed, false if rejected due to rate limiting.\n *\n * @example\n * ```ts\n * const rateLimiter = new LiteRateLimiter(fn, { limit: 5, window: 1000 });\n *\n * // First 5 calls return true\n * rateLimiter.maybeExecute('arg1', 'arg2'); // true\n *\n * // Additional calls within the window return false\n * rateLimiter.maybeExecute('arg1', 'arg2'); // false\n * ```\n */\n maybeExecute = (...args: Parameters<TFn>): boolean => {\n this.cleanupOldExecutions()\n\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n\n if (relevantExecutionTimes.length < this.options.limit) {\n this.execute(...args)\n return true\n }\n\n this.options.onReject?.(this)\n return false\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.executionTimes.push(now)\n this.setCleanupTimeout(now)\n }\n\n private getExecutionTimesInWindow = (): Array<number> => {\n if (this.options.windowType === 'sliding') {\n // For sliding window, return all executions within the current window\n return this.executionTimes.filter(\n (time) => time > Date.now() - this.options.window,\n )\n } else {\n // For fixed window, return all executions in the current window\n if (this.executionTimes.length === 0) {\n return []\n }\n const oldestExecution = Math.min(...this.executionTimes)\n const windowStart = oldestExecution\n const windowEnd = windowStart + this.options.window\n const now = Date.now()\n\n // If the window has expired, return empty array\n if (now > windowEnd) {\n return []\n }\n\n // Otherwise, return all executions in the current window\n return this.executionTimes.filter(\n (time) => time >= windowStart && time <= windowEnd,\n )\n }\n }\n\n private setCleanupTimeout = (executionTime: number): void => {\n if (\n this.options.windowType === 'sliding' ||\n this.timeoutIds.size === 0 // new fixed window\n ) {\n const now = Date.now()\n const timeUntilExpiration = executionTime - now + this.options.window + 1\n const timeoutId = setTimeout(() => {\n this.cleanupOldExecutions()\n this.clearTimeout(timeoutId)\n }, timeUntilExpiration)\n this.timeoutIds.add(timeoutId)\n }\n }\n\n private clearTimeout = (timeoutId: NodeJS.Timeout): void => {\n clearTimeout(timeoutId)\n this.timeoutIds.delete(timeoutId)\n }\n\n private clearTimeouts = (): void => {\n this.timeoutIds.forEach((timeoutId) => clearTimeout(timeoutId))\n this.timeoutIds.clear()\n }\n\n private cleanupOldExecutions = (): void => {\n this.executionTimes = this.getExecutionTimesInWindow()\n }\n\n /**\n * Returns the number of remaining executions allowed in the current window.\n */\n getRemainingInWindow = (): number => {\n const relevantExecutionTimes = this.getExecutionTimesInWindow()\n return Math.max(0, this.options.limit - relevantExecutionTimes.length)\n }\n\n /**\n * Returns the number of milliseconds until the next execution will be possible.\n * Returns 0 if executions are currently allowed.\n */\n getMsUntilNextWindow = (): number => {\n if (this.getRemainingInWindow() > 0) {\n return 0\n }\n const oldestExecution = this.executionTimes[0] ?? Infinity\n return oldestExecution + this.options.window - Date.now()\n }\n\n /**\n * Resets the rate limiter state, clearing all execution history.\n */\n reset = (): void => {\n this.executionTimes = []\n this.clearTimeouts()\n }\n}\n\n/**\n * Creates a lightweight rate-limited function that will execute the provided function up to a maximum number of times within a time window.\n *\n * This is an alternative to the rateLimit function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a rate limiter with no external dependencies, devtools integration, or reactive state.\n *\n * Rate limiting allows all executions until the limit is reached, then blocks all subsequent calls until the window resets.\n * This differs from throttling (which ensures even spacing) and debouncing (which waits for pauses).\n *\n * @example\n * ```ts\n * const rateLimitedApi = liteRateLimit(makeApiCall, {\n * limit: 5,\n * window: 60000, // 1 minute\n * windowType: 'sliding'\n * });\n *\n * // First 5 calls execute immediately\n * // Additional calls are rejected until window allows\n * rateLimitedApi();\n * ```\n *\n * @example\n * ```ts\n * // Fixed window - all 10 calls happen in first second, then 10 second wait\n * const rateLimitedFixed = liteRateLimit(logEvent, {\n * limit: 10,\n * window: 10000,\n * windowType: 'fixed'\n * });\n * ```\n */\nexport function liteRateLimit<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteRateLimiterOptions<TFn>,\n): (...args: Parameters<TFn>) => boolean {\n const rateLimiter = new LiteRateLimiter(fn, options)\n return rateLimiter.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,kBAAb,MAAsD;CAIpD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;wBAL+B,EAAE;oCACA,IAAI,KAAK;uBA2BnC,GAAG,SAAmC;GACpD,KAAK,sBAAsB;GAI3B,IAF+B,KAAK,2BAEV,CAAC,SAAS,KAAK,QAAQ,OAAO;IACtD,KAAK,QAAQ,GAAG,KAAK;IACrB,OAAO;;GAGT,KAAK,QAAQ,WAAW,KAAK;GAC7B,OAAO;;kBAGU,GAAG,SAAgC;GACpD,MAAM,MAAM,KAAK,KAAK;GACtB,KAAK,GAAG,GAAG,KAAK;GAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;GACpC,KAAK,eAAe,KAAK,IAAI;GAC7B,KAAK,kBAAkB,IAAI;;yCAG4B;GACvD,IAAI,KAAK,QAAQ,eAAe,WAE9B,OAAO,KAAK,eAAe,QACxB,SAAS,OAAO,KAAK,KAAK,GAAG,KAAK,QAAQ,OAC5C;QACI;IAEL,IAAI,KAAK,eAAe,WAAW,GACjC,OAAO,EAAE;IAGX,MAAM,cADkB,KAAK,IAAI,GAAG,KAAK,eACN;IACnC,MAAM,YAAY,cAAc,KAAK,QAAQ;IAI7C,IAHY,KAAK,KAGV,GAAG,WACR,OAAO,EAAE;IAIX,OAAO,KAAK,eAAe,QACxB,SAAS,QAAQ,eAAe,QAAQ,UAC1C;;;4BAIwB,kBAAgC;GAC3D,IACE,KAAK,QAAQ,eAAe,aAC5B,KAAK,WAAW,SAAS,GACzB;IAEA,MAAM,sBAAsB,gBADhB,KAAK,KAC8B,GAAG,KAAK,QAAQ,SAAS;IACxE,MAAM,YAAY,iBAAiB;KACjC,KAAK,sBAAsB;KAC3B,KAAK,aAAa,UAAU;OAC3B,oBAAoB;IACvB,KAAK,WAAW,IAAI,UAAU;;;uBAIV,cAAoC;GAC1D,aAAa,UAAU;GACvB,KAAK,WAAW,OAAO,UAAU;;6BAGC;GAClC,KAAK,WAAW,SAAS,cAAc,aAAa,UAAU,CAAC;GAC/D,KAAK,WAAW,OAAO;;oCAGkB;GACzC,KAAK,iBAAiB,KAAK,2BAA2B;;oCAMnB;GACnC,MAAM,yBAAyB,KAAK,2BAA2B;GAC/D,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,QAAQ,uBAAuB,OAAO;;oCAOnC;GACnC,IAAI,KAAK,sBAAsB,GAAG,GAChC,OAAO;GAGT,QADwB,KAAK,eAAe,MAAM,YACzB,KAAK,QAAQ,SAAS,KAAK,KAAK;;qBAMvC;GAClB,KAAK,iBAAiB,EAAE;GACxB,KAAK,eAAe;;EA5HpB,IAAI,KAAK,QAAQ,eAAe,QAC9B,KAAK,QAAQ,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgKhC,SAAgB,cACd,IACA,SACuC;CAEvC,OAAO,IADiB,gBAAgB,IAAI,QAC1B,CAAC"}
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/lite-throttler.ts
3
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lite-throttler.cjs","names":["fn: TFn","options: LiteThrottlerOptions<TFn>"],"sources":["../src/lite-throttler.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite throttled function\n */\nexport interface LiteThrottlerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * Defaults to true.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, throttler: LiteThrottler<TFn>) => void\n /**\n * Whether to execute on the trailing edge of the timeout.\n * Defaults to true.\n */\n trailing?: boolean\n /**\n * Time window in milliseconds during which the function can only be executed once.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a throttled function.\n *\n * This is an alternative to the Throttler in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Throttler,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential throttling functionality.\n *\n * Throttling ensures a function is called at most once within a specified time window.\n * Unlike debouncing which waits for a pause in calls, throttling guarantees consistent\n * execution timing regardless of call frequency.\n *\n * Supports both leading and trailing edge execution:\n * - Leading: Execute immediately on first call (default: true)\n * - Trailing: Execute after wait period if called during throttle (default: true)\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const throttler = new LiteThrottler((scrollY: number) => {\n * updateScrollPosition(scrollY);\n * }, {\n * wait: 100,\n * onExecute: (args, throttler) => {\n * console.log('Updated scroll position:', args[0]);\n * }\n * });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', () => {\n * throttler.maybeExecute(window.scrollY);\n * });\n * ```\n */\nexport class LiteThrottler<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private lastExecutionTime = 0\n private isPending = false\n\n constructor(\n public fn: TFn,\n public options: LiteThrottlerOptions<TFn>,\n ) {\n // Default both leading and trailing to true if neither is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.leading = true\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the throttled function. The execution behavior depends on the throttler options:\n *\n * - If enough time has passed since the last execution (>= wait period):\n * - With leading=true: Executes immediately\n * - With leading=false: Waits for the next trailing execution\n *\n * - If within the wait period:\n * - With trailing=true: Schedules execution for end of wait period\n * - With trailing=false: Drops the execution\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n const timeSinceLastExecution = now - this.lastExecutionTime\n\n // Handle leading execution\n if (this.options.leading && timeSinceLastExecution >= this.options.wait) {\n this.execute(...args)\n } else {\n // Store the most recent arguments for potential trailing execution\n this.lastArgs = args\n\n // Set up trailing execution if not already scheduled\n if (!this.timeoutId && this.options.trailing) {\n const timeoutDuration = this.options.wait - timeSinceLastExecution\n this.isPending = true\n this.timeoutId = setTimeout(() => {\n if (this.lastArgs !== undefined) {\n this.execute(...this.lastArgs)\n }\n }, timeoutDuration)\n }\n }\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastExecutionTime = Date.now()\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.isPending && this.lastArgs) {\n this.execute(...this.lastArgs)\n }\n }\n\n /**\n * Cancels any pending trailing execution and clears internal state.\n * If a trailing execution is scheduled, this will prevent that execution from occurring.\n */\n cancel = (): void => {\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n }\n}\n\n/**\n * Creates a lightweight throttled function that limits how often the provided function can execute.\n *\n * This is an alternative to the throttle function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a throttler with no external dependencies, devtools integration, or reactive state.\n *\n * Throttling ensures a function executes at most once within a specified time window,\n * regardless of how many times it is called. This is useful for rate-limiting\n * expensive operations or UI updates.\n *\n * @example\n * ```ts\n * const throttledScroll = liteThrottle(() => {\n * updateScrollIndicator();\n * }, { wait: 100 });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', throttledScroll);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then throttles\n * const throttledResize = liteThrottle(() => {\n * recalculateLayout();\n * }, { wait: 250, leading: true, trailing: false });\n * ```\n */\nexport function liteThrottle<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteThrottlerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const throttler = new LiteThrottler(fn, options)\n return throttler.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,gBAAb,MAAoD;CAMlD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;2BALmB;mBACR;uBA2BJ,GAAG,SAAgC;GAEjD,MAAM,yBADM,KAAK,KAAK,GACe,KAAK;AAG1C,OAAI,KAAK,QAAQ,WAAW,0BAA0B,KAAK,QAAQ,KACjE,MAAK,QAAQ,GAAG,KAAK;QAChB;AAEL,SAAK,WAAW;AAGhB,QAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,UAAU;KAC5C,MAAM,kBAAkB,KAAK,QAAQ,OAAO;AAC5C,UAAK,YAAY;AACjB,UAAK,YAAY,iBAAiB;AAChC,UAAI,KAAK,aAAa,OACpB,MAAK,QAAQ,GAAG,KAAK,SAAS;QAE/B,gBAAgB;;;;kBAKN,GAAG,SAAgC;AACpD,QAAK,GAAG,GAAG,KAAK;AAChB,QAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,QAAK,oBAAoB,KAAK,KAAK;AACnC,QAAK,cAAc;AACnB,QAAK,WAAW;AAChB,QAAK,YAAY;;qBAQC;AAClB,OAAI,KAAK,aAAa,KAAK,SACzB,MAAK,QAAQ,GAAG,KAAK,SAAS;;sBAQb;AACnB,QAAK,cAAc;AACnB,QAAK,WAAW;AAChB,QAAK,YAAY;;4BAGgB;AACjC,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;;AA7EnB,MACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAC1B;AACA,QAAK,QAAQ,UAAU;AACvB,QAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0G9B,SAAgB,aACd,IACA,SACoC;AAEpC,QADkB,IAAI,cAAc,IAAI,QAAQ,CAC/B"}
1
+ {"version":3,"file":"lite-throttler.cjs","names":[],"sources":["../src/lite-throttler.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite throttled function\n */\nexport interface LiteThrottlerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * Defaults to true.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, throttler: LiteThrottler<TFn>) => void\n /**\n * Whether to execute on the trailing edge of the timeout.\n * Defaults to true.\n */\n trailing?: boolean\n /**\n * Time window in milliseconds during which the function can only be executed once.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a throttled function.\n *\n * This is an alternative to the Throttler in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Throttler,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential throttling functionality.\n *\n * Throttling ensures a function is called at most once within a specified time window.\n * Unlike debouncing which waits for a pause in calls, throttling guarantees consistent\n * execution timing regardless of call frequency.\n *\n * Supports both leading and trailing edge execution:\n * - Leading: Execute immediately on first call (default: true)\n * - Trailing: Execute after wait period if called during throttle (default: true)\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const throttler = new LiteThrottler((scrollY: number) => {\n * updateScrollPosition(scrollY);\n * }, {\n * wait: 100,\n * onExecute: (args, throttler) => {\n * console.log('Updated scroll position:', args[0]);\n * }\n * });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', () => {\n * throttler.maybeExecute(window.scrollY);\n * });\n * ```\n */\nexport class LiteThrottler<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private lastExecutionTime = 0\n private isPending = false\n\n constructor(\n public fn: TFn,\n public options: LiteThrottlerOptions<TFn>,\n ) {\n // Default both leading and trailing to true if neither is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.leading = true\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the throttled function. The execution behavior depends on the throttler options:\n *\n * - If enough time has passed since the last execution (>= wait period):\n * - With leading=true: Executes immediately\n * - With leading=false: Waits for the next trailing execution\n *\n * - If within the wait period:\n * - With trailing=true: Schedules execution for end of wait period\n * - With trailing=false: Drops the execution\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n const timeSinceLastExecution = now - this.lastExecutionTime\n\n // Handle leading execution\n if (this.options.leading && timeSinceLastExecution >= this.options.wait) {\n this.execute(...args)\n } else {\n // Store the most recent arguments for potential trailing execution\n this.lastArgs = args\n\n // Set up trailing execution if not already scheduled\n if (!this.timeoutId && this.options.trailing) {\n const timeoutDuration = this.options.wait - timeSinceLastExecution\n this.isPending = true\n this.timeoutId = setTimeout(() => {\n if (this.lastArgs !== undefined) {\n this.execute(...this.lastArgs)\n }\n }, timeoutDuration)\n }\n }\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastExecutionTime = Date.now()\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.isPending && this.lastArgs) {\n this.execute(...this.lastArgs)\n }\n }\n\n /**\n * Cancels any pending trailing execution and clears internal state.\n * If a trailing execution is scheduled, this will prevent that execution from occurring.\n */\n cancel = (): void => {\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n }\n}\n\n/**\n * Creates a lightweight throttled function that limits how often the provided function can execute.\n *\n * This is an alternative to the throttle function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a throttler with no external dependencies, devtools integration, or reactive state.\n *\n * Throttling ensures a function executes at most once within a specified time window,\n * regardless of how many times it is called. This is useful for rate-limiting\n * expensive operations or UI updates.\n *\n * @example\n * ```ts\n * const throttledScroll = liteThrottle(() => {\n * updateScrollIndicator();\n * }, { wait: 100 });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', throttledScroll);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then throttles\n * const throttledResize = liteThrottle(() => {\n * recalculateLayout();\n * }, { wait: 250, leading: true, trailing: false });\n * ```\n */\nexport function liteThrottle<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteThrottlerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const throttler = new LiteThrottler(fn, options)\n return throttler.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,gBAAb,MAAoD;CAMlD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;2BALmB;mBACR;uBA2BJ,GAAG,SAAgC;GAEjD,MAAM,yBADM,KAAK,KACiB,GAAG,KAAK;GAG1C,IAAI,KAAK,QAAQ,WAAW,0BAA0B,KAAK,QAAQ,MACjE,KAAK,QAAQ,GAAG,KAAK;QAChB;IAEL,KAAK,WAAW;IAGhB,IAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,UAAU;KAC5C,MAAM,kBAAkB,KAAK,QAAQ,OAAO;KAC5C,KAAK,YAAY;KACjB,KAAK,YAAY,iBAAiB;MAChC,IAAI,KAAK,aAAa,QACpB,KAAK,QAAQ,GAAG,KAAK,SAAS;QAE/B,gBAAgB;;;;kBAKN,GAAG,SAAgC;GACpD,KAAK,GAAG,GAAG,KAAK;GAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;GACpC,KAAK,oBAAoB,KAAK,KAAK;GACnC,KAAK,cAAc;GACnB,KAAK,WAAW;GAChB,KAAK,YAAY;;qBAQC;GAClB,IAAI,KAAK,aAAa,KAAK,UACzB,KAAK,QAAQ,GAAG,KAAK,SAAS;;sBAQb;GACnB,KAAK,cAAc;GACnB,KAAK,WAAW;GAChB,KAAK,YAAY;;4BAGgB;GACjC,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;;EA7EnB,IACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAC1B;GACA,KAAK,QAAQ,UAAU;GACvB,KAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0G9B,SAAgB,aACd,IACA,SACoC;CAEpC,OAAO,IADe,cAAc,IAAI,QACxB,CAAC"}
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.cjs";
2
2
 
3
3
  //#region src/lite-throttler.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite throttled function
7
6
  */
@@ -1,7 +1,6 @@
1
- import { AnyFunction } from "@tanstack/pacer/types";
1
+ import { AnyFunction } from "./pacer/dist/types.js";
2
2
 
3
3
  //#region src/lite-throttler.d.ts
4
-
5
4
  /**
6
5
  * Options for configuring a lite throttled function
7
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"lite-throttler.js","names":["fn: TFn","options: LiteThrottlerOptions<TFn>"],"sources":["../src/lite-throttler.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite throttled function\n */\nexport interface LiteThrottlerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * Defaults to true.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, throttler: LiteThrottler<TFn>) => void\n /**\n * Whether to execute on the trailing edge of the timeout.\n * Defaults to true.\n */\n trailing?: boolean\n /**\n * Time window in milliseconds during which the function can only be executed once.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a throttled function.\n *\n * This is an alternative to the Throttler in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Throttler,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential throttling functionality.\n *\n * Throttling ensures a function is called at most once within a specified time window.\n * Unlike debouncing which waits for a pause in calls, throttling guarantees consistent\n * execution timing regardless of call frequency.\n *\n * Supports both leading and trailing edge execution:\n * - Leading: Execute immediately on first call (default: true)\n * - Trailing: Execute after wait period if called during throttle (default: true)\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const throttler = new LiteThrottler((scrollY: number) => {\n * updateScrollPosition(scrollY);\n * }, {\n * wait: 100,\n * onExecute: (args, throttler) => {\n * console.log('Updated scroll position:', args[0]);\n * }\n * });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', () => {\n * throttler.maybeExecute(window.scrollY);\n * });\n * ```\n */\nexport class LiteThrottler<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private lastExecutionTime = 0\n private isPending = false\n\n constructor(\n public fn: TFn,\n public options: LiteThrottlerOptions<TFn>,\n ) {\n // Default both leading and trailing to true if neither is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.leading = true\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the throttled function. The execution behavior depends on the throttler options:\n *\n * - If enough time has passed since the last execution (>= wait period):\n * - With leading=true: Executes immediately\n * - With leading=false: Waits for the next trailing execution\n *\n * - If within the wait period:\n * - With trailing=true: Schedules execution for end of wait period\n * - With trailing=false: Drops the execution\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n const timeSinceLastExecution = now - this.lastExecutionTime\n\n // Handle leading execution\n if (this.options.leading && timeSinceLastExecution >= this.options.wait) {\n this.execute(...args)\n } else {\n // Store the most recent arguments for potential trailing execution\n this.lastArgs = args\n\n // Set up trailing execution if not already scheduled\n if (!this.timeoutId && this.options.trailing) {\n const timeoutDuration = this.options.wait - timeSinceLastExecution\n this.isPending = true\n this.timeoutId = setTimeout(() => {\n if (this.lastArgs !== undefined) {\n this.execute(...this.lastArgs)\n }\n }, timeoutDuration)\n }\n }\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastExecutionTime = Date.now()\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.isPending && this.lastArgs) {\n this.execute(...this.lastArgs)\n }\n }\n\n /**\n * Cancels any pending trailing execution and clears internal state.\n * If a trailing execution is scheduled, this will prevent that execution from occurring.\n */\n cancel = (): void => {\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n }\n}\n\n/**\n * Creates a lightweight throttled function that limits how often the provided function can execute.\n *\n * This is an alternative to the throttle function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a throttler with no external dependencies, devtools integration, or reactive state.\n *\n * Throttling ensures a function executes at most once within a specified time window,\n * regardless of how many times it is called. This is useful for rate-limiting\n * expensive operations or UI updates.\n *\n * @example\n * ```ts\n * const throttledScroll = liteThrottle(() => {\n * updateScrollIndicator();\n * }, { wait: 100 });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', throttledScroll);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then throttles\n * const throttledResize = liteThrottle(() => {\n * recalculateLayout();\n * }, { wait: 250, leading: true, trailing: false });\n * ```\n */\nexport function liteThrottle<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteThrottlerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const throttler = new LiteThrottler(fn, options)\n return throttler.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,gBAAb,MAAoD;CAMlD,YACE,AAAOA,IACP,AAAOC,SACP;EAFO;EACA;2BALmB;mBACR;uBA2BJ,GAAG,SAAgC;GAEjD,MAAM,yBADM,KAAK,KAAK,GACe,KAAK;AAG1C,OAAI,KAAK,QAAQ,WAAW,0BAA0B,KAAK,QAAQ,KACjE,MAAK,QAAQ,GAAG,KAAK;QAChB;AAEL,SAAK,WAAW;AAGhB,QAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,UAAU;KAC5C,MAAM,kBAAkB,KAAK,QAAQ,OAAO;AAC5C,UAAK,YAAY;AACjB,UAAK,YAAY,iBAAiB;AAChC,UAAI,KAAK,aAAa,OACpB,MAAK,QAAQ,GAAG,KAAK,SAAS;QAE/B,gBAAgB;;;;kBAKN,GAAG,SAAgC;AACpD,QAAK,GAAG,GAAG,KAAK;AAChB,QAAK,QAAQ,YAAY,MAAM,KAAK;AACpC,QAAK,oBAAoB,KAAK,KAAK;AACnC,QAAK,cAAc;AACnB,QAAK,WAAW;AAChB,QAAK,YAAY;;qBAQC;AAClB,OAAI,KAAK,aAAa,KAAK,SACzB,MAAK,QAAQ,GAAG,KAAK,SAAS;;sBAQb;AACnB,QAAK,cAAc;AACnB,QAAK,WAAW;AAChB,QAAK,YAAY;;4BAGgB;AACjC,OAAI,KAAK,WAAW;AAClB,iBAAa,KAAK,UAAU;AAC5B,SAAK,YAAY;;;AA7EnB,MACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAC1B;AACA,QAAK,QAAQ,UAAU;AACvB,QAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0G9B,SAAgB,aACd,IACA,SACoC;AAEpC,QADkB,IAAI,cAAc,IAAI,QAAQ,CAC/B"}
1
+ {"version":3,"file":"lite-throttler.js","names":[],"sources":["../src/lite-throttler.ts"],"sourcesContent":["import type { AnyFunction } from '@tanstack/pacer/types'\n\n/**\n * Options for configuring a lite throttled function\n */\nexport interface LiteThrottlerOptions<TFn extends AnyFunction = AnyFunction> {\n /**\n * Whether to execute on the leading edge of the timeout.\n * Defaults to true.\n */\n leading?: boolean\n /**\n * Callback function that is called after the function is executed\n */\n onExecute?: (args: Parameters<TFn>, throttler: LiteThrottler<TFn>) => void\n /**\n * Whether to execute on the trailing edge of the timeout.\n * Defaults to true.\n */\n trailing?: boolean\n /**\n * Time window in milliseconds during which the function can only be executed once.\n */\n wait: number\n}\n\n/**\n * A lightweight class that creates a throttled function.\n *\n * This is an alternative to the Throttler in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core Throttler,\n * this version does not use TanStack Store for state management, has no devtools integration,\n * and provides only essential throttling functionality.\n *\n * Throttling ensures a function is called at most once within a specified time window.\n * Unlike debouncing which waits for a pause in calls, throttling guarantees consistent\n * execution timing regardless of call frequency.\n *\n * Supports both leading and trailing edge execution:\n * - Leading: Execute immediately on first call (default: true)\n * - Trailing: Execute after wait period if called during throttle (default: true)\n *\n * Features:\n * - Zero dependencies - no external libraries required\n * - Minimal API surface - only essential methods (maybeExecute, flush, cancel)\n * - Simple state management - uses basic private properties instead of reactive stores\n * - Callback support for monitoring execution events\n * - Lightweight - designed for use in npm packages where bundle size matters\n *\n * @example\n * ```ts\n * const throttler = new LiteThrottler((scrollY: number) => {\n * updateScrollPosition(scrollY);\n * }, {\n * wait: 100,\n * onExecute: (args, throttler) => {\n * console.log('Updated scroll position:', args[0]);\n * }\n * });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', () => {\n * throttler.maybeExecute(window.scrollY);\n * });\n * ```\n */\nexport class LiteThrottler<TFn extends AnyFunction> {\n private timeoutId: NodeJS.Timeout | undefined\n private lastArgs: Parameters<TFn> | undefined\n private lastExecutionTime = 0\n private isPending = false\n\n constructor(\n public fn: TFn,\n public options: LiteThrottlerOptions<TFn>,\n ) {\n // Default both leading and trailing to true if neither is specified\n if (\n this.options.leading === undefined &&\n this.options.trailing === undefined\n ) {\n this.options.leading = true\n this.options.trailing = true\n }\n }\n\n /**\n * Attempts to execute the throttled function. The execution behavior depends on the throttler options:\n *\n * - If enough time has passed since the last execution (>= wait period):\n * - With leading=true: Executes immediately\n * - With leading=false: Waits for the next trailing execution\n *\n * - If within the wait period:\n * - With trailing=true: Schedules execution for end of wait period\n * - With trailing=false: Drops the execution\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n const now = Date.now()\n const timeSinceLastExecution = now - this.lastExecutionTime\n\n // Handle leading execution\n if (this.options.leading && timeSinceLastExecution >= this.options.wait) {\n this.execute(...args)\n } else {\n // Store the most recent arguments for potential trailing execution\n this.lastArgs = args\n\n // Set up trailing execution if not already scheduled\n if (!this.timeoutId && this.options.trailing) {\n const timeoutDuration = this.options.wait - timeSinceLastExecution\n this.isPending = true\n this.timeoutId = setTimeout(() => {\n if (this.lastArgs !== undefined) {\n this.execute(...this.lastArgs)\n }\n }, timeoutDuration)\n }\n }\n }\n\n private execute = (...args: Parameters<TFn>): void => {\n this.fn(...args)\n this.options.onExecute?.(args, this)\n this.lastExecutionTime = Date.now()\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n /**\n * Processes the current pending execution immediately.\n * If there's a pending execution, it will be executed right away\n * and the timeout will be cleared.\n */\n flush = (): void => {\n if (this.isPending && this.lastArgs) {\n this.execute(...this.lastArgs)\n }\n }\n\n /**\n * Cancels any pending trailing execution and clears internal state.\n * If a trailing execution is scheduled, this will prevent that execution from occurring.\n */\n cancel = (): void => {\n this.clearTimeout()\n this.lastArgs = undefined\n this.isPending = false\n }\n\n private clearTimeout = (): void => {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n }\n }\n}\n\n/**\n * Creates a lightweight throttled function that limits how often the provided function can execute.\n *\n * This is an alternative to the throttle function in the core @tanstack/pacer package, but is more\n * suitable for libraries and npm packages that need minimal overhead. Unlike the core version,\n * this function creates a throttler with no external dependencies, devtools integration, or reactive state.\n *\n * Throttling ensures a function executes at most once within a specified time window,\n * regardless of how many times it is called. This is useful for rate-limiting\n * expensive operations or UI updates.\n *\n * @example\n * ```ts\n * const throttledScroll = liteThrottle(() => {\n * updateScrollIndicator();\n * }, { wait: 100 });\n *\n * // Will execute at most once per 100ms\n * window.addEventListener('scroll', throttledScroll);\n * ```\n *\n * @example\n * ```ts\n * // Leading edge execution - fires immediately then throttles\n * const throttledResize = liteThrottle(() => {\n * recalculateLayout();\n * }, { wait: 250, leading: true, trailing: false });\n * ```\n */\nexport function liteThrottle<TFn extends AnyFunction>(\n fn: TFn,\n options: LiteThrottlerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const throttler = new LiteThrottler(fn, options)\n return throttler.maybeExecute\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAa,gBAAb,MAAoD;CAMlD,YACE,AAAO,IACP,AAAO,SACP;EAFO;EACA;2BALmB;mBACR;uBA2BJ,GAAG,SAAgC;GAEjD,MAAM,yBADM,KAAK,KACiB,GAAG,KAAK;GAG1C,IAAI,KAAK,QAAQ,WAAW,0BAA0B,KAAK,QAAQ,MACjE,KAAK,QAAQ,GAAG,KAAK;QAChB;IAEL,KAAK,WAAW;IAGhB,IAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,UAAU;KAC5C,MAAM,kBAAkB,KAAK,QAAQ,OAAO;KAC5C,KAAK,YAAY;KACjB,KAAK,YAAY,iBAAiB;MAChC,IAAI,KAAK,aAAa,QACpB,KAAK,QAAQ,GAAG,KAAK,SAAS;QAE/B,gBAAgB;;;;kBAKN,GAAG,SAAgC;GACpD,KAAK,GAAG,GAAG,KAAK;GAChB,KAAK,QAAQ,YAAY,MAAM,KAAK;GACpC,KAAK,oBAAoB,KAAK,KAAK;GACnC,KAAK,cAAc;GACnB,KAAK,WAAW;GAChB,KAAK,YAAY;;qBAQC;GAClB,IAAI,KAAK,aAAa,KAAK,UACzB,KAAK,QAAQ,GAAG,KAAK,SAAS;;sBAQb;GACnB,KAAK,cAAc;GACnB,KAAK,WAAW;GAChB,KAAK,YAAY;;4BAGgB;GACjC,IAAI,KAAK,WAAW;IAClB,aAAa,KAAK,UAAU;IAC5B,KAAK,YAAY;;;EA7EnB,IACE,KAAK,QAAQ,YAAY,UACzB,KAAK,QAAQ,aAAa,QAC1B;GACA,KAAK,QAAQ,UAAU;GACvB,KAAK,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0G9B,SAAgB,aACd,IACA,SACoC;CAEpC,OAAO,IADe,cAAc,IAAI,QACxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ //#region ../pacer/dist/types.d.ts
2
+ //#region src/types.d.ts
3
+ /**
4
+ * Represents a function that can be called with any arguments and returns any value.
5
+ */
6
+ type AnyFunction = (...args: Array<any>) => any;
7
+ /**
8
+ * Represents an asynchronous function that can be called with any arguments and returns a promise.
9
+ */
10
+ //#endregion
11
+ export { AnyFunction };
12
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1,12 @@
1
+ //#region ../pacer/dist/types.d.ts
2
+ //#region src/types.d.ts
3
+ /**
4
+ * Represents a function that can be called with any arguments and returns any value.
5
+ */
6
+ type AnyFunction = (...args: Array<any>) => any;
7
+ /**
8
+ * Represents an asynchronous function that can be called with any arguments and returns a promise.
9
+ */
10
+ //#endregion
11
+ export { AnyFunction };
12
+ //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/pacer-lite",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Lightweight utilities for debouncing, throttling, and more - designed for npm packages.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -28,28 +28,28 @@
28
28
  "types": "./dist/index.d.cts",
29
29
  "exports": {
30
30
  ".": {
31
- "require": "./dist/index.cjs",
32
- "import": "./dist/index.js"
31
+ "import": "./dist/index.js",
32
+ "require": "./dist/index.cjs"
33
33
  },
34
34
  "./lite-batcher": {
35
- "require": "./dist/lite-batcher.cjs",
36
- "import": "./dist/lite-batcher.js"
35
+ "import": "./dist/lite-batcher.js",
36
+ "require": "./dist/lite-batcher.cjs"
37
37
  },
38
38
  "./lite-debouncer": {
39
- "require": "./dist/lite-debouncer.cjs",
40
- "import": "./dist/lite-debouncer.js"
39
+ "import": "./dist/lite-debouncer.js",
40
+ "require": "./dist/lite-debouncer.cjs"
41
41
  },
42
42
  "./lite-queuer": {
43
- "require": "./dist/lite-queuer.cjs",
44
- "import": "./dist/lite-queuer.js"
43
+ "import": "./dist/lite-queuer.js",
44
+ "require": "./dist/lite-queuer.cjs"
45
45
  },
46
46
  "./lite-rate-limiter": {
47
- "require": "./dist/lite-rate-limiter.cjs",
48
- "import": "./dist/lite-rate-limiter.js"
47
+ "import": "./dist/lite-rate-limiter.js",
48
+ "require": "./dist/lite-rate-limiter.cjs"
49
49
  },
50
50
  "./lite-throttler": {
51
- "require": "./dist/lite-throttler.cjs",
52
- "import": "./dist/lite-throttler.js"
51
+ "import": "./dist/lite-throttler.js",
52
+ "require": "./dist/lite-throttler.cjs"
53
53
  },
54
54
  "./package.json": "./package.json"
55
55
  },
@@ -62,7 +62,7 @@
62
62
  "src"
63
63
  ],
64
64
  "devDependencies": {
65
- "@tanstack/pacer": "0.17.0"
65
+ "@tanstack/pacer": "0.21.1"
66
66
  },
67
67
  "scripts": {
68
68
  "clean": "premove ./build ./dist",