Skip to content

fix(eslint-plugin): Fix initial lint rule bugs#8941

Open
Ephem wants to merge 3 commits into
mainfrom
fredrik/lint-rule-fixes
Open

fix(eslint-plugin): Fix initial lint rule bugs#8941
Ephem wants to merge 3 commits into
mainfrom
fredrik/lint-rule-fixes

Conversation

@Ephem

@Ephem Ephem commented Jun 22, 2026

Copy link
Copy Markdown
Member

Description

I bundled 3 small fixes into this PR, I recommend reviewing per commit.

  • Make fixer wrap existing return type in Promise<> when making the function async
    • Previously function Component(): React.ReactElement would become async function Component(): JSX.Element which would fail TS
    • Now becomes function Component(): Promise<React.ReactElement>
    • Does not wrap if it's already a Promise
    • type Return = Promise<...>; can get double-wrapped via Promise<Return> - we can't follow it, but this should be very rare and fine in practice, worst case TS complains and you have to fix it manually
  • Make the import { auth } from "@clerk/nextjs/server" match the quote style of already existing imports
    • Default to " to match Prettier, ESLint and create-next-app defaults
  • Support || in custom checks, like if (!isAuthenticated || !has(...))

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features
    • The require-auth-protection rule now recognizes authentication guards expressed with OR-conditions (e.g., if (!isAuthenticated || otherCondition)).
    • The fixer now respects the file's existing import quote style when adding new imports.
    • Enhanced TypeScript type handling: function return types are wrapped in Promise<> when converting functions to async.

Ephem added 3 commits June 22, 2026 11:37
Also changes the fallback to double quotes to match Prettier, ESLint and `create-next-app` defaults
Now recognizes `if (!isAuthenticated || otherCondition)` as valid
@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7a21eca

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clerk/eslint-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jun 22, 2026 10:43am
swingset Ready Ready Preview, Comment Jun 22, 2026 10:43am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Three improvements to the require-auth-protection ESLint rule in @clerk/eslint-plugin: a new quote-style.ts utility infers the existing file's import quote character and is used by fixers when inserting auth imports; OR-compound conditions (e.g., !isAuthenticated || x) are now recognized as valid auth guards; and the async fixer now wraps explicit non-Promise return type annotations in Promise<>.

Changes

require-auth-protection rule improvements

Layer / File(s) Summary
Quote style inference utility
packages/eslint-plugin/src/next/lib/quote-style.ts, packages/eslint-plugin/src/next/__tests__/quote-style.test.ts
Adds QuoteChar type and inferQuoteChar function scanning Program.body for import/export-from quote characters, falling back to ". Four test cases cover double-quoted imports, single-quoted imports, re-export sources, and the fallback.
OR-condition auth guard detection
packages/eslint-plugin/src/next/lib/protection-checks.ts, packages/eslint-plugin/src/next/__tests__/require-auth-protection.test.ts, .changeset/eslint-plugin-or-auth-guards.md
Adds guardFiresWhenUnauthenticated helper that recurses through || logical expressions; isAuthGuardWithExit now uses it. New valid cases accept ||-guards; new invalid cases reject &&-guards.
Async fixer: Promise wrapping + quote style
packages/eslint-plugin/src/next/lib/fixers.ts, packages/eslint-plugin/src/next/__tests__/require-auth-protection.suggestions.test.ts, packages/eslint-plugin/src/next/__tests__/fix-auth-protection.test.ts, .changeset/eslint-plugin-add-promise-type.md, .changeset/eslint-plugin-fixer-quote-style.md
ensureAsyncFix replaced by ensureAsyncFixes returning multiple fixes: inserts async and conditionally rewrites explicit return type annotations to Promise<...> (skipping TSTypePredicate and already-Promise types). Import text generation switched to inferQuoteChar. All suggestion and fixer tests updated to assert double-quoted import output.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop, hop! The guards now see || with glee,
Quotes match the file—no hardcoding for me!
Return types wrapped in Promise<> so neat,
The fixer's now async, no missing a beat.
From single to double, the quotes align right,
Three fixes in one—what a hoppy delight! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title describes fixing bugs in the eslint-plugin, which aligns with the three main bug fixes (return type wrapping, quote style matching, and OR operator support) documented in the PR objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8941

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8941

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8941

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8941

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@8941

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8941

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8941

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8941

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8941

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8941

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8941

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8941

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8941

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8941

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8941

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8941

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8941

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8941

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8941

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8941

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8941

commit: 7a21eca

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/eslint-plugin/src/next/lib/fixers.ts`:
- Around line 135-139: The current code allows async insertion for
type-predicate return types while only skipping the return-type wrapping, which
produces invalid TypeScript. Instead of returning null to skip only the return
type modification, move the check for TSTypePredicate to an earlier point in the
addAuthProtectFixes function to prevent the entire fix from being applied to
functions with type-predicate return types. This way, when a function has a
type-predicate return annotation (detected via typeAnnotation.type ===
'TSTypePredicate'), the entire fixer should exit early rather than allowing a
partial transformation that combines async with an incompatible return type.
🪄 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: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 0835949b-dd74-43ac-bffe-a2efd415fa88

📥 Commits

Reviewing files that changed from the base of the PR and between 1693915 and 7a21eca.

📒 Files selected for processing (10)
  • .changeset/eslint-plugin-add-promise-type.md
  • .changeset/eslint-plugin-fixer-quote-style.md
  • .changeset/eslint-plugin-or-auth-guards.md
  • packages/eslint-plugin/src/next/__tests__/fix-auth-protection.test.ts
  • packages/eslint-plugin/src/next/__tests__/quote-style.test.ts
  • packages/eslint-plugin/src/next/__tests__/require-auth-protection.suggestions.test.ts
  • packages/eslint-plugin/src/next/__tests__/require-auth-protection.test.ts
  • packages/eslint-plugin/src/next/lib/fixers.ts
  • packages/eslint-plugin/src/next/lib/protection-checks.ts
  • packages/eslint-plugin/src/next/lib/quote-style.ts

Comment thread packages/eslint-plugin/src/next/lib/fixers.ts
import { auth } from '@clerk/nextjs/server';
export default async function Page() {
const { isAuthenticated } = await auth();
if (!isAuthenticated || someFlag) return null;

@jacekradko jacekradko Jun 22, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Directional question.. should we allow mix of auth/not-auth conditional logic here or should it be strictly auth.* || auth.* ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a good question and I asked myself the same, but I don't see why not? As long as it always happens for !isAuthenticated I think it's fine.

There is a small risk of if (!isAuthenticated || doDangerousThing()), but I feel that should be rare and obvious enough that DX wins here. We already allow arbitrary code above the early exit now which is not exactly the same (we are already in an "unauthed state" there, which we are not when evaluating the if), but close enough?

@jacekradko jacekradko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good. Just an exploratory question on logical checks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants