From 226883230abdeccf92722e808521b7fd3b708b6e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 05:25:24 +0000 Subject: [PATCH 1/2] Update version @offload-project/rrule@2.8.1 --- .changeset/bumpy-llamas-allow.md | 98 --------------------------- CHANGELOG.md | 113 +++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 114 insertions(+), 99 deletions(-) delete mode 100644 .changeset/bumpy-llamas-allow.md diff --git a/.changeset/bumpy-llamas-allow.md b/.changeset/bumpy-llamas-allow.md deleted file mode 100644 index 7753be0c..00000000 --- a/.changeset/bumpy-llamas-allow.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -"@offload-project/rrule": patch ---- - -Refactored the core recurrence-rule implementation to share query/caching logic across RRule and RRuleSet, while also fixing a few correctness/performance issues in iteration and caching behavior. - -## Bug Fixes - -- Fixed removeFilteredDays accumulation bug - - Was overwriting filtered on each iteration instead of accumulating. Only the last day's filter status was returned, causing sub-daily frequencies to - potentially skip the wrong number of days when earlier days in the set were filtered out. - -- Fixed RRuleSet.clone() inverted noCache - - Changed new RRuleSet(!!this._cache) to new RRuleSet(!this._cache). The constructor param is noCache, so the old code was enabling cache on uncached - sets and vice versa. - -- Removed dead lno1wkst = 0 assignment - - The value was assigned inside an if block but never read afterward. Changed declaration from let to const. - -## Architecture - -- Extracted RRuleBase abstract class - - Moved shared query methods (all, between, before, after, count) and caching logic into RRuleBase. - - RRule extends RRuleBase — keeps options, _iter, toString, toText, NLP methods. - - RRuleSet extends RRuleBase — no longer extends RRule or calls super({}, noCache) with fake empty options. - - Exported RRuleBase from src/index.ts so consumers can use instanceof RRuleBase for any rule-like object. - - Updated test utilities to use RRuleBase for shared type checking. - -## Performance - -- rrules()/exrules() — eliminated serialize+reparse - - Was: this._rrule.map((e) => rrulestr(e.toString())) — serializes to RFC string then re-parses. - - Now: this._rrule.map((e) => e.clone()) — direct clone, removed the rrulestr import entirely. - -- _addRule/_addDate — eliminated O(n) array allocation - - Was: collection.map(String).includes(String(rrule)) — allocates a new array on every call. - - Now: collection.some((r) => String(r) === str) — short-circuits without allocating. - - Same pattern for _addDate: .some((d) => d.getTime() === time) instead of .map(Number).includes(Number(date)). - -- Added cache size bounds (src/cache.ts) - - Added MAX_CACHE_SIZE = 64 constant. - - before/after/between caches now evict the oldest entry (FIFO) when the limit is reached, preventing unbounded memory growth on long-lived instances. - -## Type Safety - -- Narrowed bynweekday to tuple type (src/types.ts) - - Changed bynweekday: number[][] | null to bynweekday: [number, number][] | null in ParsedOptions, enabling safe destructuring without ! assertions in - monthinfo.ts and parseoptions.ts. - -- Narrowed toText options to ParsedOptions (src/nlp/totext.ts) - - Changed private options: Partial to private options: ParsedOptions, removing ~40 ! assertions on this.options.freq, this.options.interval, - this.options.bymonthday, etc. - -- Added explicit return types to dateutil helpers (src/dateutil.ts) - - getWeekday(): number, getMonthDays(): number, monthRange(): [number, number]. - - Eliminated downstream ! assertions in datetime.ts and yearinfo.ts where these return values were used. - -- Added explicit return type to extractName (src/rrulestr.ts) - - Typed as { name: string; value: string } with default destructuring values, removing ! assertions on name and value. - -- Added default destructuring values in parseString (src/parsestring.ts) - - const [key = '', value = ''] = attr.split('=') and similar patterns, eliminating undefined-possibility assertions. - -- Fixed Cache.all type (src/cache.ts) - - Was: Date[] | Partial | false — Partial was never stored as all. - - Now: Date[] | false. - -- Clarified cache miss check (src/cache.ts) - - Changed if (!cached && this.all) to if (cached === false && this.all) — makes intent explicit for "not in cache" vs "cached as null". - -## Code Cleanup - -Converted C-style loops to for...of across 7 files -- monthinfo.ts, optionstostring.ts, parseoptions.ts, yearinfo.ts, iterset.ts, iter/index.ts, iter/poslist.ts — eliminates uncertain array-index ! - assertions. - -Removed dead code (src/iter/index.ts) -- Deleted redundant interval === 0 check (already checked at function entry). - -Removed redundant instanceof runtime guards (src/rruleset.ts) -- _addRule had if (!(rrule instanceof RRule)) and _addDate had if (!(date instanceof Date)) — parameters are already typed, so these were always true. - Removed guards and corresponding tests. - -Fixed test parse() null safety (test/lib/utils.ts) -- Added null guard for regex match result before destructuring. Simplified with Number() instead of intermediate variables. - -## Features - -- toText() now includes start date (src/nlp/totext.ts) - - When dtstart is explicitly set in rule options, toText() appends , starting [formatted date] to the output. - - Example: "every 2 months on the 15th, starting February 18, 2026". - - Rules without an explicit dtstart are unaffected. - -## Tooling - -- Updated README (README.md) - - Fixed stale badges, broken code examples, byeaster docs, wkst typo, LICENCE/LICENSE link, dev tooling (Biome), and documented new toText() starting - date behavior. diff --git a/CHANGELOG.md b/CHANGELOG.md index f1df226e..3c4e436c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,119 @@ ### Patch Changes +- 1090936: Refactored the core recurrence-rule implementation to share query/caching logic across RRule and RRuleSet, while also fixing a few correctness/performance issues in iteration and caching behavior. + + ## Bug Fixes + + - Fixed removeFilteredDays accumulation bug + + - Was overwriting filtered on each iteration instead of accumulating. Only the last day's filter status was returned, causing sub-daily frequencies to + potentially skip the wrong number of days when earlier days in the set were filtered out. + + - Fixed RRuleSet.clone() inverted noCache + + - Changed new RRuleSet(!!this.\_cache) to new RRuleSet(!this.\_cache). The constructor param is noCache, so the old code was enabling cache on uncached + sets and vice versa. + + - Removed dead lno1wkst = 0 assignment + - The value was assigned inside an if block but never read afterward. Changed declaration from let to const. + + ## Architecture + + - Extracted RRuleBase abstract class + - Moved shared query methods (all, between, before, after, count) and caching logic into RRuleBase. + - RRule extends RRuleBase — keeps options, \_iter, toString, toText, NLP methods. + - RRuleSet extends RRuleBase — no longer extends RRule or calls super({}, noCache) with fake empty options. + - Exported RRuleBase from src/index.ts so consumers can use instanceof RRuleBase for any rule-like object. + - Updated test utilities to use RRuleBase for shared type checking. + + ## Performance + + - rrules()/exrules() — eliminated serialize+reparse + + - Was: this.\_rrule.map((e) => rrulestr(e.toString())) — serializes to RFC string then re-parses. + - Now: this.\_rrule.map((e) => e.clone()) — direct clone, removed the rrulestr import entirely. + + - \_addRule/\_addDate — eliminated O(n) array allocation + + - Was: collection.map(String).includes(String(rrule)) — allocates a new array on every call. + - Now: collection.some((r) => String(r) === str) — short-circuits without allocating. + - Same pattern for \_addDate: .some((d) => d.getTime() === time) instead of .map(Number).includes(Number(date)). + + - Added cache size bounds (src/cache.ts) + - Added MAX_CACHE_SIZE = 64 constant. + - before/after/between caches now evict the oldest entry (FIFO) when the limit is reached, preventing unbounded memory growth on long-lived instances. + + ## Type Safety + + - Narrowed bynweekday to tuple type (src/types.ts) + + - Changed bynweekday: number[][] | null to bynweekday: [number, number][] | null in ParsedOptions, enabling safe destructuring without ! assertions in + monthinfo.ts and parseoptions.ts. + + - Narrowed toText options to ParsedOptions (src/nlp/totext.ts) + + - Changed private options: Partial to private options: ParsedOptions, removing ~40 ! assertions on this.options.freq, this.options.interval, + this.options.bymonthday, etc. + + - Added explicit return types to dateutil helpers (src/dateutil.ts) + + - getWeekday(): number, getMonthDays(): number, monthRange(): [number, number]. + - Eliminated downstream ! assertions in datetime.ts and yearinfo.ts where these return values were used. + + - Added explicit return type to extractName (src/rrulestr.ts) + + - Typed as { name: string; value: string } with default destructuring values, removing ! assertions on name and value. + + - Added default destructuring values in parseString (src/parsestring.ts) + + - const [key = '', value = ''] = attr.split('=') and similar patterns, eliminating undefined-possibility assertions. + + - Fixed Cache.all type (src/cache.ts) + + - Was: Date[] | Partial | false — Partial was never stored as all. + - Now: Date[] | false. + + - Clarified cache miss check (src/cache.ts) + - Changed if (!cached && this.all) to if (cached === false && this.all) — makes intent explicit for "not in cache" vs "cached as null". + + ## Code Cleanup + + Converted C-style loops to for...of across 7 files + + - monthinfo.ts, optionstostring.ts, parseoptions.ts, yearinfo.ts, iterset.ts, iter/index.ts, iter/poslist.ts — eliminates uncertain array-index ! + assertions. + + Removed dead code (src/iter/index.ts) + + - Deleted redundant interval === 0 check (already checked at function entry). + + Removed redundant instanceof runtime guards (src/rruleset.ts) + + - \_addRule had if (!(rrule instanceof RRule)) and \_addDate had if (!(date instanceof Date)) — parameters are already typed, so these were always true. + Removed guards and corresponding tests. + + Fixed test parse() null safety (test/lib/utils.ts) + + - Added null guard for regex match result before destructuring. Simplified with Number() instead of intermediate variables. + + ## Features + + - toText() now includes start date (src/nlp/totext.ts) + - When dtstart is explicitly set in rule options, toText() appends , starting [formatted date] to the output. + - Example: "every 2 months on the 15th, starting February 18, 2026". + - Rules without an explicit dtstart are unaffected. + + ## Tooling + + - Updated README (README.md) + - Fixed stale badges, broken code examples, byeaster docs, wkst typo, LICENCE/LICENSE link, dev tooling (Biome), and documented new toText() starting + date behavior. + +## 2.8.1 + +### Patch Changes + - 2a0bd87: Refactored the core recurrence-rule implementation to share query/caching logic across RRule and RRuleSet, while also fixing a few correctness/performance issues in iteration and caching behavior. ## Bug Fixes diff --git a/package.json b/package.json index 5b64b562..8460cb71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@offload-project/rrule", - "version": "2.8.0", + "version": "2.8.1", "description": "JavaScript library for working with recurrence rules for calendar dates.", "homepage": "http://offload-project.github.io/rrule/", "license": "BSD-3-Clause", From ecada48b644d82ed682b8726eede0b59dadd360d Mon Sep 17 00:00:00 2001 From: Shavonn Brown Date: Sat, 21 Feb 2026 00:33:43 -0500 Subject: [PATCH 2/2] chore: make previous version recognizable to changesets --- CHANGELOG.md | 115 +-------------------------------------------------- 1 file changed, 1 insertion(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c4e436c..3c1c68e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,119 +4,6 @@ ### Patch Changes -- 1090936: Refactored the core recurrence-rule implementation to share query/caching logic across RRule and RRuleSet, while also fixing a few correctness/performance issues in iteration and caching behavior. - - ## Bug Fixes - - - Fixed removeFilteredDays accumulation bug - - - Was overwriting filtered on each iteration instead of accumulating. Only the last day's filter status was returned, causing sub-daily frequencies to - potentially skip the wrong number of days when earlier days in the set were filtered out. - - - Fixed RRuleSet.clone() inverted noCache - - - Changed new RRuleSet(!!this.\_cache) to new RRuleSet(!this.\_cache). The constructor param is noCache, so the old code was enabling cache on uncached - sets and vice versa. - - - Removed dead lno1wkst = 0 assignment - - The value was assigned inside an if block but never read afterward. Changed declaration from let to const. - - ## Architecture - - - Extracted RRuleBase abstract class - - Moved shared query methods (all, between, before, after, count) and caching logic into RRuleBase. - - RRule extends RRuleBase — keeps options, \_iter, toString, toText, NLP methods. - - RRuleSet extends RRuleBase — no longer extends RRule or calls super({}, noCache) with fake empty options. - - Exported RRuleBase from src/index.ts so consumers can use instanceof RRuleBase for any rule-like object. - - Updated test utilities to use RRuleBase for shared type checking. - - ## Performance - - - rrules()/exrules() — eliminated serialize+reparse - - - Was: this.\_rrule.map((e) => rrulestr(e.toString())) — serializes to RFC string then re-parses. - - Now: this.\_rrule.map((e) => e.clone()) — direct clone, removed the rrulestr import entirely. - - - \_addRule/\_addDate — eliminated O(n) array allocation - - - Was: collection.map(String).includes(String(rrule)) — allocates a new array on every call. - - Now: collection.some((r) => String(r) === str) — short-circuits without allocating. - - Same pattern for \_addDate: .some((d) => d.getTime() === time) instead of .map(Number).includes(Number(date)). - - - Added cache size bounds (src/cache.ts) - - Added MAX_CACHE_SIZE = 64 constant. - - before/after/between caches now evict the oldest entry (FIFO) when the limit is reached, preventing unbounded memory growth on long-lived instances. - - ## Type Safety - - - Narrowed bynweekday to tuple type (src/types.ts) - - - Changed bynweekday: number[][] | null to bynweekday: [number, number][] | null in ParsedOptions, enabling safe destructuring without ! assertions in - monthinfo.ts and parseoptions.ts. - - - Narrowed toText options to ParsedOptions (src/nlp/totext.ts) - - - Changed private options: Partial to private options: ParsedOptions, removing ~40 ! assertions on this.options.freq, this.options.interval, - this.options.bymonthday, etc. - - - Added explicit return types to dateutil helpers (src/dateutil.ts) - - - getWeekday(): number, getMonthDays(): number, monthRange(): [number, number]. - - Eliminated downstream ! assertions in datetime.ts and yearinfo.ts where these return values were used. - - - Added explicit return type to extractName (src/rrulestr.ts) - - - Typed as { name: string; value: string } with default destructuring values, removing ! assertions on name and value. - - - Added default destructuring values in parseString (src/parsestring.ts) - - - const [key = '', value = ''] = attr.split('=') and similar patterns, eliminating undefined-possibility assertions. - - - Fixed Cache.all type (src/cache.ts) - - - Was: Date[] | Partial | false — Partial was never stored as all. - - Now: Date[] | false. - - - Clarified cache miss check (src/cache.ts) - - Changed if (!cached && this.all) to if (cached === false && this.all) — makes intent explicit for "not in cache" vs "cached as null". - - ## Code Cleanup - - Converted C-style loops to for...of across 7 files - - - monthinfo.ts, optionstostring.ts, parseoptions.ts, yearinfo.ts, iterset.ts, iter/index.ts, iter/poslist.ts — eliminates uncertain array-index ! - assertions. - - Removed dead code (src/iter/index.ts) - - - Deleted redundant interval === 0 check (already checked at function entry). - - Removed redundant instanceof runtime guards (src/rruleset.ts) - - - \_addRule had if (!(rrule instanceof RRule)) and \_addDate had if (!(date instanceof Date)) — parameters are already typed, so these were always true. - Removed guards and corresponding tests. - - Fixed test parse() null safety (test/lib/utils.ts) - - - Added null guard for regex match result before destructuring. Simplified with Number() instead of intermediate variables. - - ## Features - - - toText() now includes start date (src/nlp/totext.ts) - - When dtstart is explicitly set in rule options, toText() appends , starting [formatted date] to the output. - - Example: "every 2 months on the 15th, starting February 18, 2026". - - Rules without an explicit dtstart are unaffected. - - ## Tooling - - - Updated README (README.md) - - Fixed stale badges, broken code examples, byeaster docs, wkst typo, LICENCE/LICENSE link, dev tooling (Biome), and documented new toText() starting - date behavior. - -## 2.8.1 - -### Patch Changes - - 2a0bd87: Refactored the core recurrence-rule implementation to share query/caching logic across RRule and RRuleSet, while also fixing a few correctness/performance issues in iteration and caching behavior. ## Bug Fixes @@ -226,7 +113,7 @@ - Fixed stale badges, broken code examples, byeaster docs, wkst typo, LICENCE/LICENSE link, dev tooling (Biome), and documented new toText() starting date behavior. -- 2.8.0 (2023-11-10) +## 2.8.0 - Bugfixes: - Don't minify `rrule.js` (minified version is still at `rrule.min.js`) ([#606](https://github.com/jkbrzt/rrule/pull/606))