Repository navigation
refactor: large initial factor for big fixes and performance #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Changesets | ||
|
|
||
| Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works | ||
| with multi-package repos, or single-package repos to help you version and publish your code. You can | ||
| find the full documentation for it [in our repository](https://github.com/changesets/changesets) | ||
|
|
||
| We have a quick list of common questions to get you started engaging with this project in | ||
| [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json", | ||
| "changelog": "@changesets/cli/changelog", | ||
| "commit": false, | ||
| "fixed": [], | ||
| "linked": [], | ||
| "access": "public", | ||
| "baseBranch": "main", | ||
| "updateInternalDependencies": "patch", | ||
| "ignore": [] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| --- | ||
| "@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<Options> 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<IterArgs> | false — Partial<IterArgs> 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. |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| github: [jakubroztocil, davidgoli] | ||
| github: [shavonn, jakubroztocil, davidgoli] |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: write | ||
| issues: write | ||
| pull-requests: write | ||
| packages: write | ||
| id-token: write | ||
|
|
||
| concurrency: ${{ github.workflow }}-${{ github.ref }} | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: oven-sh/setup-bun@v2 | ||
| - uses: actions/setup-node@v4 | ||
|
|
||
| - name: Install Dependencies | ||
| shell: bash | ||
| run: bun install | ||
|
|
||
| - name: Capture New Release Version | ||
| run: | | ||
| bun changeset status --output=release.json | ||
| echo "NEW_VERSION=$(jq -r '.releases | map(.name+"@"+.newVersion) | join(",")' release.json)" >> "$GITHUB_ENV" | ||
| rm release.json | ||
|
|
||
| - name: Create Release Pull Request or Publish to GitHub Packages | ||
| id: changesets | ||
| uses: changesets/action@v1 | ||
| with: | ||
| publish: bun publish-package | ||
| title: "Release version ${{env.NEW_VERSION}}" | ||
| commit: "Update version ${{env.NEW_VERSION}}" | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,51 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - main | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - main | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| test: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strategy: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| matrix: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| node-version: [20.x, 22.x, 24.x] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: oven-sh/setup-bun@v2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Setup Node | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/setup-node@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| node-version: ${{ matrix.node-version }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Install Dependencies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shell: bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: bun install | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: bun run build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Unit Tests - Canada | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=en_CA TZ=America/Vancouver bun test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Unit Tests - US | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=en_US TZ=America/Los_Angeles bun test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Unit Tests - Kenya | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=sw_KE TZ=Africa/Nairobi bun test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Unit Tests - Christmas | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=en_KI TZ=Pacific/Kiritimati bun test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Run Unit Tests - Japan | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=jp_JP TZ=Asia/Tokyo bun test | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+51
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: LANG=en_CA TZ=America/Vancouver bun test | |
| - name: Run Unit Tests - US | |
| run: LANG=en_US TZ=America/Los_Angeles bun test | |
| - name: Run Unit Tests - Kenya | |
| run: LANG=sw_KE TZ=Africa/Nairobi bun test | |
| - name: Run Unit Tests - Christmas | |
| run: LANG=en_KI TZ=Pacific/Kiritimati bun test | |
| - name: Run Unit Tests - Japan | |
| run: LANG=jp_JP TZ=Asia/Tokyo bun test | |
| run: LANG=en_CA TZ=America/Vancouver bun run test | |
| - name: Run Unit Tests - US | |
| run: LANG=en_US TZ=America/Los_Angeles bun run test | |
| - name: Run Unit Tests - Kenya | |
| run: LANG=sw_KE TZ=Africa/Nairobi bun run test | |
| - name: Run Unit Tests - Christmas | |
| run: LANG=en_KI TZ=Pacific/Kiritimati bun run test | |
| - name: Run Unit Tests - Japan | |
| run: LANG=jp_JP TZ=Asia/Tokyo bun run test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The release workflow uses
bun changeset ...andpublish: bun publish-package. Bun won't execute package binaries/scripts with that syntax reliably. Usebunx changeset ...(orbun run change -- status ...) and setpublishtobun run publish-packageso the Changesets action can actually run the commands.