@clerk/eslint-plugin 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +263 -0
- package/dist/chunk-C_NdSu1c.js +34 -0
- package/dist/next/fix-auth-protection-cli.d.mts +1 -0
- package/dist/next/fix-auth-protection-cli.d.ts +1 -0
- package/dist/next/fix-auth-protection-cli.js +101 -0
- package/dist/next/fix-auth-protection-cli.js.map +1 -0
- package/dist/next/fix-auth-protection-cli.mjs +100 -0
- package/dist/next/fix-auth-protection-cli.mjs.map +1 -0
- package/dist/next/fix-auth-protection.d.mts +59 -0
- package/dist/next/fix-auth-protection.d.mts.map +1 -0
- package/dist/next/fix-auth-protection.d.ts +59 -0
- package/dist/next/fix-auth-protection.d.ts.map +1 -0
- package/dist/next/fix-auth-protection.js +149 -0
- package/dist/next/fix-auth-protection.js.map +1 -0
- package/dist/next/fix-auth-protection.mjs +148 -0
- package/dist/next/fix-auth-protection.mjs.map +1 -0
- package/dist/next.d.mts +7 -0
- package/dist/next.d.mts.map +1 -0
- package/dist/next.d.ts +6 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +833 -0
- package/dist/next.js.map +1 -0
- package/dist/next.mjs +831 -0
- package/dist/next.mjs.map +1 -0
- package/package.json +81 -3
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.js","names":["path","CLERK_AUTH_SOURCE","path","requireAuthProtection"],"sources":["../src/next/lib/exports.ts","../src/next/lib/file-info.ts","../src/next/lib/fixers.ts","../src/next/lib/match-folders.ts","../src/next/lib/project-root.ts","../src/next/lib/protection-checks.ts","../src/next/require-auth-protection.ts","../src/next/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */\n/**\n * Resolve a module's exports to the function target that will run when the framework dispatches.\n */\n\nimport type { TSESTree } from '@typescript-eslint/utils';\n\nexport type FunctionNode =\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression;\n\nexport type ExportTarget =\n | { kind: 'function'; node: FunctionNode }\n | { kind: 'imported'; source: string }\n | { kind: 'unknown' };\n\nexport interface NamedExportItem {\n name: string;\n target: ExportTarget;\n reportNode: TSESTree.Node;\n}\n\nexport interface DefaultExportItem {\n target: ExportTarget;\n reportNode: TSESTree.Node;\n}\n\nexport interface ExportAllItem {\n source: string;\n reportNode: TSESTree.Node;\n}\n\nexport function unwrapFunction(node: TSESTree.Node | null | undefined): FunctionNode | null {\n if (!node) {\n return null;\n }\n if (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n ) {\n return node;\n }\n return null;\n}\n\nexport function resolveLocalIdentifierTarget(programNode: TSESTree.Program, name: string): ExportTarget {\n for (const stmt of programNode.body) {\n if (stmt.type === 'FunctionDeclaration' && stmt.id && stmt.id.name === name) {\n return { kind: 'function', node: stmt };\n }\n if (stmt.type === 'VariableDeclaration') {\n for (const declarator of stmt.declarations) {\n if (declarator.id.type !== 'Identifier' || declarator.id.name !== name) {\n continue;\n }\n const initFn = unwrapFunction(declarator.init ?? undefined);\n if (initFn) {\n return { kind: 'function', node: initFn };\n }\n return { kind: 'unknown' };\n }\n }\n if (stmt.type === 'ImportDeclaration') {\n for (const spec of stmt.specifiers) {\n if (spec.local && spec.local.name === name) {\n return {\n kind: 'imported',\n source: stmt.source.value,\n };\n }\n }\n }\n }\n return { kind: 'unknown' };\n}\n\nexport function resolveDefaultExportTarget(programNode: TSESTree.Program, declaration: TSESTree.Node): ExportTarget {\n const direct = unwrapFunction(declaration);\n if (direct) {\n return { kind: 'function', node: direct };\n }\n\n if (declaration.type !== 'Identifier') {\n return { kind: 'unknown' };\n }\n\n return resolveLocalIdentifierTarget(programNode, declaration.name);\n}\n\nfunction getExportedName(spec: TSESTree.ExportSpecifier): string | null {\n const node = spec.exported;\n if (node.type === 'Identifier') {\n return node.name;\n }\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value;\n }\n return null;\n}\n\n/**\n * Resolve the module's default export, regardless of whether it's declared with\n * `export default ...` or via a specifier such as `export { Page as default }`\n * or `export { default } from './Page'`.\n */\nexport function resolveDefaultExport(programNode: TSESTree.Program): DefaultExportItem | null {\n for (const stmt of programNode.body) {\n if (stmt.type === 'ExportDefaultDeclaration') {\n return {\n target: resolveDefaultExportTarget(programNode, stmt.declaration),\n reportNode: stmt,\n };\n }\n\n if (stmt.type !== 'ExportNamedDeclaration') {\n continue;\n }\n // `export type { Foo as default }` — the whole statement is type-only\n if (stmt.exportKind === 'type') {\n continue;\n }\n\n for (const spec of stmt.specifiers) {\n if (spec.type !== 'ExportSpecifier') {\n continue;\n }\n // `export { type Foo as default }` — individual specifier is type-only\n if (spec.exportKind === 'type') {\n continue;\n }\n if (getExportedName(spec) !== 'default') {\n continue;\n }\n\n if (stmt.source) {\n return {\n target: { kind: 'imported', source: stmt.source.value },\n reportNode: stmt,\n };\n }\n\n if (spec.local.type !== 'Identifier') {\n return { target: { kind: 'unknown' }, reportNode: stmt };\n }\n\n return {\n target: resolveLocalIdentifierTarget(programNode, spec.local.name),\n reportNode: stmt,\n };\n }\n }\n return null;\n}\n\n/**\n * Yield value-level `export * from '...'` declarations. The rule cannot follow\n * these across files, so callers treat them conservatively as unverifiable.\n */\nexport function* iterateExportAllDeclarations(programNode: TSESTree.Program): Generator<ExportAllItem> {\n for (const stmt of programNode.body) {\n if (stmt.type !== 'ExportAllDeclaration') {\n continue;\n }\n // `export type * from '...'` — type-only re-export\n if (stmt.exportKind === 'type') {\n continue;\n }\n // `export * as name from '...'` exposes a namespace binding, not top-level\n // route handlers or Server Functions.\n if (stmt.exported) {\n continue;\n }\n yield {\n source: stmt.source.value,\n reportNode: stmt,\n };\n }\n}\n\nexport function* iterateNamedExports(programNode: TSESTree.Program): Generator<NamedExportItem> {\n for (const stmt of programNode.body) {\n if (stmt.type !== 'ExportNamedDeclaration') {\n continue;\n }\n // `export type { Foo }` — the whole statement is type-only\n if (stmt.exportKind === 'type') {\n continue;\n }\n\n if (stmt.declaration) {\n const decl = stmt.declaration;\n if (decl.type === 'FunctionDeclaration' && decl.id) {\n yield {\n name: decl.id.name,\n target: { kind: 'function', node: decl },\n reportNode: stmt,\n };\n } else if (decl.type === 'VariableDeclaration') {\n for (const declarator of decl.declarations) {\n if (declarator.id.type !== 'Identifier') {\n continue;\n }\n const fn = unwrapFunction(declarator.init ?? undefined);\n yield {\n name: declarator.id.name,\n target: fn ? { kind: 'function', node: fn } : { kind: 'unknown' },\n reportNode: stmt,\n };\n }\n }\n continue;\n }\n\n for (const spec of stmt.specifiers) {\n if (spec.type !== 'ExportSpecifier') {\n continue;\n }\n // `export { type Foo }` — individual specifier is type-only\n if (spec.exportKind === 'type') {\n continue;\n }\n const exportedName = getExportedName(spec);\n if (!exportedName) {\n continue;\n }\n\n if (stmt.source) {\n yield {\n name: exportedName,\n target: { kind: 'imported', source: stmt.source.value },\n reportNode: stmt,\n };\n continue;\n }\n\n if (spec.local.type !== 'Identifier') {\n continue;\n }\n yield {\n name: exportedName,\n target: resolveLocalIdentifierTarget(programNode, spec.local.name),\n reportNode: stmt,\n };\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */\n/**\n * Utilities for classifying a file by path, kind, and module-level directives.\n */\n\nimport path from 'node:path';\n\nimport type { TSESTree } from '@typescript-eslint/utils';\n\nexport type FileKind = 'page' | 'layout' | 'template' | 'default' | 'route';\n\nconst RESOURCE_FILES = new Set<FileKind>(['page', 'layout', 'template', 'default', 'route']);\n\nconst RESOURCE_EXTENSIONS = /\\.(ts|tsx|js|jsx|mjs|cjs)$/;\n\n/**\n * @param rootDir Project root to relativize against — typically from\n * `resolveProjectRoot()` (explicit option, nearest `eslint.config.*`, or ESLint\n * `cwd`). When omitted or when the file lies outside `rootDir`, the absolute\n * path is scanned for an `app` segment instead.\n */\nexport function getRelativeFolder(filename: string | undefined, rootDir: string | undefined): string | null {\n if (!filename) {\n return null;\n }\n const normalizedFile = filename.replaceAll('\\\\', '/');\n\n // Prefer a project-relative path so that noise in the absolute prefix (a home\n // directory like `/Users/app/...`, a monorepo root, etc.) can't be mistaken\n // for the Next.js App Router root. When the file lives outside `rootDir` (e.g.\n // in `RuleTester`, which lints in-memory code), fall back to the absolute path.\n let candidate = normalizedFile;\n if (rootDir) {\n const normalizedRoot = rootDir.replaceAll('\\\\', '/');\n const rel = path.posix.relative(normalizedRoot, normalizedFile);\n if (rel && !rel.startsWith('..')) {\n candidate = rel;\n }\n }\n\n // The App Router root is the first path segment that is exactly `app` (this\n // also covers the `src/app/` convention, where the leading `src` segment is\n // simply skipped). Folder globs in config are rooted at `app/...`, so we\n // re-root the returned folder there. Matching whole segments (rather than the\n // `/app/` substring) avoids false positives like `myapp` or `app-utils`.\n const segments = candidate.split('/');\n const appIdx = segments.findIndex(seg => seg === 'app');\n if (appIdx !== -1) {\n return path.posix.dirname(segments.slice(appIdx).join('/'));\n }\n\n // No `app` segment: only meaningful when we have a project-relative path.\n if (candidate !== normalizedFile) {\n return path.posix.dirname(candidate);\n }\n return null;\n}\n\nexport function getFileKind(filename: string | undefined): FileKind | null {\n if (!filename) {\n return null;\n }\n const base = path.basename(filename).replace(RESOURCE_EXTENSIONS, '');\n return RESOURCE_FILES.has(base as FileKind) ? (base as FileKind) : null;\n}\n\nfunction hasTopLevelDirective(programNode: TSESTree.Program, name: string): boolean {\n for (const stmt of programNode.body) {\n if (stmt.type !== 'ExpressionStatement') {\n break;\n }\n if (!('directive' in stmt)) {\n break;\n }\n if (stmt.directive === name) {\n return true;\n }\n }\n return false;\n}\n\nexport function isServerFunctionModule(programNode: TSESTree.Program): boolean {\n return hasTopLevelDirective(programNode, 'use server');\n}\n\nexport function isClientModule(programNode: TSESTree.Program): boolean {\n return hasTopLevelDirective(programNode, 'use client');\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */\n/**\n * Reusable fixers that add `await auth.protect()` to a function.\n *\n * These are intentionally decoupled from the ESLint rule: they take a `fixer`\n * and `sourceCode` plus the resolved function node and return plain\n * `RuleFix[]`. The rule wires them into a suggestion today, but a later\n * auto-apply script (and `@clerk/upgrade`) can reuse the exact same logic.\n *\n * Mirrors the operations of the original `transform-add-auth-protect` codemod:\n * - ensure the function is `async`\n * - insert `await auth.protect()` as the first executable statement\n * - add `import { auth } from '@clerk/nextjs/server'` (or merge the `auth`\n * specifier into an existing import from that source)\n */\n\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\n\nimport type { FunctionNode } from './exports';\n\nconst CLERK_AUTH_SOURCE = '@clerk/nextjs/server';\n\nexport interface BuildAuthProtectFixesParams {\n fixer: TSESLint.RuleFixer;\n sourceCode: TSESLint.SourceCode;\n fn: FunctionNode;\n /** Local names `auth` is already imported as, from `findAuthLocalNames`. */\n authNames: Set<string>;\n}\n\n/**\n * The local name to call `.protect()` on. Reuses an existing alias (e.g.\n * `import { auth as clerkAuth }`) when present, otherwise defaults to `auth`.\n */\nexport function resolveAuthName(authNames: Set<string>): string {\n for (const name of authNames) {\n return name;\n }\n return 'auth';\n}\n\n/**\n * Build the ordered, non-overlapping set of edits that protect `fn`. All edits\n * belong to a single suggestion and are applied atomically.\n */\nexport function buildAuthProtectFixes({\n fixer,\n sourceCode,\n fn,\n authNames,\n}: BuildAuthProtectFixesParams): TSESLint.RuleFix[] {\n const program = sourceCode.ast;\n const authName = resolveAuthName(authNames);\n const fixes: TSESLint.RuleFix[] = [];\n\n // Order matters when insertions share a position. When the function is the\n // first statement in the file (e.g. `function Page() {}; export default Page`),\n // the import and the `async ` keyword both insert at the function's start;\n // emitting the import first keeps it on its own line above the function.\n const importFix = ensureAuthImportFix(fixer, sourceCode, program, authNames);\n if (importFix) {\n fixes.push(importFix);\n }\n\n const asyncFix = ensureAsyncFix(fixer, sourceCode, fn);\n if (asyncFix) {\n fixes.push(asyncFix);\n }\n\n fixes.push(insertProtectCallFix(fixer, sourceCode, fn, authName, authNames));\n\n return fixes;\n}\n\n/**\n * If `node` is `await <auth>()` (a zero-argument call to one of the imported\n * `auth` names), return the callee identifier so it can be rewritten to\n * `<auth>.protect`. Returns `null` otherwise.\n *\n * Used to merge protection into an existing call (`const { userId } = await\n * auth()` -> `const { userId } = await auth.protect()`) instead of prepending a\n * duplicate `await auth.protect();`.\n */\nfunction mergeableAuthCallee(\n node: TSESTree.Node | null | undefined,\n authNames: Set<string>,\n): TSESTree.Identifier | null {\n if (!node || node.type !== 'AwaitExpression') {\n return null;\n }\n const arg = node.argument;\n if (arg.type !== 'CallExpression' || arg.arguments.length > 0) {\n return null;\n }\n if (arg.callee.type !== 'Identifier' || !authNames.has(arg.callee.name)) {\n return null;\n }\n return arg.callee;\n}\n\n/**\n * Look for a mergeable `await <auth>()` in the first executable statement of a\n * block body — either a bare `await auth();` or the initializer of the first\n * declarator (`const { userId } = await auth();`).\n */\nfunction firstStatementAuthCallee(stmt: TSESTree.Statement, authNames: Set<string>): TSESTree.Identifier | null {\n if (stmt.type === 'ExpressionStatement') {\n return mergeableAuthCallee(stmt.expression, authNames);\n }\n if (stmt.type === 'VariableDeclaration') {\n const first = stmt.declarations[0];\n return first ? mergeableAuthCallee(first.init, authNames) : null;\n }\n return null;\n}\n\nfunction getLineIndent(sourceCode: TSESLint.SourceCode, node: TSESTree.Node): string {\n const line = sourceCode.lines[node.loc.start.line - 1] ?? '';\n const match = /^\\s*/.exec(line);\n return match ? match[0] : '';\n}\n\nfunction ensureAsyncFix(\n fixer: TSESLint.RuleFixer,\n sourceCode: TSESLint.SourceCode,\n fn: FunctionNode,\n): TSESLint.RuleFix | null {\n if (fn.async) {\n return null;\n }\n const firstToken = sourceCode.getFirstToken(fn);\n if (!firstToken) {\n return null;\n }\n return fixer.insertTextBefore(firstToken, 'async ');\n}\n\nfunction insertProtectCallFix(\n fixer: TSESLint.RuleFixer,\n sourceCode: TSESLint.SourceCode,\n fn: FunctionNode,\n authName: string,\n authNames: Set<string>,\n): TSESLint.RuleFix {\n const call = `await ${authName}.protect();`;\n const body = fn.body;\n\n // Concise-body arrow (`() => expr`) — merge into an existing `await auth()`\n // body, otherwise wrap in a block so we can insert.\n if (body.type !== 'BlockStatement') {\n const conciseCallee = mergeableAuthCallee(body, authNames);\n if (conciseCallee) {\n return fixer.replaceText(conciseCallee, `${conciseCallee.name}.protect`);\n }\n const fnIndent = getLineIndent(sourceCode, fn);\n const inner = `${fnIndent} `;\n const exprText = sourceCode.getText(body);\n const blockBody = `{\\n${inner}${call}\\n${inner}return ${exprText};\\n${fnIndent}}`;\n\n // Replace everything after the `=>`, not just the body node. A body node's\n // range excludes any parentheses wrapping the expression, so replacing only\n // the body leaves them behind and emits `() => ({ ...block... })` for a\n // parenthesized concise body (`() => ({ ok: true })`, `() => (<jsx />)`),\n // which is a syntax error.\n const arrowToken = sourceCode.getTokenBefore(body, {\n filter: token => token.type === 'Punctuator' && token.value === '=>',\n });\n if (arrowToken) {\n return fixer.replaceTextRange([arrowToken.range[1], fn.range[1]], ` ${blockBody}`);\n }\n // Defensive fallback: no `=>` found (unexpected). Replace just the body.\n return fixer.replaceText(body, blockBody);\n }\n\n const stmts = body.body;\n\n // Skip a leading directive prologue (e.g. an inline `'use server'`): inserting\n // before it would demote the directive to an ordinary expression statement.\n let lastDirective: TSESTree.Statement | null = null;\n let firstExecIdx = 0;\n for (const stmt of stmts) {\n if (stmt.type === 'ExpressionStatement' && stmt.directive) {\n lastDirective = stmt;\n firstExecIdx++;\n } else {\n break;\n }\n }\n\n // If the first executable statement already awaits `auth()`, rewrite that call\n // to `auth.protect()` rather than prepending a duplicate protection call.\n const firstExec = stmts[firstExecIdx];\n if (firstExec) {\n const mergeCallee = firstStatementAuthCallee(firstExec, authNames);\n if (mergeCallee) {\n return fixer.replaceText(mergeCallee, `${mergeCallee.name}.protect`);\n }\n }\n\n if (lastDirective) {\n const indent = getLineIndent(sourceCode, lastDirective);\n return fixer.insertTextAfter(lastDirective, `\\n${indent}${call}`);\n }\n\n const firstStmt = stmts[0];\n if (firstStmt) {\n const indent = getLineIndent(sourceCode, firstStmt);\n return fixer.insertTextBefore(firstStmt, `${call}\\n${indent}`);\n }\n\n // Empty block body.\n const openBrace = sourceCode.getFirstToken(body);\n const indent = `${getLineIndent(sourceCode, fn)} `;\n if (openBrace) {\n return fixer.insertTextAfter(openBrace, `\\n${indent}${call}`);\n }\n return fixer.insertTextBefore(body, `${call}\\n`);\n}\n\nfunction ensureAuthImportFix(\n fixer: TSESLint.RuleFixer,\n sourceCode: TSESLint.SourceCode,\n program: TSESTree.Program,\n authNames: Set<string>,\n): TSESLint.RuleFix | null {\n // `auth` is already imported (possibly aliased) — reuse it, no import change.\n if (authNames.size > 0) {\n return null;\n }\n\n // Past the guard above, no `auth` import exists, so the specifier is always\n // the unaliased `auth`. (Callers reuse an existing alias for the\n // `.protect()` call, but a fresh import never introduces one.)\n\n // Merge into an existing value import from `@clerk/nextjs/server` when it has\n // a named-specifier list we can extend.\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') {\n continue;\n }\n if (stmt.source.value !== CLERK_AUTH_SOURCE || stmt.importKind === 'type') {\n continue;\n }\n const named = stmt.specifiers.filter((spec): spec is TSESTree.ImportSpecifier => spec.type === 'ImportSpecifier');\n const last = named[named.length - 1];\n if (last) {\n return fixer.insertTextAfter(last, ', auth');\n }\n continue;\n }\n\n const importText = `import { auth } from '${CLERK_AUTH_SOURCE}';`;\n const stmts = program.body;\n\n // Insert after a leading directive prologue (module-level `'use server'` /\n // `'use client'`), otherwise before the first statement.\n let lastDirective: TSESTree.ExpressionStatement | null = null;\n for (const stmt of stmts) {\n if (stmt.type === 'ExpressionStatement' && stmt.directive) {\n lastDirective = stmt;\n } else {\n break;\n }\n }\n\n if (lastDirective) {\n return fixer.insertTextAfter(lastDirective, `\\n${importText}`);\n }\n\n const firstStmt = stmts[0];\n if (firstStmt) {\n return fixer.insertTextBefore(firstStmt, `${importText}\\n`);\n }\n\n return fixer.insertTextAfterRange([0, 0], `${importText}\\n`);\n}\n","/**\n * Folder-glob matcher for the require-auth-protection rule.\n */\n\nexport interface ClassifyOptions {\n protected?: string[];\n public?: string[];\n}\n\nexport type FolderClass = 'public' | 'protected' | 'unmatched';\n\nconst REGEX_SPECIAL = /[.+^${}()|[\\]\\\\]/g;\n\nfunction segmentToRegex(seg: string): string {\n let out = '';\n for (let i = 0; i < seg.length; i++) {\n const ch = seg[i];\n if (ch === '*') {\n out += '[^/]*';\n } else if (REGEX_SPECIAL.test(ch)) {\n out += '\\\\' + ch;\n } else {\n out += ch;\n }\n REGEX_SPECIAL.lastIndex = 0;\n }\n return out;\n}\n\nfunction segmentMatches(patternSeg: string, pathSeg: string): boolean {\n if (patternSeg === pathSeg) {\n return true;\n }\n if (!patternSeg.includes('*')) {\n return false;\n }\n return new RegExp('^' + segmentToRegex(patternSeg) + '$').test(pathSeg);\n}\n\nfunction matchSegments(patternSegs: string[], pi: number, pathSegs: string[], si: number): boolean {\n while (pi < patternSegs.length) {\n const seg = patternSegs[pi];\n if (seg === '**') {\n if (pi === patternSegs.length - 1) {\n return true;\n }\n for (let k = si; k <= pathSegs.length; k++) {\n if (matchSegments(patternSegs, pi + 1, pathSegs, k)) {\n return true;\n }\n }\n return false;\n }\n if (si >= pathSegs.length) {\n return false;\n }\n if (!segmentMatches(seg, pathSegs[si])) {\n return false;\n }\n pi++;\n si++;\n }\n return si === pathSegs.length;\n}\n\nexport function matchPath(pattern: string, path: string): boolean {\n return matchSegments(pattern.split('/'), 0, path.split('/'), 0);\n}\n\nexport function specificity(pattern: string): number {\n return pattern.split('/').filter(seg => seg.length > 0 && seg !== '**' && !seg.includes('*')).length;\n}\n\nexport function literalPrefix(pattern: string): string {\n const segs = pattern.split('/');\n const result: string[] = [];\n for (const seg of segs) {\n if (seg === '**' || seg.includes('*')) {\n break;\n }\n result.push(seg);\n }\n return result.join('/');\n}\n\nexport function hasDescendantsMatching(folder: string, patterns: string[] | undefined): boolean {\n if (!patterns || patterns.length === 0) {\n return false;\n }\n for (const pattern of patterns) {\n const prefix = literalPrefix(pattern);\n if (!prefix) {\n continue;\n }\n if (prefix === folder) {\n return true;\n }\n if (prefix.startsWith(folder + '/')) {\n return true;\n }\n }\n return false;\n}\n\nexport function classifyFolder(folderPath: string, options: ClassifyOptions): FolderClass {\n const protectPatterns = options.protected ?? [];\n const publicPatterns = options.public ?? [];\n\n const protectMatches = protectPatterns.filter(p => matchPath(p, folderPath));\n const publicMatches = publicPatterns.filter(p => matchPath(p, folderPath));\n\n if (protectMatches.length === 0 && publicMatches.length === 0) {\n return 'unmatched';\n }\n if (publicMatches.length === 0) {\n return 'protected';\n }\n if (protectMatches.length === 0) {\n return 'public';\n }\n\n const maxProtect = Math.max(...protectMatches.map(specificity));\n const maxPublic = Math.max(...publicMatches.map(specificity));\n\n return maxProtect >= maxPublic ? 'protected' : 'public';\n}\n","/**\n * Resolve the directory paths should be relativized against when classifying\n * App Router folders.\n */\n\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\n\n/** Filenames ESLint searches for when resolving flat config (precedence order). */\nexport const ESLINT_CONFIG_FILENAMES = [\n 'eslint.config.js',\n 'eslint.config.mjs',\n 'eslint.config.cjs',\n 'eslint.config.ts',\n 'eslint.config.mts',\n 'eslint.config.cts',\n] as const;\n\nfunction normalizeDir(dir: string): string {\n return dir.replaceAll('\\\\', '/');\n}\n\n/**\n * Walk up from `filePath` and return the directory of the nearest\n * `eslint.config.*`, mirroring ESLint's per-file config lookup.\n */\nexport function findEslintProjectRoot(filePath: string): string | null {\n let dir = path.resolve(path.dirname(filePath));\n const { root } = path.parse(dir);\n\n while (true) {\n for (const name of ESLINT_CONFIG_FILENAMES) {\n if (existsSync(path.join(dir, name))) {\n return normalizeDir(dir);\n }\n }\n if (dir === root) {\n return null;\n }\n dir = path.dirname(dir);\n }\n}\n\nexport interface ResolveProjectRootOptions {\n /** Explicit override (e.g. `import.meta.dirname` from `eslint.config.mjs`). */\n rootDir?: string;\n /** ESLint `context.cwd` fallback when config discovery finds nothing. */\n cwd?: string;\n}\n\n/**\n * Pick the directory to relativize linted file paths against.\n *\n * Precedence: explicit `rootDir` → nearest `eslint.config.*` ancestor → `cwd`.\n */\nexport function resolveProjectRoot(\n filename: string | undefined,\n { rootDir, cwd }: ResolveProjectRootOptions = {},\n): string | undefined {\n if (rootDir) {\n return normalizeDir(rootDir);\n }\n if (filename) {\n const fromConfig = findEslintProjectRoot(filename);\n if (fromConfig) {\n return fromConfig;\n }\n }\n return cwd ? normalizeDir(cwd) : undefined;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */\n/**\n * AST detection for \"is this function protected at its top?\"\n */\n\nimport type { TSESTree } from '@typescript-eslint/utils';\n\nimport type { FunctionNode } from './exports';\n\nconst CLERK_AUTH_SOURCE = '@clerk/nextjs/server';\n\n/**\n * Collect the local names that `auth` is imported as from `@clerk/nextjs/server`\n * in the given module. Usually returns `{'auth'}`, but handles aliased imports\n * like `import { auth as clerkAuth } from '@clerk/nextjs/server'` correctly.\n * Type-only imports (`import type { auth }` / `import { type auth }`) are\n * excluded — they are erased at compile time and do not provide a runtime binding.\n */\nexport function findAuthLocalNames(programNode: TSESTree.Program): Set<string> {\n const names = new Set<string>();\n for (const stmt of programNode.body) {\n if (stmt.type !== 'ImportDeclaration') {\n continue;\n }\n if (stmt.source.value !== CLERK_AUTH_SOURCE) {\n continue;\n }\n if (stmt.importKind === 'type') {\n continue;\n }\n for (const spec of stmt.specifiers) {\n if (spec.type !== 'ImportSpecifier') {\n continue;\n }\n if (spec.importKind === 'type') {\n continue;\n }\n const imported = spec.imported.type === 'Identifier' ? spec.imported.name : spec.imported.value;\n if (imported === 'auth') {\n names.add(spec.local.name);\n }\n }\n }\n return names;\n}\n\ntype AuthField = 'userId' | 'sessionId' | 'isAuthenticated';\n\nconst AUTH_FIELDS = new Set<AuthField>(['userId', 'sessionId', 'isAuthenticated']);\n\n// We don't trace these to actual imports like with `auth`, as all we really care\n// about is that the code stops executing at this point. Tracing these to imports\n// would be complex, not worth the effort (at this point) and disallow any type\n// of wrapper that eventually calls these functions behind the scenes.\n// Essentially, if you name something to any of these, we'll credit you with an exit.\nconst EXIT_FUNCTIONS = new Set([\n 'redirect',\n 'permanentRedirect',\n 'notFound',\n 'unauthorized',\n 'forbidden',\n 'redirectToSignIn',\n 'redirectToSignUp',\n]);\n\nfunction isProtectCall(node: TSESTree.Node | null | undefined, authNames: Set<string>): boolean {\n if (!node || node.type !== 'CallExpression') {\n return false;\n }\n const callee = node.callee;\n if (callee.type !== 'MemberExpression') {\n return false;\n }\n if (callee.property.type !== 'Identifier' || callee.property.name !== 'protect') {\n return false;\n }\n if (callee.object.type === 'Identifier' && authNames.has(callee.object.name)) {\n return true;\n }\n if (\n callee.object.type === 'AwaitExpression' &&\n callee.object.argument.type === 'CallExpression' &&\n callee.object.argument.callee.type === 'Identifier' &&\n authNames.has(callee.object.argument.callee.name)\n ) {\n return true;\n }\n return false;\n}\n\nfunction isProtectAwait(node: TSESTree.Node | null | undefined, authNames: Set<string>): boolean {\n return !!node && node.type === 'AwaitExpression' && isProtectCall(node.argument, authNames);\n}\n\nfunction isProtectAwaitStatement(stmt: TSESTree.Statement, authNames: Set<string>): boolean {\n if (stmt.type === 'ExpressionStatement') {\n return isProtectAwait(stmt.expression, authNames);\n }\n if (stmt.type === 'VariableDeclaration') {\n // Only the first declarator counts: later declarators are preceded by\n // earlier ones executing first, so `auth.protect()` wouldn't be at the top.\n const first = stmt.declarations[0];\n return first != null && isProtectAwait(first.init ?? undefined, authNames);\n }\n return false;\n}\n\nfunction capturedAuthBindings(stmt: TSESTree.Statement, authNames: Set<string>): Set<AuthField> | null {\n if (stmt.type !== 'VariableDeclaration') {\n return null;\n }\n\n // Require a single declarator: a multi-declarator statement such as\n // `const { userId } = await auth(), side = doWork()` runs `side = doWork()`\n // after the destructure but before the guard, so it must not be treated as\n // protected (matching the rejection of any statement between destructure and\n // guard).\n if (stmt.declarations.length !== 1) {\n return null;\n }\n\n const decl = stmt.declarations[0];\n if (!decl) {\n return null;\n }\n if (decl.id.type !== 'ObjectPattern') {\n return null;\n }\n if (!decl.init || decl.init.type !== 'AwaitExpression') {\n return null;\n }\n const arg = decl.init.argument;\n if (arg.type !== 'CallExpression') {\n return null;\n }\n if (arg.callee.type !== 'Identifier' || !authNames.has(arg.callee.name)) {\n return null;\n }\n\n const bindings = new Set<AuthField>();\n for (const prop of decl.id.properties) {\n if (prop.type !== 'Property') {\n continue;\n }\n if (prop.key.type !== 'Identifier') {\n continue;\n }\n const fieldName = prop.key.name;\n if (!AUTH_FIELDS.has(fieldName as AuthField)) {\n continue;\n }\n if (prop.value.type !== 'Identifier' || prop.value.name !== fieldName) {\n continue;\n }\n bindings.add(fieldName as AuthField);\n }\n return bindings.size > 0 ? bindings : null;\n}\n\nfunction isRecognizedAuthCheck(test: TSESTree.Expression, bindings: Set<AuthField>): boolean {\n if (test.type === 'UnaryExpression' && test.operator === '!') {\n // `!userId` / `!sessionId` / `!isAuthenticated`. On the server these fields\n // are `string | null` / `boolean`, so the negation is equivalent to the\n // explicit `=== null` / `=== false` checks. Both forms are accepted here.\n return (\n test.argument.type === 'Identifier' &&\n AUTH_FIELDS.has(test.argument.name as AuthField) &&\n bindings.has(test.argument.name as AuthField)\n );\n }\n\n if (test.type !== 'BinaryExpression') {\n return false;\n }\n if (test.operator !== '===' && test.operator !== '==') {\n return false;\n }\n\n let id: TSESTree.Identifier;\n let other: TSESTree.Expression;\n if (test.left.type === 'Identifier' && bindings.has(test.left.name as AuthField)) {\n id = test.left;\n other = test.right;\n } else if (test.right.type === 'Identifier' && bindings.has(test.right.name as AuthField)) {\n id = test.right;\n other = test.left;\n } else {\n return false;\n }\n\n const name = id.name as AuthField;\n\n if (name === 'userId' || name === 'sessionId') {\n return other.type === 'Literal' && other.value === null;\n }\n if (name === 'isAuthenticated') {\n return test.operator === '===' && other.type === 'Literal' && other.value === false;\n }\n return false;\n}\n\nfunction isExitCall(expr: TSESTree.Expression | null | undefined): boolean {\n if (!expr || expr.type !== 'CallExpression') {\n return false;\n }\n if (expr.callee.type !== 'Identifier') {\n return false;\n }\n return EXIT_FUNCTIONS.has(expr.callee.name);\n}\n\nfunction statementExits(stmt: TSESTree.Statement | null | undefined): boolean {\n if (!stmt) {\n return false;\n }\n if (stmt.type === 'ReturnStatement') {\n return true;\n }\n if (stmt.type === 'ThrowStatement') {\n return true;\n }\n if (stmt.type === 'ExpressionStatement') {\n return isExitCall(stmt.expression);\n }\n return false;\n}\n\nfunction consequentExits(consequent: TSESTree.Statement | null | undefined): boolean {\n if (!consequent) {\n return false;\n }\n if (statementExits(consequent)) {\n return true;\n }\n if (consequent.type === 'BlockStatement') {\n // A guaranteed top-level exit anywhere in the block is enough: the block\n // only runs in the unauthenticated branch the developer is explicitly\n // handling, and once it exits, the protected code below is unreachable for\n // a signed-out user. Work the developer chooses to run before bailing\n // (logging, cleanup, etc.) is their deliberate call, so we don't forbid it.\n return consequent.body.some(statementExits);\n }\n return false;\n}\n\nfunction isAuthGuardWithExit(stmt: TSESTree.Statement, bindings: Set<AuthField>): boolean {\n if (stmt.type !== 'IfStatement') {\n return false;\n }\n if (!isRecognizedAuthCheck(stmt.test, bindings)) {\n return false;\n }\n return consequentExits(stmt.consequent);\n}\n\nfunction isNonRuntimeStatement(stmt: TSESTree.Statement): boolean {\n if (stmt.type === 'ExpressionStatement' && stmt.directive) {\n return true;\n }\n if (stmt.type === 'TSTypeAliasDeclaration') {\n return true;\n }\n if (stmt.type === 'TSInterfaceDeclaration') {\n return true;\n }\n return false;\n}\n\nfunction nextExecutable(stmts: TSESTree.Statement[], from: number): number {\n let i = from;\n while (i < stmts.length && isNonRuntimeStatement(stmts[i])) {\n i++;\n }\n return i;\n}\n\nexport function hasProtectAtTop(fn: FunctionNode | null | undefined, authNames: Set<string>): boolean {\n if (!fn || !fn.async) {\n return false;\n }\n\n const body = fn.body;\n if (body && body.type !== 'BlockStatement') {\n return body.type === 'AwaitExpression' && isProtectCall(body.argument, authNames);\n }\n if (!body || body.type !== 'BlockStatement') {\n return false;\n }\n\n const stmts = body.body;\n const first = nextExecutable(stmts, 0);\n if (first >= stmts.length) {\n return false;\n }\n\n if (isProtectAwaitStatement(stmts[first], authNames)) {\n return true;\n }\n\n const captured = capturedAuthBindings(stmts[first], authNames);\n if (captured) {\n const second = nextExecutable(stmts, first + 1);\n if (second < stmts.length && isAuthGuardWithExit(stmts[second], captured)) {\n return true;\n }\n }\n\n return false;\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */\nimport type { TSESLint, TSESTree } from '@typescript-eslint/utils';\nimport type { Rule } from 'eslint';\n\nimport type { ExportTarget, FunctionNode } from './lib/exports';\nimport { iterateExportAllDeclarations, iterateNamedExports, resolveDefaultExport } from './lib/exports';\nimport { type FileKind, getFileKind, getRelativeFolder, isClientModule, isServerFunctionModule } from './lib/file-info';\nimport { buildAuthProtectFixes } from './lib/fixers';\nimport type { ClassifyOptions } from './lib/match-folders';\nimport { classifyFolder, hasDescendantsMatching } from './lib/match-folders';\nimport { resolveProjectRoot } from './lib/project-root';\nimport { findAuthLocalNames, hasProtectAtTop } from './lib/protection-checks';\n\nexport type MessageId =\n | 'missingProtect'\n | 'addAuthProtect'\n | 'exportImported'\n | 'unverifiableExport'\n | 'unlistedMixedScopeLayout';\n\ninterface ResourceOptions {\n /** Route handler files, such as `route.ts`. */\n routeHandlers?: boolean;\n /** Module-level and inline Server Functions using `'use server'`. */\n serverFunctions?: boolean;\n /** Server Component entrypoints, such as `page.tsx`, `layout.tsx`, `template.tsx`, and `default.tsx`. */\n serverComponentEntrypoints?: boolean;\n}\n\ntype NormalizedResourceOptions = Required<ResourceOptions>;\n\nexport interface RuleOptions {\n /** Glob patterns that mark folders as protected. */\n protected: string[];\n /** Glob patterns that exempt folders from protection. */\n public?: string[];\n /** Resource groups that should be checked. All resource groups are checked by default. */\n resources?: ResourceOptions;\n /** Layouts that wrap both protected and public descendants. */\n mixedScopeLayouts?: 'auto' | string[];\n /**\n * Directory paths are relativized against when resolving `app/...` folder\n * globs. Defaults to the nearest ancestor `eslint.config.*` (same walk ESLint\n * uses for config lookup), then ESLint `cwd`. Set to `import.meta.dirname` in\n * your `eslint.config.mjs` when config discovery is unavailable.\n */\n rootDir?: string;\n}\n\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD']);\n\nconst DEFAULT_RESOURCES: NormalizedResourceOptions = {\n routeHandlers: true,\n serverFunctions: true,\n serverComponentEntrypoints: true,\n};\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n hasSuggestions: true,\n docs: {\n description: 'Require `await auth.protect()` in App Router resources under protected folders',\n },\n schema: [\n {\n type: 'object',\n properties: {\n protected: {\n type: 'array',\n items: { type: 'string' },\n minItems: 1,\n },\n public: { type: 'array', items: { type: 'string' } },\n resources: {\n type: 'object',\n properties: {\n routeHandlers: { type: 'boolean' },\n serverFunctions: { type: 'boolean' },\n serverComponentEntrypoints: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n mixedScopeLayouts: {\n oneOf: [\n { type: 'string', enum: ['auto'] },\n { type: 'array', items: { type: 'string' } },\n ],\n },\n rootDir: { type: 'string' },\n },\n required: ['protected'],\n additionalProperties: false,\n },\n ],\n messages: {\n missingProtect:\n 'Expected `await auth.protect()` at the top of {{subject}} in a folder configured as protected. Add the call to the top of the function, move the file into a public folder, or configure this folder as public.',\n addAuthProtect: 'Add `await auth.protect()` to the top of this {{subject}}.',\n exportImported:\n \"This {{subject}} is exported from '{{source}}'. The rule cannot follow imports across files. Add a wrapper with `await auth.protect()`, or ensure the imported function calls it and add an eslint-disable comment with a reason.\",\n unverifiableExport:\n 'This {{subject}} could not be verified as being protected, likely because it is assigned from a call expression (e.g. `const handler = withAuth(impl)`). Inline a function literal that calls `await auth.protect()`, or add an eslint-disable comment with a reason.',\n unlistedMixedScopeLayout:\n \"This {{fileKind}} at '{{folder}}/' wraps both protected and public descendants but is not listed in `mixedScopeLayouts`. Either add '{{folder}}' to the list to acknowledge the mixed scope, or restructure so the {{fileKind}} wraps only public or protected descendants.\",\n },\n },\n\n create(context) {\n const filename = context.physicalFilename ?? context.filename ?? context.getFilename?.();\n const cwd = context.cwd || context.getCwd?.();\n const options = (context.options[0] ?? {}) as Partial<RuleOptions>;\n const config: ClassifyOptions = {\n protected: options.protected,\n public: options.public ?? [],\n };\n const resources = normalizeResources(options.resources);\n const mixedScopeLayoutsOption = options.mixedScopeLayouts === undefined ? 'auto' : options.mixedScopeLayouts;\n\n const projectRoot = resolveProjectRoot(filename, { rootDir: options.rootDir, cwd });\n const folder = getRelativeFolder(filename, projectRoot);\n if (!folder) {\n return {};\n }\n\n const fileKind = getFileKind(filename);\n\n let authNames = new Set<string>();\n let shouldCheckInlineServerFunctions = false;\n // Keeps track of which functions have already been checked to avoid\n // program visitor and function visitors performing duplicate checks.\n const checkedFunctions = new WeakSet<FunctionNode>();\n\n return {\n Program(programNode) {\n const ast = programNode as TSESTree.Program;\n const isServerFunction = isServerFunctionModule(ast);\n const isClient = isClientModule(ast);\n\n const sourceClass = classifyFolder(folder, config);\n if (sourceClass !== 'protected') {\n return;\n }\n\n // This needs to be before the other bailouts. It sets up state\n // necessary for the independent function visitors to work.\n authNames = findAuthLocalNames(ast);\n shouldCheckInlineServerFunctions = resources.serverFunctions && !isClient;\n\n if (!fileKind && !isServerFunction) {\n return;\n }\n\n if (\n isClient &&\n (fileKind === 'page' || fileKind === 'layout' || fileKind === 'template' || fileKind === 'default')\n ) {\n return;\n }\n\n if (\n resources.serverComponentEntrypoints &&\n (fileKind === 'layout' || fileKind === 'template') &&\n hasDescendantsMatching(folder, config.public)\n ) {\n checkUnacknowledgedMixedScope(context, ast, fileKind, folder, mixedScopeLayoutsOption);\n return;\n }\n\n if (\n resources.serverComponentEntrypoints &&\n (fileKind === 'page' || fileKind === 'layout' || fileKind === 'template' || fileKind === 'default')\n ) {\n checkDefaultExport(context, ast, fileKind, authNames, checkedFunctions);\n } else if (resources.routeHandlers && fileKind === 'route') {\n checkRouteHandlers(context, ast, authNames, checkedFunctions);\n } else if (resources.serverFunctions && isServerFunction) {\n checkServerFunctions(context, ast, authNames, checkedFunctions);\n }\n },\n FunctionDeclaration(node) {\n checkInlineServerFunction(\n context,\n node as TSESTree.FunctionDeclaration,\n authNames,\n shouldCheckInlineServerFunctions,\n checkedFunctions,\n );\n },\n FunctionExpression(node) {\n checkInlineServerFunction(\n context,\n node as TSESTree.FunctionExpression,\n authNames,\n shouldCheckInlineServerFunctions,\n checkedFunctions,\n );\n },\n ArrowFunctionExpression(node) {\n checkInlineServerFunction(\n context,\n node as TSESTree.ArrowFunctionExpression,\n authNames,\n shouldCheckInlineServerFunctions,\n checkedFunctions,\n );\n },\n };\n },\n};\n\nexport default rule;\n\nfunction normalizeResources(resources: ResourceOptions | undefined): NormalizedResourceOptions {\n return { ...DEFAULT_RESOURCES, ...resources };\n}\n\nfunction checkUnacknowledgedMixedScope(\n context: Rule.RuleContext,\n programNode: TSESTree.Program,\n fileKind: 'layout' | 'template',\n folder: string,\n mixedScopeLayoutsOption: 'auto' | string[],\n): void {\n if (mixedScopeLayoutsOption === 'auto') {\n return;\n }\n if (mixedScopeLayoutsOption.includes(folder)) {\n return;\n }\n const defaultExport = programNode.body.find(\n (n): n is TSESTree.ExportDefaultDeclaration => n.type === 'ExportDefaultDeclaration',\n );\n context.report({\n node: defaultExport ?? programNode,\n messageId: 'unlistedMixedScopeLayout',\n data: { folder, fileKind },\n });\n}\n\nfunction getMissingProtectReportNode(fn: FunctionNode, fallback: TSESTree.Node): TSESTree.Node {\n return fn.id ?? fn.body ?? fallback;\n}\n\nfunction checkMissingProtect(\n context: Rule.RuleContext,\n reportNode: TSESTree.Node,\n target: ExportTarget,\n subject: string,\n authNames: Set<string>,\n checkedFunctions?: WeakSet<FunctionNode>,\n): void {\n if (target.kind === 'imported') {\n context.report({\n node: reportNode,\n messageId: 'exportImported',\n data: { subject, source: target.source },\n });\n return;\n }\n if (target.kind === 'function') {\n checkedFunctions?.add(target.node);\n if (!hasProtectAtTop(target.node, authNames)) {\n context.report({\n node: getMissingProtectReportNode(target.node, reportNode),\n messageId: 'missingProtect',\n data: { subject },\n suggest: buildAddAuthProtectSuggestion(context, target.node, subject, authNames),\n });\n }\n return;\n }\n context.report({\n node: reportNode,\n messageId: 'unverifiableExport',\n data: { subject },\n });\n}\n\nfunction checkRouteHandlers(\n context: Rule.RuleContext,\n programNode: TSESTree.Program,\n authNames: Set<string>,\n checkedFunctions: WeakSet<FunctionNode>,\n): void {\n for (const { name, target, reportNode } of iterateNamedExports(programNode)) {\n if (!HTTP_METHODS.has(name)) {\n continue;\n }\n checkMissingProtect(context, reportNode, target, `${name} handler`, authNames, checkedFunctions);\n }\n // `export *` could re-export an HTTP-method handler we can't see across files\n for (const { source, reportNode } of iterateExportAllDeclarations(programNode)) {\n checkMissingProtect(context, reportNode, { kind: 'imported', source }, 'route handlers', authNames);\n }\n}\n\nfunction checkServerFunctions(\n context: Rule.RuleContext,\n programNode: TSESTree.Program,\n authNames: Set<string>,\n checkedFunctions: WeakSet<FunctionNode>,\n): void {\n for (const { name, target, reportNode } of iterateNamedExports(programNode)) {\n if (name === 'default') {\n continue;\n }\n checkMissingProtect(context, reportNode, target, `Server Function '${name}'`, authNames, checkedFunctions);\n }\n const defaultExport = resolveDefaultExport(programNode);\n if (defaultExport) {\n checkMissingProtect(\n context,\n defaultExport.reportNode,\n defaultExport.target,\n 'Server Function',\n authNames,\n checkedFunctions,\n );\n }\n // `export *` can re-export Server Functions we can't see across files.\n for (const { source, reportNode } of iterateExportAllDeclarations(programNode)) {\n checkMissingProtect(context, reportNode, { kind: 'imported', source }, 'Server Functions', authNames);\n }\n}\n\nfunction checkDefaultExport(\n context: Rule.RuleContext,\n programNode: TSESTree.Program,\n fileKind: FileKind,\n authNames: Set<string>,\n checkedFunctions: WeakSet<FunctionNode>,\n): void {\n const defaultExport = resolveDefaultExport(programNode);\n if (!defaultExport) {\n return;\n }\n\n checkMissingProtect(context, defaultExport.reportNode, defaultExport.target, fileKind, authNames, checkedFunctions);\n}\n\nfunction hasUseServerDirective(fn: FunctionNode): boolean {\n const body = fn.body;\n if (!body || body.type !== 'BlockStatement') {\n return false;\n }\n\n for (const stmt of body.body) {\n if (stmt.type !== 'ExpressionStatement') {\n return false;\n }\n if (typeof stmt.directive !== 'string') {\n return false;\n }\n if (stmt.directive === 'use server') {\n return true;\n }\n }\n return false;\n}\n\nfunction checkInlineServerFunction(\n context: Rule.RuleContext,\n fn: FunctionNode,\n authNames: Set<string>,\n shouldCheckInlineServerFunctions: boolean,\n checkedFunctions: WeakSet<FunctionNode>,\n): void {\n if (!shouldCheckInlineServerFunctions || checkedFunctions.has(fn) || !hasUseServerDirective(fn)) {\n return;\n }\n if (!hasProtectAtTop(fn, authNames)) {\n context.report({\n node: getMissingProtectReportNode(fn, fn),\n messageId: 'missingProtect',\n data: { subject: 'Inline Server Function' },\n suggest: buildAddAuthProtectSuggestion(context, fn, 'Inline Server Function', authNames),\n });\n }\n}\n\nfunction buildAddAuthProtectSuggestion(\n context: Rule.RuleContext,\n fn: FunctionNode,\n subject: string,\n authNames: Set<string>,\n): Rule.SuggestionReportDescriptor[] {\n const sourceCode = context.sourceCode;\n return [\n {\n messageId: 'addAuthProtect',\n data: { subject },\n fix(fixer) {\n return buildAuthProtectFixes({\n fixer: fixer as unknown as TSESLint.RuleFixer,\n sourceCode: sourceCode as unknown as TSESLint.SourceCode,\n fn,\n authNames,\n }) as unknown as Rule.Fix[];\n },\n },\n ];\n}\n","import type { ESLint } from 'eslint';\n\nimport requireAuthProtection from './require-auth-protection';\n\nconst plugin: ESLint.Plugin = {\n meta: {\n name: '@clerk/eslint-plugin/next',\n version: PACKAGE_VERSION,\n },\n rules: {\n 'require-auth-protection': requireAuthProtection,\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|