@tanstack/pacer 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/cjs/async-batcher.cjs +163 -0
  2. package/dist/cjs/async-batcher.cjs.map +1 -0
  3. package/dist/cjs/async-batcher.d.cts +273 -0
  4. package/dist/cjs/async-debouncer.cjs +149 -162
  5. package/dist/cjs/async-debouncer.cjs.map +1 -1
  6. package/dist/cjs/async-debouncer.d.cts +76 -57
  7. package/dist/cjs/async-queuer.cjs +282 -343
  8. package/dist/cjs/async-queuer.cjs.map +1 -1
  9. package/dist/cjs/async-queuer.d.cts +121 -100
  10. package/dist/cjs/async-rate-limiter.cjs +128 -185
  11. package/dist/cjs/async-rate-limiter.cjs.map +1 -1
  12. package/dist/cjs/async-rate-limiter.d.cts +72 -61
  13. package/dist/cjs/async-throttler.cjs +168 -178
  14. package/dist/cjs/async-throttler.cjs.map +1 -1
  15. package/dist/cjs/async-throttler.d.cts +97 -69
  16. package/dist/cjs/batcher.cjs +110 -119
  17. package/dist/cjs/batcher.cjs.map +1 -1
  18. package/dist/cjs/batcher.d.cts +76 -51
  19. package/dist/cjs/debouncer.cjs +97 -85
  20. package/dist/cjs/debouncer.cjs.map +1 -1
  21. package/dist/cjs/debouncer.d.cts +54 -26
  22. package/dist/cjs/index.cjs +3 -6
  23. package/dist/cjs/index.cjs.map +1 -1
  24. package/dist/cjs/index.d.cts +1 -1
  25. package/dist/cjs/queuer.cjs +246 -294
  26. package/dist/cjs/queuer.cjs.map +1 -1
  27. package/dist/cjs/queuer.d.cts +102 -81
  28. package/dist/cjs/rate-limiter.cjs +97 -130
  29. package/dist/cjs/rate-limiter.cjs.map +1 -1
  30. package/dist/cjs/rate-limiter.d.cts +50 -37
  31. package/dist/cjs/throttler.cjs +107 -123
  32. package/dist/cjs/throttler.cjs.map +1 -1
  33. package/dist/cjs/throttler.d.cts +59 -35
  34. package/dist/cjs/utils.cjs +0 -13
  35. package/dist/cjs/utils.cjs.map +1 -1
  36. package/dist/cjs/utils.d.cts +0 -1
  37. package/dist/esm/async-batcher.d.ts +273 -0
  38. package/dist/esm/async-batcher.js +163 -0
  39. package/dist/esm/async-batcher.js.map +1 -0
  40. package/dist/esm/async-debouncer.d.ts +76 -57
  41. package/dist/esm/async-debouncer.js +149 -162
  42. package/dist/esm/async-debouncer.js.map +1 -1
  43. package/dist/esm/async-queuer.d.ts +121 -100
  44. package/dist/esm/async-queuer.js +282 -343
  45. package/dist/esm/async-queuer.js.map +1 -1
  46. package/dist/esm/async-rate-limiter.d.ts +72 -61
  47. package/dist/esm/async-rate-limiter.js +128 -185
  48. package/dist/esm/async-rate-limiter.js.map +1 -1
  49. package/dist/esm/async-throttler.d.ts +97 -69
  50. package/dist/esm/async-throttler.js +168 -178
  51. package/dist/esm/async-throttler.js.map +1 -1
  52. package/dist/esm/batcher.d.ts +76 -51
  53. package/dist/esm/batcher.js +110 -119
  54. package/dist/esm/batcher.js.map +1 -1
  55. package/dist/esm/debouncer.d.ts +54 -26
  56. package/dist/esm/debouncer.js +97 -85
  57. package/dist/esm/debouncer.js.map +1 -1
  58. package/dist/esm/index.d.ts +1 -1
  59. package/dist/esm/index.js +4 -7
  60. package/dist/esm/queuer.d.ts +102 -81
  61. package/dist/esm/queuer.js +246 -294
  62. package/dist/esm/queuer.js.map +1 -1
  63. package/dist/esm/rate-limiter.d.ts +50 -37
  64. package/dist/esm/rate-limiter.js +97 -130
  65. package/dist/esm/rate-limiter.js.map +1 -1
  66. package/dist/esm/throttler.d.ts +59 -35
  67. package/dist/esm/throttler.js +107 -123
  68. package/dist/esm/throttler.js.map +1 -1
  69. package/dist/esm/utils.d.ts +0 -1
  70. package/dist/esm/utils.js +0 -13
  71. package/dist/esm/utils.js.map +1 -1
  72. package/package.json +14 -11
  73. package/src/async-batcher.ts +475 -0
  74. package/src/async-debouncer.ts +201 -121
  75. package/src/async-queuer.ts +337 -216
  76. package/src/async-rate-limiter.ts +176 -136
  77. package/src/async-throttler.ts +233 -139
  78. package/src/batcher.ts +158 -92
  79. package/src/debouncer.ts +135 -52
  80. package/src/index.ts +1 -1
  81. package/src/queuer.ts +348 -226
  82. package/src/rate-limiter.ts +125 -80
  83. package/src/throttler.ts +152 -78
  84. package/src/utils.ts +0 -15
  85. package/dist/cjs/compare.cjs +0 -72
  86. package/dist/cjs/compare.cjs.map +0 -1
  87. package/dist/cjs/compare.d.cts +0 -12
  88. package/dist/esm/compare.d.ts +0 -12
  89. package/dist/esm/compare.js +0 -72
  90. package/dist/esm/compare.js.map +0 -1
  91. package/src/compare.ts +0 -105
@@ -1 +1 @@
1
- {"version":3,"file":"debouncer.js","sources":["../../src/debouncer.ts"],"sourcesContent":["import { parseFunctionOrValue } from './utils'\nimport type { AnyFunction } from './types'\n\n/**\n * Options for configuring a debounced function\n */\nexport interface DebouncerOptions<TFn extends AnyFunction> {\n /**\n * Whether the debouncer is enabled. When disabled, maybeExecute will not trigger any executions.\n * Can be a boolean or a function that returns a boolean.\n * Defaults to true.\n */\n enabled?: boolean | ((debouncer: Debouncer<TFn>) => boolean)\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?: (debouncer: Debouncer<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 * Can be a number or a function that returns a number.\n * Defaults to 0ms\n */\n wait: number | ((debouncer: Debouncer<TFn>) => number)\n}\n\nconst defaultOptions: Required<DebouncerOptions<any>> = {\n enabled: true,\n leading: false,\n onExecute: () => {},\n trailing: true,\n wait: 0,\n}\n\n/**\n * A class that creates a debounced function.\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 * @example\n * ```ts\n * const debouncer = new Debouncer((value: string) => {\n * saveToDatabase(value);\n * }, { wait: 500 });\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 Debouncer<TFn extends AnyFunction> {\n private _canLeadingExecute = true\n private _executionCount = 0\n private _isPending = false\n private _options: Required<DebouncerOptions<TFn>>\n private _timeoutId: NodeJS.Timeout | undefined\n\n constructor(\n private fn: TFn,\n initialOptions: DebouncerOptions<TFn>,\n ) {\n this._options = {\n ...defaultOptions,\n ...initialOptions,\n }\n }\n\n /**\n * Updates the debouncer options\n */\n setOptions(newOptions: Partial<DebouncerOptions<TFn>>): void {\n this._options = { ...this._options, ...newOptions }\n\n // End the pending state if the debouncer is disabled\n if (!this._options.enabled) {\n this._isPending = false\n }\n }\n\n /**\n * Returns the current debouncer options\n */\n getOptions(): Required<DebouncerOptions<TFn>> {\n return this._options\n }\n\n /**\n * Returns the current enabled state of the debouncer\n */\n getEnabled(): boolean {\n return parseFunctionOrValue(this._options.enabled, this)\n }\n\n /**\n * Returns the current wait time in milliseconds\n */\n getWait(): number {\n return parseFunctionOrValue(this._options.wait, this)\n }\n\n /**\n * Attempts to execute the debounced function\n * If a call is already in progress, it will be queued\n */\n maybeExecute(...args: Parameters<TFn>): void {\n let _didLeadingExecute = false\n\n // Handle leading execution\n if (this._options.leading && this._canLeadingExecute) {\n this._canLeadingExecute = false\n _didLeadingExecute = true\n this.execute(...args)\n }\n\n // Start pending state to indicate that the debouncer is waiting for the trailing edge\n if (this._options.trailing) {\n this._isPending = true\n }\n\n // Clear any existing timeout\n if (this._timeoutId) clearTimeout(this._timeoutId)\n\n // Set new timeout that will reset canLeadingExecute and execute trailing only if enabled and did not execute leading\n this._timeoutId = setTimeout(() => {\n this._canLeadingExecute = true\n if (this._options.trailing && !_didLeadingExecute) {\n this.execute(...args)\n }\n }, this.getWait())\n }\n\n private execute(...args: Parameters<TFn>): void {\n if (!this.getEnabled()) return undefined\n this.fn(...args) // EXECUTE!\n this._isPending = false\n this._executionCount++\n this._options.onExecute(this)\n }\n\n /**\n * Cancels any pending execution\n */\n cancel(): void {\n if (this._timeoutId) {\n clearTimeout(this._timeoutId)\n this._canLeadingExecute = true\n this._isPending = false\n }\n }\n\n /**\n * Returns the number of times the function has been executed\n */\n getExecutionCount(): number {\n return this._executionCount\n }\n\n /**\n * Returns `true` if debouncing\n */\n getIsPending(): boolean {\n return this.getEnabled() && this._isPending\n }\n}\n\n/**\n * Creates a 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 the the simple function wrapper implementation pulled from the Debouncer class. If you need\n * more control over the debouncing behavior, use the Debouncer class directly.\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 debounced = debounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debounced);\n * ```\n */\nexport function debounce<TFn extends AnyFunction>(\n fn: TFn,\n initialOptions: DebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new Debouncer(fn, initialOptions)\n return debouncer.maybeExecute.bind(debouncer)\n}\n"],"names":[],"mappings":";AAoCA,MAAM,iBAAkD;AAAA,EACtD,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW,MAAM;AAAA,EAAC;AAAA,EAClB,UAAU;AAAA,EACV,MAAM;AACR;AAyBO,MAAM,UAAmC;AAAA,EAO9C,YACU,IACR,gBACA;AAFQ,SAAA,KAAA;AAPV,SAAQ,qBAAqB;AAC7B,SAAQ,kBAAkB;AAC1B,SAAQ,aAAa;AAQnB,SAAK,WAAW;AAAA,MACd,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMF,WAAW,YAAkD;AAC3D,SAAK,WAAW,EAAE,GAAG,KAAK,UAAU,GAAG,WAAW;AAG9C,QAAA,CAAC,KAAK,SAAS,SAAS;AAC1B,WAAK,aAAa;AAAA,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAMF,aAA8C;AAC5C,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMd,aAAsB;AACpB,WAAO,qBAAqB,KAAK,SAAS,SAAS,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMzD,UAAkB;AAChB,WAAO,qBAAqB,KAAK,SAAS,MAAM,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,gBAAgB,MAA6B;AAC3C,QAAI,qBAAqB;AAGzB,QAAI,KAAK,SAAS,WAAW,KAAK,oBAAoB;AACpD,WAAK,qBAAqB;AACL,2BAAA;AAChB,WAAA,QAAQ,GAAG,IAAI;AAAA,IAAA;AAIlB,QAAA,KAAK,SAAS,UAAU;AAC1B,WAAK,aAAa;AAAA,IAAA;AAIpB,QAAI,KAAK,WAAyB,cAAA,KAAK,UAAU;AAG5C,SAAA,aAAa,WAAW,MAAM;AACjC,WAAK,qBAAqB;AAC1B,UAAI,KAAK,SAAS,YAAY,CAAC,oBAAoB;AAC5C,aAAA,QAAQ,GAAG,IAAI;AAAA,MAAA;AAAA,IACtB,GACC,KAAK,SAAS;AAAA,EAAA;AAAA,EAGX,WAAW,MAA6B;AAC9C,QAAI,CAAC,KAAK,WAAW,EAAU,QAAA;AAC1B,SAAA,GAAG,GAAG,IAAI;AACf,SAAK,aAAa;AACb,SAAA;AACA,SAAA,SAAS,UAAU,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,SAAe;AACb,QAAI,KAAK,YAAY;AACnB,mBAAa,KAAK,UAAU;AAC5B,WAAK,qBAAqB;AAC1B,WAAK,aAAa;AAAA,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAMF,oBAA4B;AAC1B,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMd,eAAwB;AACf,WAAA,KAAK,gBAAgB,KAAK;AAAA,EAAA;AAErC;AAsBgB,SAAA,SACd,IACA,gBACoC;AACpC,QAAM,YAAY,IAAI,UAAU,IAAI,cAAc;AAC3C,SAAA,UAAU,aAAa,KAAK,SAAS;AAC9C;"}
1
+ {"version":3,"file":"debouncer.js","sources":["../../src/debouncer.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport { parseFunctionOrValue } from './utils'\nimport type { AnyFunction } from './types'\n\nexport interface DebouncerState<TFn extends AnyFunction> {\n /**\n * Whether the debouncer can execute on the leading edge of the timeout\n */\n canLeadingExecute: boolean\n /**\n * Number of function executions that have been completed\n */\n executionCount: number\n /**\n * Whether the debouncer is waiting for the timeout to trigger execution\n */\n isPending: boolean\n /**\n * The arguments from the most recent call to maybeExecute\n */\n lastArgs: Parameters<TFn> | undefined\n /**\n * Current execution status - 'idle' when not active, 'pending' when waiting for timeout\n */\n status: 'disabled' | 'idle' | 'pending'\n}\n\nfunction getDefaultDebouncerState<\n TFn extends AnyFunction,\n>(): DebouncerState<TFn> {\n return structuredClone({\n canLeadingExecute: true,\n executionCount: 0,\n isPending: false,\n lastArgs: undefined,\n status: 'idle',\n })\n}\n\n/**\n * Options for configuring a debounced function\n */\nexport interface DebouncerOptions<TFn extends AnyFunction> {\n /**\n * Whether the debouncer is enabled. When disabled, maybeExecute will not trigger any executions.\n * Can be a boolean or a function that returns a boolean.\n * Defaults to true.\n */\n enabled?: boolean | ((debouncer: Debouncer<TFn>) => boolean)\n /**\n * Initial state for the debouncer\n */\n initialState?: Partial<DebouncerState<TFn>>\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?: (debouncer: Debouncer<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 * Can be a number or a function that returns a number.\n * Defaults to 0ms\n */\n wait: number | ((debouncer: Debouncer<TFn>) => number)\n}\n\nconst defaultOptions: Omit<\n Required<DebouncerOptions<any>>,\n 'initialState' | 'onExecute'\n> = {\n enabled: true,\n leading: false,\n trailing: true,\n wait: 0,\n}\n\n/**\n * A class that creates a debounced function.\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 * State Management:\n * - Uses TanStack Store for reactive state management\n * - Use `initialState` to provide initial state values when creating the debouncer\n * - Use `onExecute` callback to react to function execution and implement custom logic\n * - The state includes canLeadingExecute, execution count, and isPending status\n * - State can be accessed via `debouncer.store.state` when using the class directly\n * - When using framework adapters (React/Solid), state is accessed from `debouncer.state`\n *\n * @example\n * ```ts\n * const debouncer = new Debouncer((value: string) => {\n * saveToDatabase(value);\n * }, { wait: 500 });\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 Debouncer<TFn extends AnyFunction> {\n readonly store: Store<Readonly<DebouncerState<TFn>>> = new Store(\n getDefaultDebouncerState<TFn>(),\n )\n options: DebouncerOptions<TFn>\n #timeoutId: NodeJS.Timeout | undefined\n\n constructor(\n private fn: TFn,\n initialOptions: DebouncerOptions<TFn>,\n ) {\n this.options = {\n ...defaultOptions,\n ...initialOptions,\n }\n this.#setState(this.options.initialState ?? {})\n }\n\n /**\n * Updates the debouncer options\n */\n setOptions = (newOptions: Partial<DebouncerOptions<TFn>>): void => {\n this.options = { ...this.options, ...newOptions }\n\n // Cancel pending execution if the debouncer is disabled\n if (!this.#getEnabled()) {\n this.cancel()\n }\n }\n\n #setState = (newState: Partial<DebouncerState<TFn>>): void => {\n this.store.setState((state) => {\n const combinedState = {\n ...state,\n ...newState,\n }\n const { isPending } = combinedState\n return {\n ...combinedState,\n status: !this.#getEnabled()\n ? 'disabled'\n : isPending\n ? 'pending'\n : 'idle',\n }\n })\n }\n\n /**\n * Returns the current enabled state of the debouncer\n */\n #getEnabled = (): boolean => {\n return !!parseFunctionOrValue(this.options.enabled, this)\n }\n\n /**\n * Returns the current wait time in milliseconds\n */\n #getWait = (): number => {\n return parseFunctionOrValue(this.options.wait, this)\n }\n\n /**\n * Attempts to execute the debounced function\n * If a call is already in progress, it will be queued\n */\n maybeExecute = (...args: Parameters<TFn>): void => {\n if (!this.#getEnabled()) return undefined\n let _didLeadingExecute = false\n\n // Handle leading execution\n if (this.options.leading && this.store.state.canLeadingExecute) {\n this.#setState({ canLeadingExecute: false })\n _didLeadingExecute = true\n this.#execute(...args)\n }\n\n // Start pending state to indicate that the debouncer is waiting for the trailing edge\n if (this.options.trailing) {\n this.#setState({ isPending: true, lastArgs: args })\n }\n\n // Clear any existing timeout\n if (this.#timeoutId) clearTimeout(this.#timeoutId)\n\n // Set new timeout that will reset canLeadingExecute and execute trailing only if enabled and did not execute leading\n this.#timeoutId = setTimeout(() => {\n this.#setState({ canLeadingExecute: true })\n if (this.options.trailing && !_didLeadingExecute) {\n this.#execute(...args)\n }\n }, this.#getWait())\n }\n\n #execute = (...args: Parameters<TFn>): void => {\n if (!this.#getEnabled()) return undefined\n this.fn(...args) // EXECUTE!\n this.#setState({\n isPending: false,\n executionCount: this.store.state.executionCount + 1,\n })\n this.options.onExecute?.(this)\n }\n\n /**\n * Processes the current pending execution immediately\n */\n flush = (): void => {\n if (this.store.state.isPending && this.store.state.lastArgs) {\n this.#clearTimeout() // clear any pending timeout\n this.#execute(...this.store.state.lastArgs) // execute immediately\n }\n }\n\n #clearTimeout = (): void => {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId)\n this.#timeoutId = undefined\n }\n }\n\n /**\n * Cancels any pending execution\n */\n cancel = (): void => {\n this.#clearTimeout()\n this.#setState({\n canLeadingExecute: true,\n isPending: false,\n })\n }\n\n /**\n * Resets the debouncer state to its default values\n */\n reset = (): void => {\n this.#setState(getDefaultDebouncerState<TFn>())\n }\n}\n\n/**\n * Creates a 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 the the simple function wrapper implementation pulled from the Debouncer class. If you need\n * more control over the debouncing behavior, use the Debouncer class directly.\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 * State Management:\n * - Uses TanStack Store for reactive state management\n * - Use `initialState` to provide initial state values when creating the debouncer\n * - Use `onExecute` callback to react to function execution and implement custom logic\n * - The state includes canLeadingExecute, execution count, and isPending status\n * - State can be accessed via the underlying Debouncer instance's `store.state` property\n * - When using framework adapters (React/Solid), state is accessed from the hook's state property\n *\n * @example\n * ```ts\n * const debounced = debounce(() => {\n * saveChanges();\n * }, { wait: 1000 });\n *\n * // Called repeatedly but executes at most once per second\n * inputElement.addEventListener('input', debounced);\n * ```\n */\nexport function debounce<TFn extends AnyFunction>(\n fn: TFn,\n initialOptions: DebouncerOptions<TFn>,\n): (...args: Parameters<TFn>) => void {\n const debouncer = new Debouncer(fn, initialOptions)\n return debouncer.maybeExecute\n}\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
+ export * from './async-batcher.js';
1
2
  export * from './async-debouncer.js';
2
3
  export * from './async-queuer.js';
3
4
  export * from './async-rate-limiter.js';
4
5
  export * from './async-throttler.js';
5
6
  export * from './batcher.js';
6
- export * from './compare.js';
7
7
  export * from './debouncer.js';
8
8
  export * from './queuer.js';
9
9
  export * from './rate-limiter.js';
package/dist/esm/index.js CHANGED
@@ -1,15 +1,16 @@
1
+ import { AsyncBatcher, asyncBatch } from "./async-batcher.js";
1
2
  import { AsyncDebouncer, asyncDebounce } from "./async-debouncer.js";
2
3
  import { AsyncQueuer, asyncQueue } from "./async-queuer.js";
3
4
  import { AsyncRateLimiter, asyncRateLimit } from "./async-rate-limiter.js";
4
5
  import { AsyncThrottler, asyncThrottle } from "./async-throttler.js";
5
6
  import { Batcher, batch } from "./batcher.js";
6
- import { isPlainArray, isPlainObject, replaceEqualDeep, shallowEqualObjects } from "./compare.js";
7
7
  import { Debouncer, debounce } from "./debouncer.js";
8
8
  import { Queuer, queue } from "./queuer.js";
9
9
  import { RateLimiter, rateLimit } from "./rate-limiter.js";
10
10
  import { Throttler, throttle } from "./throttler.js";
11
- import { bindInstanceMethods, isFunction, parseFunctionOrValue } from "./utils.js";
11
+ import { isFunction, parseFunctionOrValue } from "./utils.js";
12
12
  export {
13
+ AsyncBatcher,
13
14
  AsyncDebouncer,
14
15
  AsyncQueuer,
15
16
  AsyncRateLimiter,
@@ -19,21 +20,17 @@ export {
19
20
  Queuer,
20
21
  RateLimiter,
21
22
  Throttler,
23
+ asyncBatch,
22
24
  asyncDebounce,
23
25
  asyncQueue,
24
26
  asyncRateLimit,
25
27
  asyncThrottle,
26
28
  batch,
27
- bindInstanceMethods,
28
29
  debounce,
29
30
  isFunction,
30
- isPlainArray,
31
- isPlainObject,
32
31
  parseFunctionOrValue,
33
32
  queue,
34
33
  rateLimit,
35
- replaceEqualDeep,
36
- shallowEqualObjects,
37
34
  throttle
38
35
  };
39
36
  //# sourceMappingURL=index.js.map
@@ -1,3 +1,54 @@
1
+ import { Store } from '@tanstack/store';
2
+ export interface QueuerState<TValue> {
3
+ /**
4
+ * Number of items that have been processed by the queuer
5
+ */
6
+ executionCount: number;
7
+ /**
8
+ * Number of items that have been removed from the queue due to expiration
9
+ */
10
+ expirationCount: number;
11
+ /**
12
+ * Whether the queuer has no items to process (items array is empty)
13
+ */
14
+ isEmpty: boolean;
15
+ /**
16
+ * Whether the queuer has reached its maximum capacity
17
+ */
18
+ isFull: boolean;
19
+ /**
20
+ * Whether the queuer is not currently processing any items
21
+ */
22
+ isIdle: boolean;
23
+ /**
24
+ * Whether the queuer is active and will process items automatically
25
+ */
26
+ isRunning: boolean;
27
+ /**
28
+ * Timestamps when items were added to the queue for expiration tracking
29
+ */
30
+ itemTimestamps: Array<number>;
31
+ /**
32
+ * Array of items currently waiting to be processed
33
+ */
34
+ items: Array<TValue>;
35
+ /**
36
+ * Whether the queuer has a pending timeout for processing the next item
37
+ */
38
+ pendingTick: boolean;
39
+ /**
40
+ * Number of items that have been rejected from being added to the queue
41
+ */
42
+ rejectionCount: number;
43
+ /**
44
+ * Number of items currently in the queue
45
+ */
46
+ size: number;
47
+ /**
48
+ * Current processing status - 'idle' when not processing, 'running' when active, 'stopped' when paused
49
+ */
50
+ status: 'idle' | 'running' | 'stopped';
51
+ }
1
52
  /**
2
53
  * Options for configuring a Queuer instance.
3
54
  *
@@ -33,6 +84,10 @@ export interface QueuerOptions<TValue> {
33
84
  * Initial items to populate the queuer with
34
85
  */
35
86
  initialItems?: Array<TValue>;
87
+ /**
88
+ * Initial state for the queuer
89
+ */
90
+ initialState?: Partial<QueuerState<TValue>>;
36
91
  /**
37
92
  * Maximum number of items allowed in the queuer
38
93
  */
@@ -45,10 +100,6 @@ export interface QueuerOptions<TValue> {
45
100
  * Callback fired whenever an item is removed from the queuer
46
101
  */
47
102
  onExecute?: (item: TValue, queuer: Queuer<TValue>) => void;
48
- /**
49
- * Callback fired whenever the queuer's running state changes
50
- */
51
- onIsRunningChange?: (queuer: Queuer<TValue>) => void;
52
103
  /**
53
104
  * Callback fired whenever an item is added or removed from the queuer
54
105
  */
@@ -86,7 +137,7 @@ export type QueuePosition = 'front' | 'back';
86
137
  * - Callbacks for queue state changes, execution, rejection, and expiration
87
138
  *
88
139
  * Running behavior:
89
- * - `start()`: Begins automatically processing items in the queue (defaults to running)
140
+ * - `start()`: Begins automatically processing items in the queue (defaults to isRunning)
90
141
  * - `stop()`: Pauses processing but maintains queue state
91
142
  * - `wait`: Configurable delay between processing items
92
143
  * - `onItemsChange`/`onExecute`: Callbacks for monitoring queue state
@@ -115,6 +166,17 @@ export type QueuePosition = 'front' | 'back';
115
166
  * - `getIsExpired`: Function to override default expiration
116
167
  * - `onExpire`: Callback for expired items
117
168
  *
169
+ * State Management:
170
+ * - Uses TanStack Store for reactive state management
171
+ * - Use `initialState` to provide initial state values when creating the queuer
172
+ * - Use `onExecute` callback to react to item execution and implement custom logic
173
+ * - Use `onItemsChange` callback to react to items being added or removed from the queue
174
+ * - Use `onExpire` callback to react to items expiring and implement custom logic
175
+ * - Use `onReject` callback to react to items being rejected when the queue is full
176
+ * - The state includes execution count, expiration count, rejection count, and isRunning status
177
+ * - State can be accessed via `queuer.store.state` when using the class directly
178
+ * - When using framework adapters (React/Solid), state is accessed from `queuer.state`
179
+ *
118
180
  * Example usage:
119
181
  * ```ts
120
182
  * // Auto-processing queue with wait time
@@ -137,56 +199,15 @@ export type QueuePosition = 'front' | 'back';
137
199
  * ```
138
200
  */
139
201
  export declare class Queuer<TValue> {
202
+ #private;
140
203
  private fn;
141
- private _options;
142
- private _items;
143
- private _itemTimestamps;
144
- private _executionCount;
145
- private _rejectionCount;
146
- private _expirationCount;
147
- private _onItemsChanges;
148
- private _running;
149
- private _pendingTick;
204
+ readonly store: Store<Readonly<QueuerState<TValue>>>;
205
+ options: QueuerOptions<TValue>;
150
206
  constructor(fn: (item: TValue) => void, initialOptions?: QueuerOptions<TValue>);
151
207
  /**
152
208
  * Updates the queuer options. New options are merged with existing options.
153
209
  */
154
- setOptions(newOptions: Partial<QueuerOptions<TValue>>): void;
155
- /**
156
- * Returns the current queuer options, including defaults and any overrides.
157
- */
158
- getOptions(): Required<QueuerOptions<TValue>>;
159
- /**
160
- * Returns the current wait time (in milliseconds) between processing items.
161
- * If a function is provided, it is called with the queuer instance.
162
- */
163
- getWait(): number;
164
- /**
165
- * Processes items in the queue up to the wait interval. Internal use only.
166
- */
167
- private tick;
168
- /**
169
- * Checks for expired items in the queue and removes them. Calls onExpire for each expired item.
170
- * Internal use only.
171
- */
172
- private checkExpiredItems;
173
- /**
174
- * Stops processing items in the queue. Does not clear the queue.
175
- */
176
- stop(): void;
177
- /**
178
- * Starts processing items in the queue. If already running, does nothing.
179
- */
180
- start(): void;
181
- /**
182
- * Removes all pending items from the queue. Does not affect items being processed.
183
- */
184
- clear(): void;
185
- /**
186
- * Resets the queuer to its initial state. Optionally repopulates with initial items.
187
- * Does not affect callbacks or options.
188
- */
189
- reset(withInitialItems?: boolean): void;
210
+ setOptions: (newOptions: Partial<QueuerOptions<TValue>>) => void;
190
211
  /**
191
212
  * Adds an item to the queue. If the queue is full, the item is rejected and onReject is called.
192
213
  * Items can be inserted based on priority or at the front/back depending on configuration.
@@ -199,7 +220,7 @@ export declare class Queuer<TValue> {
199
220
  * queuer.addItem('task2', 'front');
200
221
  * ```
201
222
  */
202
- addItem(item: TValue, position?: QueuePosition, runOnUpdate?: boolean): boolean;
223
+ addItem: (item: TValue, position?: QueuePosition, runOnItemsChange?: boolean) => boolean;
203
224
  /**
204
225
  * Removes and returns the next item from the queue without executing the function.
205
226
  * Use for manual queue management. Normally, use execute() to process items.
@@ -212,7 +233,7 @@ export declare class Queuer<TValue> {
212
233
  * queuer.getNextItem('back');
213
234
  * ```
214
235
  */
215
- getNextItem(position?: QueuePosition): TValue | undefined;
236
+ getNextItem: (position?: QueuePosition) => TValue | undefined;
216
237
  /**
217
238
  * Removes and returns the next item from the queue and processes it using the provided function.
218
239
  *
@@ -223,7 +244,12 @@ export declare class Queuer<TValue> {
223
244
  * queuer.execute('back');
224
245
  * ```
225
246
  */
226
- execute(position?: QueuePosition): TValue | undefined;
247
+ execute: (position?: QueuePosition) => TValue | undefined;
248
+ /**
249
+ * Processes a specified number of items to execute immediately with no wait time
250
+ * If no numberOfItems is provided, all items will be processed
251
+ */
252
+ flush: (numberOfItems?: number, position?: QueuePosition) => void;
227
253
  /**
228
254
  * Returns the next item in the queue without removing it.
229
255
  *
@@ -233,52 +259,47 @@ export declare class Queuer<TValue> {
233
259
  * queuer.peekNextItem('back'); // back
234
260
  * ```
235
261
  */
236
- peekNextItem(position?: QueuePosition): TValue | undefined;
237
- /**
238
- * Returns true if the queue is empty (no pending items).
239
- */
240
- getIsEmpty(): boolean;
241
- /**
242
- * Returns true if the queue is full (reached maxSize).
243
- */
244
- getIsFull(): boolean;
245
- /**
246
- * Returns the number of pending items in the queue.
247
- */
248
- getSize(): number;
262
+ peekNextItem: (position?: QueuePosition) => TValue | undefined;
249
263
  /**
250
264
  * Returns a copy of all items in the queue.
251
265
  */
252
- peekAllItems(): Array<TValue>;
253
- /**
254
- * Returns the number of items that have been processed and removed from the queue.
255
- */
256
- getExecutionCount(): number;
266
+ peekAllItems: () => Array<TValue>;
257
267
  /**
258
- * Returns the number of items that have been rejected from being added to the queue.
268
+ * Starts processing items in the queue. If already isRunning, does nothing.
259
269
  */
260
- getRejectionCount(): number;
270
+ start: () => void;
261
271
  /**
262
- * Returns the number of items that have expired and been removed from the queue.
272
+ * Stops processing items in the queue. Does not clear the queue.
263
273
  */
264
- getExpirationCount(): number;
274
+ stop: () => void;
265
275
  /**
266
- * Returns true if the queuer is currently running (processing items).
276
+ * Removes all pending items from the queue. Does not affect items being processed.
267
277
  */
268
- getIsRunning(): boolean;
278
+ clear: () => void;
269
279
  /**
270
- * Returns true if the queuer is running but has no items to process.
280
+ * Resets the queuer state to its default values
271
281
  */
272
- getIsIdle(): boolean;
282
+ reset: () => void;
273
283
  }
274
284
  /**
275
285
  * Creates a queue that processes items immediately upon addition.
276
286
  * Items are processed sequentially in FIFO order by default.
277
287
  *
278
288
  * This is a simplified wrapper around the Queuer class that only exposes the
279
- * `addItem` method. The queue is always running and will process items as they are added.
289
+ * `addItem` method. The queue is always isRunning and will process items as they are added.
280
290
  * For more control over queue processing, use the Queuer class directly.
281
291
  *
292
+ * State Management:
293
+ * - Uses TanStack Store for reactive state management
294
+ * - Use `initialState` to provide initial state values when creating the queuer
295
+ * - Use `onExecute` callback to react to item execution and implement custom logic
296
+ * - Use `onItemsChange` callback to react to items being added or removed from the queue
297
+ * - Use `onExpire` callback to react to items expiring and implement custom logic
298
+ * - Use `onReject` callback to react to items being rejected when the queue is full
299
+ * - The state includes execution count, expiration count, rejection count, and isRunning status
300
+ * - State can be accessed via the underlying Queuer instance's `store.state` property
301
+ * - When using framework adapters (React/Solid), state is accessed from the hook's state property
302
+ *
282
303
  * Example usage:
283
304
  * ```ts
284
305
  * // Basic sequential processing
@@ -297,4 +318,4 @@ export declare class Queuer<TValue> {
297
318
  * processPriority(3); // Processed before 1
298
319
  * ```
299
320
  */
300
- export declare function queue<TValue>(fn: (item: TValue) => void, options: QueuerOptions<TValue>): (item: TValue, position?: QueuePosition, runOnUpdate?: boolean) => boolean;
321
+ export declare function queue<TValue>(fn: (item: TValue) => void, initialOptions: QueuerOptions<TValue>): (item: TValue, position?: QueuePosition, runOnItemsChange?: boolean) => boolean;