Skip to content

release: v0.12.3#28

Merged
sv2dev merged 5 commits intomainfrom
fix/guard-type-restriction
Apr 2, 2026
Merged

release: v0.12.3#28
sv2dev merged 5 commits intomainfrom
fix/guard-type-restriction

Conversation

@sv2dev
Copy link
Copy Markdown
Owner

@sv2dev sv2dev commented Apr 1, 2026

Summary

  • Releases v0.12.3 with two bug fixes improving type safety
  • Builds on v0.12.2's guard type restriction by addressing a related state-typing gap

Changes

  • router.go() now omits the state option from the type signature when the route handler declares no state type, preventing accidental state passing on untyped routes
  • Route guard property "?" is restricted to function type only (released in 0.12.2, included here as this branch tracks both fixes)

Changelog

[0.12.3] - 2026-04-02

Fixed

  • router.go() no longer exposes the state option for routes where no state type is declared, preventing accidental state passing on untyped routes

Summary by CodeRabbit

  • New Features

    • Enhanced package exports with explicit type declarations for improved IDE support and module resolution.
  • Bug Fixes

    • Fixed route guard "?" behavior to correctly reject invalid configurations.
    • Fixed router.go() state exposure rules to prevent invalid state parameters on stateless routes.
    • Corrected scroll restoration event handling for better session persistence.
  • Documentation

    • Added detailed CHANGELOG documenting all project versions and changes.
  • Chores

    • Updated TypeScript configuration for improved module compatibility.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Warning

Rate limit exceeded

@sv2dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 3 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 20 minutes and 3 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05c0dbd1-66c7-44ca-8326-8a4be3db4451

📥 Commits

Reviewing files that changed from the base of the PR and between 2f486ab and 24b4a63.

📒 Files selected for processing (15)
  • .gitignore
  • CHANGELOG.md
  • packages/esroute-lit/package.json
  • packages/esroute-lit/src/index.ts
  • packages/esroute-lit/src/render-routes-directive.spec.ts
  • packages/esroute/package.json
  • packages/esroute/src/index.ts
  • packages/esroute/src/nav-opts.spec.ts
  • packages/esroute/src/route-resolver.spec.ts
  • packages/esroute/src/route-resolver.ts
  • packages/esroute/src/router.spec.ts
  • packages/esroute/src/router.ts
  • packages/esroute/src/routes.ts
  • packages/esroute/src/scroll-restoration.ts
  • tsconfig.json

Walkthrough

A version bump (0.12.1 → 0.12.3) with CHANGELOG documentation, ESM package metadata additions (exports, types fields), explicit .js file extension updates across module imports/exports, Routes interface type refinements for guard behavior, Router.go typing adjustments, route-resolver null-safety improvements, and minor configuration changes.

Changes

Cohort / File(s) Summary
Documentation & Versioning
CHANGELOG.md
Added comprehensive changelog documenting releases 0.1.0–0.12.3 with semantic versioning, covering typed routing, route guards, state exposure, hash handling, and bundle metadata.
Package Metadata
packages/esroute/package.json, packages/esroute-lit/package.json
Version bumped to 0.12.3; added "type": "module", "types", and "exports" map with explicit entry points for ESM/type support.
ESM Module Resolution
packages/esroute/src/index.ts, packages/esroute-lit/src/index.ts, packages/esroute/src/route-resolver.ts, packages/esroute/src/router.ts, packages/esroute/src/routes.ts, packages/esroute/src/scroll-restoration.ts
Updated all module re-export and import specifiers to include explicit .js extensions for ESM compatibility.
Type System Enhancements
packages/esroute/src/routes.ts
Extended Routes interface: added optional "?" property typed as Resolve<T, S> for route guards; broadened string index signature to allow undefined.
Router Typing & Logic
packages/esroute/src/router.ts
Refined Router.go overload: omit state property when route handler does not require state; strengthened notFound handler parameter typing.
Route Resolution
packages/esroute/src/route-resolver.ts
Added early null-check inside do-while loop to prevent continued iteration when routes becomes null/undefined; adjusted internal control-flow typing.
Scroll Restoration
packages/esroute/src/scroll-restoration.ts
Moved "visibilitychange" listener from window to document for more reliable scroll-state persistence.
Test Type Assertions
packages/esroute/src/route-resolver.spec.ts, packages/esroute/src/router.spec.ts, packages/esroute-lit/src/render-routes-directive.spec.ts, packages/esroute/src/nav-opts.spec.ts
Updated import paths to .js extensions; added compile-time type safety tests for Routes guard shape and router.go state requirements.
Build Configuration
tsconfig.json
Updated module system and resolution from "esnext"/"bundler" to "node16".
Version Control
.gitignore
Added .claude to ignore patterns.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A hop toward module16!
Explicit .js paths now align,
Routes guards refined, null-checks divine,
State omitted when it's not required—
Bundle and types, both well-inspired! 📦✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'release: v0.12.3' directly and concisely identifies the main purpose of the PR—releasing version 0.12.3 with type safety fixes. It is clear, specific, and aligns with the primary objective documented in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/guard-type-restriction

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/esroute/src/scroll-restoration.ts (1)

36-36: Gate visibilitychange saves to hidden state only.

Right now save runs on both visible/hidden transitions. Restricting to document.visibilityState === "hidden" avoids unnecessary history.replaceState churn.

♻️ Suggested change
-  document.addEventListener("visibilitychange", save);
+  document.addEventListener("visibilitychange", () => {
+    if (document.visibilityState === "hidden") save();
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/esroute/src/scroll-restoration.ts` at line 36, The current listener
calls save on every visibilitychange; update the handler so it only runs when
document.visibilityState === "hidden" to avoid unnecessary history.replaceState
churn—replace the direct listener registration
(document.addEventListener("visibilitychange", save)) with a small wrapper that
checks document.visibilityState === "hidden" and then calls save (referencing
the existing save function) so only hidden-state transitions trigger the save.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/pr/SKILL.md:
- Around line 17-24: Update the monorepo source checks in SKILL.md so they cover
package-level source paths, not just root src/: replace or extend uses of the
`git diff main...HEAD -- src/` and the uncommitted-change detection/auto-commit
step that only reference `src/` to also include package directories (e.g.,
`packages/*/src/` or `packages/**/src/`) and any other repository source
locations; ensure the logic that checks for uncommitted changes (the auto-commit
via the commit skill) and the “what changed” diffs (`git diff ...`) use the
expanded glob patterns so package changes aren’t skipped.
- Around line 27-33: The release detection currently only checks whether
package.json files were modified (the git log invocation in SKILL.md) and may
misclassify PRs; update the git log invocation to search commits that
specifically touched the "version" field by using git log with a grep-by-diff
(-G) regex that matches the "version" JSON key so only commits that changed the
version line in packages/esroute/package.json or
packages/esroute-lit/package.json mark the PR as a release.

In `@CHANGELOG.md`:
- Line 99: The breaking-change line for createRouter is malformed due to an
extra trailing parenthesis; update the changelog entry so it reads:
"**Breaking**: `createRouter` is now a factory function instead of a class — use
`createRouter({ routes, ... })` instead of `new Router(...)`" (remove the stray
trailing `)` at the end), ensuring the text references createRouter and Router
exactly as shown.

In `@packages/esroute-lit/package.json`:
- Around line 5-13: The patch added "type": "module" causing a breaking change
for CommonJS consumers; fix by either releasing as a major version bump or by
restoring CJS compatibility: build a CommonJS bundle (e.g., dist/index.cjs) and
adjust the package.json exports to provide both "import" and "require"
conditions and ensure "main" or "exports" points to the CJS entry for require
users; update the "types" mapping if needed so dist/index.d.ts still matches
both builds and remove or document "type": "module" if you choose the dual-build
approach.

---

Nitpick comments:
In `@packages/esroute/src/scroll-restoration.ts`:
- Line 36: The current listener calls save on every visibilitychange; update the
handler so it only runs when document.visibilityState === "hidden" to avoid
unnecessary history.replaceState churn—replace the direct listener registration
(document.addEventListener("visibilitychange", save)) with a small wrapper that
checks document.visibilityState === "hidden" and then calls save (referencing
the existing save function) so only hidden-state transitions trigger the save.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08fa9f74-76f4-4fff-94bb-2cc27464a0e0

📥 Commits

Reviewing files that changed from the base of the PR and between 757e168 and 68a653a.

📒 Files selected for processing (15)
  • .claude/skills/pr/SKILL.md
  • CHANGELOG.md
  • packages/esroute-lit/package.json
  • packages/esroute-lit/src/index.ts
  • packages/esroute-lit/src/render-routes-directive.spec.ts
  • packages/esroute/package.json
  • packages/esroute/src/index.ts
  • packages/esroute/src/nav-opts.spec.ts
  • packages/esroute/src/route-resolver.spec.ts
  • packages/esroute/src/route-resolver.ts
  • packages/esroute/src/router.spec.ts
  • packages/esroute/src/router.ts
  • packages/esroute/src/routes.ts
  • packages/esroute/src/scroll-restoration.ts
  • tsconfig.json

Comment on lines +17 to +24
- `git log main..HEAD --oneline` — commits on this branch
- `git diff main...HEAD -- src/` — what changed in source
- `git diff main...HEAD -- CHANGELOG.md README.md packages/esroute/README.md packages/esroute-lit/README.md` — what docs already changed

If `git log main..HEAD` is empty, tell the user there's nothing to PR and stop.

If there are uncommitted changes in `src/` (shown by `git status`), commit them automatically using the commit skill before proceeding — they're part of the work being PR'd.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Monorepo source checks are too narrow (src/ only).

Line 18 and Line 23 only target root src/, but this repository’s source changes are primarily under package paths. That can skip intended PR/docs behavior.

🛠️ Suggested fix
-- `git diff main...HEAD -- src/` — what changed in source
+- `git diff main...HEAD -- packages/esroute/src/ packages/esroute-lit/src/` — what changed in source
...
-If there are uncommitted changes in `src/` (shown by `git status`), commit them automatically using the commit skill before proceeding — they're part of the work being PR'd.
+If there are uncommitted changes in `packages/esroute/src/` or `packages/esroute-lit/src/` (shown by `git status`), commit them automatically using the commit skill before proceeding — they're part of the work being PR'd.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `git log main..HEAD --oneline` — commits on this branch
- `git diff main...HEAD -- src/` — what changed in source
- `git diff main...HEAD -- CHANGELOG.md README.md packages/esroute/README.md packages/esroute-lit/README.md` — what docs already changed
If `git log main..HEAD` is empty, tell the user there's nothing to PR and stop.
If there are uncommitted changes in `src/` (shown by `git status`), commit them automatically using the commit skill before proceeding — they're part of the work being PR'd.
- `git log main..HEAD --oneline` — commits on this branch
- `git diff main...HEAD -- packages/esroute/src/ packages/esroute-lit/src/` — what changed in source
- `git diff main...HEAD -- CHANGELOG.md README.md packages/esroute/README.md packages/esroute-lit/README.md` — what docs already changed
If `git log main..HEAD` is empty, tell the user there's nothing to PR and stop.
If there are uncommitted changes in `packages/esroute/src/` or `packages/esroute-lit/src/` (shown by `git status`), commit them automatically using the commit skill before proceeding — they're part of the work being PR'd.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/pr/SKILL.md around lines 17 - 24, Update the monorepo source
checks in SKILL.md so they cover package-level source paths, not just root src/:
replace or extend uses of the `git diff main...HEAD -- src/` and the
uncommitted-change detection/auto-commit step that only reference `src/` to also
include package directories (e.g., `packages/*/src/` or `packages/**/src/`) and
any other repository source locations; ensure the logic that checks for
uncommitted changes (the auto-commit via the commit skill) and the “what
changed” diffs (`git diff ...`) use the expanded glob patterns so package
changes aren’t skipped.

Comment on lines +27 to +33
Check whether any commit on this branch touched a `package.json` version field:

```bash
git log main..HEAD --oneline --diff-filter=M -- packages/esroute/package.json packages/esroute-lit/package.json
```

If this returns output, this is a **release PR**. Read the new version from `packages/esroute/package.json`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Release detection does not actually validate version field changes.

The command on Line 30 only checks whether those files were modified, not whether "version" changed. This can incorrectly classify non-release PRs as releases.

🛠️ Suggested fix
-Check whether any commit on this branch touched a `package.json` version field:
+Check whether any commit on this branch changed a `package.json` `version` field:

 ```bash
-git log main..HEAD --oneline --diff-filter=M -- packages/esroute/package.json packages/esroute-lit/package.json
+git log main..HEAD --oneline --diff-filter=M -G '^\s*"version"\s*:' -- packages/esroute/package.json packages/esroute-lit/package.json
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @.claude/skills/pr/SKILL.md around lines 27 - 33, The release detection
currently only checks whether package.json files were modified (the git log
invocation in SKILL.md) and may misclassify PRs; update the git log invocation
to search commits that specifically touched the "version" field by using git log
with a grep-by-diff (-G) regex that matches the "version" JSON key so only
commits that changed the version line in packages/esroute/package.json or
packages/esroute-lit/package.json mark the PR as a release.


</details>

<!-- fingerprinting:phantom:poseidon:hawk:429bf112-f3c6-4bab-be03-2e2f510ce663 -->

<!-- This is an auto-generated comment by CodeRabbit -->

## [0.5.0] - 2022-09-18

### Changed
- **Breaking**: `createRouter` is now a factory function instead of a class — use `createRouter({ routes, ... })` instead of `new Router(...)`)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix malformed markdown in breaking-change entry.

Line 99 has an extra trailing ) which renders awkwardly in the changelog text.

✏️ Suggested fix
-- **Breaking**: `createRouter` is now a factory function instead of a class — use `createRouter({ routes, ... })` instead of `new Router(...)`)
+- **Breaking**: `createRouter` is now a factory function instead of a class — use `createRouter({ routes, ... })` instead of `new Router(...)`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` at line 99, The breaking-change line for createRouter is
malformed due to an extra trailing parenthesis; update the changelog entry so it
reads: "**Breaking**: `createRouter` is now a factory function instead of a
class — use `createRouter({ routes, ... })` instead of `new Router(...)`"
(remove the stray trailing `)` at the end), ensuring the text references
createRouter and Router exactly as shown.

Comment on lines +5 to +13
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Compare published metadata to validate whether CJS compatibility changed.
for v in 0.12.2 0.12.3; do
  echo "=== `@esroute/lit`@$v ==="
  curl -s "https://registry.npmjs.org/@esroute/lit/$v" | jq '{
    version,
    type,
    main,
    exports
  }'
done

Repository: sv2dev/esroute

Length of output: 286


🏁 Script executed:

cat packages/esroute-lit/package.json | head -20

Repository: sv2dev/esroute

Length of output: 644


🏁 Script executed:

#!/bin/bash
# Find what version is in the current package.json
version=$(grep -oP '"version"\s*:\s*"\K[^"]+' packages/esroute-lit/package.json)
echo "Current version in repo: $version"

# Query NPM for versions around this one
npm_response=$(curl -s "https://registry.npmjs.org/@esroute/lit" | jq -r '.versions | keys | .[-5:]' 2>/dev/null)
echo "Recent versions on NPM:"
echo "$npm_response"

Repository: sv2dev/esroute

Length of output: 171


Patch release introduces breaking module-format change that should be a major version bump.

Adding "type": "module" without providing a "require" export condition breaks CommonJS consumers. Version 0.12.2 had no "type" field (treating .js files as CommonJS), while 0.12.3 now treats them as ESM-only. This violates semver for a patch release.

Either (a) release this as 1.0.0+ (breaking change), or (b) provide dual exports with corresponding CommonJS build artifacts:

"exports": {
  ".": {
    "import": "./dist/index.js",
    "require": "./dist/index.cjs"
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/esroute-lit/package.json` around lines 5 - 13, The patch added
"type": "module" causing a breaking change for CommonJS consumers; fix by either
releasing as a major version bump or by restoring CJS compatibility: build a
CommonJS bundle (e.g., dist/index.cjs) and adjust the package.json exports to
provide both "import" and "require" conditions and ensure "main" or "exports"
points to the CJS entry for require users; update the "types" mapping if needed
so dist/index.d.ts still matches both builds and remove or document "type":
"module" if you choose the dual-build approach.

Sven Rogge and others added 5 commits April 2, 2026 12:42
Prevent passing state to router.go() for routes where no state type is
declared. Previously, the optional NavMeta still exposed the state field,
allowing accidental state usage on untyped routes.
Configure packages as ES modules with proper exports field, update TypeScript compiler options for Node16 module resolution, and add .js file extensions to internal imports for ESM compatibility.
@sv2dev sv2dev force-pushed the fix/guard-type-restriction branch from 2f486ab to 24b4a63 Compare April 2, 2026 10:42
@sv2dev sv2dev merged commit c4f2f06 into main Apr 2, 2026
2 checks passed
@sv2dev sv2dev deleted the fix/guard-type-restriction branch April 2, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant