@tanstack/pacer-lite
Advanced tools
| //#region ../pacer/dist/types.d.ts | ||
| //#region src/types.d.ts | ||
| /** | ||
| * Represents a function that can be called with any arguments and returns any value. | ||
| */ | ||
| type AnyFunction = (...args: Array<any>) => any; | ||
| /** | ||
| * Represents an asynchronous function that can be called with any arguments and returns a promise. | ||
| */ | ||
| //#endregion | ||
| export { AnyFunction }; | ||
| //# sourceMappingURL=types.d.cts.map |
| //#region ../pacer/dist/types.d.ts | ||
| //#region src/types.d.ts | ||
| /** | ||
| * Represents a function that can be called with any arguments and returns any value. | ||
| */ | ||
| type AnyFunction = (...args: Array<any>) => any; | ||
| /** | ||
| * Represents an asynchronous function that can be called with any arguments and returns a promise. | ||
| */ | ||
| //#endregion | ||
| export { AnyFunction }; | ||
| //# sourceMappingURL=types.d.ts.map |
+1
-0
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_lite_debouncer = require('./lite-debouncer.cjs'); | ||
@@ -2,0 +3,0 @@ const require_lite_throttler = require('./lite-throttler.cjs'); |
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
@@ -2,0 +3,0 @@ //#region src/lite-batcher.ts |
@@ -1,1 +0,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"} | ||
| {"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 +0,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"} | ||
| {"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"} |
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
@@ -2,0 +3,0 @@ //#region src/lite-debouncer.ts |
@@ -1,1 +0,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"} | ||
| {"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,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.cjs"; | ||
| //#region src/lite-debouncer.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite debounced function |
@@ -1,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.js"; | ||
| //#region src/lite-debouncer.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite debounced function |
@@ -1,1 +0,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"} | ||
| {"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"} |
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
@@ -2,0 +3,0 @@ //#region src/lite-queuer.ts |
@@ -1,1 +0,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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"} | ||
| {"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 +0,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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"} | ||
| {"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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"} |
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
@@ -2,0 +3,0 @@ //#region src/lite-rate-limiter.ts |
@@ -1,1 +0,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"} | ||
| {"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,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.cjs"; | ||
| //#region src/lite-rate-limiter.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite rate-limited function |
@@ -1,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.js"; | ||
| //#region src/lite-rate-limiter.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite rate-limited function |
@@ -1,1 +0,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"} | ||
| {"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"} |
@@ -0,1 +1,2 @@ | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
@@ -2,0 +3,0 @@ //#region src/lite-throttler.ts |
@@ -1,1 +0,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"} | ||
| {"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,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.cjs"; | ||
| //#region src/lite-throttler.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite throttled function |
@@ -1,5 +0,4 @@ | ||
| import { AnyFunction } from "@tanstack/pacer/types"; | ||
| import { AnyFunction } from "./pacer/dist/types.js"; | ||
| //#region src/lite-throttler.d.ts | ||
| /** | ||
@@ -6,0 +5,0 @@ * Options for configuring a lite throttled function |
@@ -1,1 +0,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"} | ||
| {"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"} |
+14
-14
| { | ||
| "name": "@tanstack/pacer-lite", | ||
| "version": "0.2.1", | ||
| "version": "0.2.2", | ||
| "description": "Lightweight utilities for debouncing, throttling, and more - designed for npm packages.", | ||
@@ -31,24 +31,24 @@ "author": "Tanner Linsley", | ||
| ".": { | ||
| "require": "./dist/index.cjs", | ||
| "import": "./dist/index.js" | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.cjs" | ||
| }, | ||
| "./lite-batcher": { | ||
| "require": "./dist/lite-batcher.cjs", | ||
| "import": "./dist/lite-batcher.js" | ||
| "import": "./dist/lite-batcher.js", | ||
| "require": "./dist/lite-batcher.cjs" | ||
| }, | ||
| "./lite-debouncer": { | ||
| "require": "./dist/lite-debouncer.cjs", | ||
| "import": "./dist/lite-debouncer.js" | ||
| "import": "./dist/lite-debouncer.js", | ||
| "require": "./dist/lite-debouncer.cjs" | ||
| }, | ||
| "./lite-queuer": { | ||
| "require": "./dist/lite-queuer.cjs", | ||
| "import": "./dist/lite-queuer.js" | ||
| "import": "./dist/lite-queuer.js", | ||
| "require": "./dist/lite-queuer.cjs" | ||
| }, | ||
| "./lite-rate-limiter": { | ||
| "require": "./dist/lite-rate-limiter.cjs", | ||
| "import": "./dist/lite-rate-limiter.js" | ||
| "import": "./dist/lite-rate-limiter.js", | ||
| "require": "./dist/lite-rate-limiter.cjs" | ||
| }, | ||
| "./lite-throttler": { | ||
| "require": "./dist/lite-throttler.cjs", | ||
| "import": "./dist/lite-throttler.js" | ||
| "import": "./dist/lite-throttler.js", | ||
| "require": "./dist/lite-throttler.cjs" | ||
| }, | ||
@@ -66,3 +66,3 @@ "./package.json": "./package.json" | ||
| "devDependencies": { | ||
| "@tanstack/pacer": "0.17.1" | ||
| "@tanstack/pacer": "0.21.1" | ||
| }, | ||
@@ -69,0 +69,0 @@ "scripts": { |
+9
-9
@@ -89,3 +89,3 @@ <div align="center"> | ||
| > [!NOTE] | ||
| > You may know **TanSack Pacer** by our adapter names, too! | ||
| > You may know **TanStack Pacer** by our adapter names, too! | ||
| > | ||
@@ -95,3 +95,3 @@ > - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react/react-pacer) | ||
| > - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid/solid-pacer) | ||
| > - Angular Pacer - needs a contributor! | ||
| > - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular/angular-pacer) | ||
| > - Svelte Pacer - needs a contributor! | ||
@@ -111,8 +111,8 @@ > - Vue Pacer - needs a contributor! | ||
| <tr> | ||
| <td> | ||
| <td> | ||
| <a href="https://www.coderabbit.ai/?via=tanstack&dub_id=aCcEEdAOqqutX6OS" > | ||
| <picture> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/coderabbit-dark-CMcuvjEy.svg" height="40" /> | ||
| <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/coderabbit-light-DVMJ2jHi.svg" height="40" /> | ||
| <img src="https://tanstack.com/assets/coderabbit-light-DVMJ2jHi.svg" height="40" alt="CodeRabbit" /> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/coderabbit-dark-D643Zkrv.svg" /> | ||
| <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" /> | ||
| <img src="https://tanstack.com/assets/coderabbit-light-CIzGLYU_.svg" height="40" alt="CodeRabbit" /> | ||
| </picture> | ||
@@ -124,5 +124,5 @@ </a> | ||
| <picture> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/cloudflare-white-DQDB7UaL.svg" height="60" /> | ||
| <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/cloudflare-black-CPufaW0B.svg" height="60" /> | ||
| <img src="https://tanstack.com/assets/cloudflare-black-CPufaW0B.svg" height="60" alt="Cloudflare" /> | ||
| <source media="(prefers-color-scheme: dark)" srcset="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" /> | ||
| <source media="(prefers-color-scheme: light)" srcset="https://tanstack.com/assets/cloudflare-black-6Ojsn8yh.svg" /> | ||
| <img src="https://tanstack.com/assets/cloudflare-white-Co-Tyjbl.svg" height="60" alt="Cloudflare" /> | ||
| </picture> | ||
@@ -129,0 +129,0 @@ </a> |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
267008
0.22%45
4.65%3636
0.47%