Conversation
…n and equality functions Enhance element search methods to support custom comparison functions. Enhance constructors to accept options objects for both Heap and HeapAsync, allowing users to specify custom comparison and equality functions. Update relevant methods to utilize these configurations, ensuring backward compatibility with existing comparator function usage. Add tests to validate new functionality. Should fix: #669
…add _worstIndex method Enhance the add method to reject elements worse than the worst kept when the heap reaches its limit, and replace the worst element if a better one is added. New private method, _worstIndex, to find the index of the worst element for eviction. Update _applyLimit to remove the worst elements while maintaining heap properties. Add tests to validate the new functionality for both Heap and HeapAsync. Should fix #656
…nd new features This release introduces significant changes, including: - `setLimit` and `_applyLimit` methods in the HeapAsync class are now async. - Constructors for Heap and HeapAsync now accept options objects for custom comparison and equality functions. - New `isEqual` property added to both classes. - Enhanced eviction logic to maintain the best N elements in the heap.
📝 WalkthroughWalkthroughVersion 3.0.0 introduces breaking changes: new HeapOptions and HeapAsyncOptions interfaces for constructor configuration, custom equality functions via isEqual property, limit-based eviction logic with Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (21)
🧰 Additional context used🧬 Code graph analysis (2)tests/heap-async/heap-async-public-methods.test.ts (1)
src/Heap.ts (1)
🔇 Additional comments (30)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
README.md (3)
274-286: Update constructor documentation to reflect new options-based API.The constructor documentation still shows the old API with positional comparator argument, but version 3.0.0 introduces a breaking change where constructors accept
HeapOptionsandHeapAsyncOptionsobjects instead.This creates a significant gap: the changelog describes the breaking change (lines 46-55) but users cannot find examples of how to use the new API in the README.
📝 Proposed update to constructor documentation
Replace lines 274-286 with:
- ## Constructor - - ### Heap - - ```js - new Heap([comparator]); - ``` - - ### HeapAsync - - ```js - new HeapAsync([asyncComparator]); - ```With:
## Constructor ### Heap ```js new Heap([options]);Where
optionsis aHeapOptions<T>object with optional properties:
compare?: Comparator<T>- Custom comparator function (default:Heap.minComparator)isEqual?: IsEqual<T>- Custom equality function (default: strict equality)Legacy constructor (still supported for backward compatibility):
new Heap([comparator]); // Positional comparator argumentHeapAsync
new HeapAsync([options]);Where
optionsis aHeapAsyncOptions<T>object with optional properties:
compare?: AsyncComparator<T>- Async comparator functionisEqual?: AsyncIsEqual<T>- Async equality functionLegacy constructor:
new HeapAsync([asyncComparator]); // Positional comparator argument</details> --- `162-181`: **Add example demonstrating new options-based constructor with custom isEqual.** The "Custom Heap" example uses the old positional comparator API. Add an example showing how to use the new `HeapOptions` interface with both `compare` and `isEqual` options, which is particularly important for users who need custom equality functions (addressing issue #669). <details> <summary>📝 Proposed example for custom equality</summary> Add after the existing "Custom Heap" example: ```js #### Custom Heap with Custom Equality A heap where elements are compared by priority and equality is determined by a custom function. ```js import { Heap } from 'heap-js'; const customPriorityComparator = (a, b) => a.priority - b.priority; const customIsEqual = (a, b) => a.id === b.id; // Compare by id instead of reference // Custom Heap with both compare and isEqual options const customHeap = new Heap({ compare: customPriorityComparator, isEqual: customIsEqual }); // Initialize the heap with an array customHeap.init([ { id: 1, priority: 5 }, { id: 2, priority: 18 }, { id: 3, priority: 1 } ]); // Now contains and remove use custom equality console.log(customHeap.contains({ id: 1, priority: 99 })); //> true (matches by id) customHeap.remove({ id: 2, priority: 99 }); // Removes element with id: 2 console.log(customHeap.peek()); //> { id: 3, priority: 1 }</details> --- `183-202`: **Update HeapAsync example to show new options-based constructor.** The HeapAsync example uses the old positional comparator API. Update it to demonstrate the new `HeapAsyncOptions` interface and highlight the important change that `setLimit` is now async. <details> <summary>📝 Proposed updated HeapAsync example</summary> Replace the example (lines 183-202) with: ```js #### Min HeapAsync A heap where the most important element is always at the top, the elements are objects with a `priority` property, and the comparator function is asynchronous. Implements the same interface as `Heap`, but almost all methods return a `Promise`. ```js import { HeapAsync } from 'heap-js'; const customPriorityComparator = (a, b) => Promise.resolve(a.priority - b.priority); // Custom HeapAsync using options object const customHeap = new HeapAsync({ compare: customPriorityComparator }); // Initialize the heap with an array await customHeap.init([{ priority: 5 }, { priority: 18 }, { priority: 1 }]); // Push a new value await customHeap.push({ priority: 2 }); console.log(await customHeap.peek()); //> { priority: 1 } console.log(await customHeap.pop()); //> { priority: 1 } console.log(await customHeap.peek()); //> { priority: 2 } // Use setLimit to apply limit asynchronously (new in 3.0.0) await customHeap.setLimit(2); // Keep only top 2 elementsNote the key breaking change: use
setLimit()method instead of setting thelimitproperty directly, assetLimitis async.</details> </blockquote></details> </blockquote></details>📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
dist/heap-js.es5.jsis excluded by!**/dist/**dist/heap-js.umd.jsis excluded by!**/dist/**dist/types/Heap.d.tsis excluded by!**/dist/**dist/types/HeapAsync.d.tsis excluded by!**/dist/**📒 Files selected for processing (21)
README.mddocs/assets/navigation.jsdocs/assets/search.jsdocs/classes/Heap.htmldocs/classes/HeapAsync.htmldocs/functions/toInt.htmldocs/index.htmldocs/interfaces/HeapAsyncOptions.htmldocs/interfaces/HeapOptions.htmldocs/modules.htmldocs/types/AsyncComparator.htmldocs/types/AsyncIsEqual.htmldocs/types/Comparator.htmldocs/types/IsEqual.htmlpackage.jsonsrc/Heap.tssrc/HeapAsync.tstests/heap-async/heap-async-private-methods.test.tstests/heap-async/heap-async-public-methods.test.tstests/heap/heap-private-methods.test.tstests/heap/heap-public-methods.test.ts🧰 Additional context used
🧬 Code graph analysis (2)
tests/heap-async/heap-async-public-methods.test.ts (1)
src/HeapAsync.ts (1)
HeapAsync(24-963)src/Heap.ts (1)
dist/types/Heap.d.ts (3)
HeapOptions(7-19)Comparator(2-2)IsEqual(3-3)🔇 Additional comments (30)
package.json (1)
3-3: Version bump correctly reflects major release.The upgrade from 2.7.1 to 3.0.0 is appropriate for breaking changes introduced in this PR.
docs/modules.html (1)
1-1: Auto-generated documentation reflects new API.The TypeDoc output correctly includes references to the new
HeapOptionsandHeapAsyncOptionsinterfaces, confirming the API changes are properly documented in generated docs.README.md (1)
46-55: Changelog for 3.0.0 is clear and comprehensive.The changelog accurately documents the breaking changes and new features. It correctly highlights the async behavior changes and references the relevant issues (#669, #656).
docs/types/AsyncComparator.html (1)
1-1: Documentation regenerated appropriately.The AsyncComparator type documentation has been properly regenerated for the 3.0.0 release with updated source references.
docs/types/AsyncIsEqual.html (1)
1-1: Documentation regenerated appropriately.The AsyncIsEqual type documentation has been properly updated with the new source reference for the 3.0.0 release.
tests/heap/heap-private-methods.test.ts (1)
150-154: Excellent boundary condition test.The test for
_worstIndex()on an empty heap appropriately validates the sentinel return value, ensuring the eviction logic handles edge cases correctly. This complements the new limit-based eviction features in 3.0.0.docs/types/IsEqual.html (1)
1-1: Documentation regenerated appropriately.The IsEqual type documentation has been properly regenerated with updated source references for the 3.0.0 release.
docs/functions/toInt.html (1)
1-1: Documentation regenerated appropriately.The toInt function documentation has been properly updated with the new source line reference (L23), reflecting the addition of new interfaces and types in Heap.ts.
tests/heap-async/heap-async-private-methods.test.ts (1)
168-172: Non-empty heap scenarios for_worstIndex()are already tested through public limit API integration tests.The empty heap edge case is correctly validated by this test. Non-empty scenarios are covered in
tests/heap-async/heap-async-public-methods.test.ts(lines 220+), where tests like "limit keeps top N best values" and "maintain heap property after limit enforcement" exercise_worstIndex()indirectly by callingsetLimit()and triggering the limit enforcement logic. This pattern matches the synchronous version and provides adequate coverage.docs/index.html (1)
14-21: LGTM! Changelog documentation is comprehensive.The 3.0.0 changelog accurately documents the breaking changes (
setLimit/_applyLimitnow async), new constructor options,isEqualproperty, O(n) vs O(log n) search complexity trade-off, and limit eviction behavior. Issue references are properly linked.docs/interfaces/HeapAsyncOptions.html (1)
1-12: LGTM! Auto-generated documentation is accurate.The TypeDoc-generated documentation correctly reflects the
HeapAsyncOptions<T>interface with its optionalcompareandisEqualproperties and their default values.tests/heap/heap-public-methods.test.ts (3)
424-479: LGTM! Comprehensive limit eviction tests.Good coverage of the limit behavior for both min-heap and max-heap scenarios, including:
- Keeping top N values during push
- Limit enforcement after init
- Rejecting worse elements at capacity
- Accepting better elements at capacity
- Heap property maintenance after limit enforcement
702-783: LGTM! Custom IsEqual function tests are well-structured.The tests properly validate custom equality callbacks for
contains,indexOf,indexOfEvery, andremovemethods, covering various heap positions and edge cases.
785-897: LGTM! Options constructor tests provide thorough coverage.Good backward compatibility testing with the comparator function, plus comprehensive validation of the new options object pattern including
compare,isEqual, defaults, and clone behavior.tests/heap-async/heap-async-public-methods.test.ts (3)
221-231: LGTM! Correctly migrated to async setLimit.The test properly uses
await heap.setLimit(5)for async limit application, aligning with the breaking change documented in the PR.
234-289: LGTM! Async limit eviction tests mirror sync Heap tests.Good async coverage of limit behavior including min/max heap scenarios, rejection/acceptance at capacity, and heap property maintenance.
518-609: LGTM! HeapAsync options constructor tests are comprehensive.Good coverage of async comparator backward compatibility, options object patterns, defaults, and configured
isEqualbehavior forcontains,remove, andclone.src/Heap.ts (6)
6-21: LGTM! Clean HeapOptions interface definition.The interface is well-documented with JSDoc defaults and properly exports both
compareandisEqualoptional properties.
61-72: LGTM! Constructor handles all input variants correctly.Good backward-compatible design that accepts either a comparator function or an options object, with proper defaults.
357-371: LGTM! Add eviction logic is correct.The eviction logic properly finds the worst element, compares against the new element, and only replaces if the new element is better. The re-heaping with
_sortNodeUpfollowed by_sortNodeDowncorrectly maintains heap invariants after replacement.
486-514: LGTM! indexOf correctly handles custom equality callbacks.The dual-path approach—O(n) full scan when a custom callback is provided vs. heap-optimized search with default equality—is well-documented and correctly implemented.
1053-1068: LGTM! _worstIndex correctly finds the worst element among leaves.The implementation correctly searches only the leaf nodes (second half of the array) since the worst element in a heap is always among the leaves.
834-850: LGTM! _applyLimit correctly evicts worst elements.The eviction loop properly handles both cases: when the worst element is at the end (simple pop) and when it's elsewhere (swap with last, pop, and re-heap).
src/HeapAsync.ts (7)
4-18: LGTM! HeapAsyncOptions interface mirrors HeapOptions correctly.The interface properly uses
AsyncComparatorandAsyncIsEqualtypes with appropriate defaults documented.
47-58: LGTM! Constructor matches Heap pattern with async types.Correctly handles async comparator function, options object, or undefined with proper defaults.
352-366: LGTM! Async add eviction logic is correct.Properly awaits
_worstIndex()andcompare()calls while maintaining the same eviction logic as the sync Heap.
519-533: LGTM! Breaking change for limit handling is well-implemented.The setter now includes a clear comment directing users to
setLimit()for async application, and the newsetLimit()method properly awaits_applyLimit(). This aligns with the documented breaking changes.
455-463: LGTM! contains() correctly uses optional callback.The fallback to
this.isEqualwhen no callback is provided is correct.
726-742: LGTM! Async _applyLimit correctly evicts worst elements.The async version properly awaits all heap operations while maintaining the same eviction logic as the sync version.
952-962: LGTM! Async _worstIndex implementation is correct.Properly awaits async compare calls while searching only leaf nodes for the worst element.
The main breaking changes are that
setLimitand_applyLimitmethods of the HeapAsync class are now async, and that setting thelimitproperty will NOT apply the limit asynchronously; use thesetLimitmethod instead.HeapOptionsandHeapAsyncOptions, with thecompareandisEqualoptions.isEqualproperty to theHeapandHeapAsyncclasses to support custom equality functions to override the default equality function.setLimitmethod to support async limit application. Setting only thelimitproperty will not apply the limit asynchronously.Summary by CodeRabbit
Release Notes - Version 3.0.0
New Features
Breaking Changes
✏️ Tip: You can customize this high-level summary in your review settings.