@sarj/eslint-plugin 2.3.2 → 2.3.3

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rules/enforce-file-structure.ts","../src/rules/no-client-side-data-fetching.ts","../src/rules/no-comment-cruft.ts","../src/rules/no-enum.ts","../src/rules/no-insecure-random-id.ts","../src/rules/no-json-stringify-error.ts","../src/rules/no-log-only-catch.ts","../src/rules/no-raw-env.ts","../src/rules/no-sentinel-return-on-catch.ts","../src/rules/no-sequential-await.ts","../src/rules/no-string-concat-in-loop.ts","../src/rules/no-unnecessary-use-client.ts","../src/rules/prefer-discriminated-union.ts","../src/rules/prefer-schema-for-api-payload.ts","../src/rules/prefer-semantic-colors.ts","../src/rules/_tailwind.ts","../src/rules/prefer-server-actions.ts","../src/rules/prefer-shadcn.ts","../src/rules/require-assert-never.ts","../src/rules/require-zod-form-validation.ts","../src/rules/zod-naming-convention.ts","../src/rules/no-cors-wildcard-with-credentials.ts","../src/rules/no-fat-try-blocks.ts","../src/rules/no-secret-in-log.ts","../src/rules/prefer-string-literal-union.ts","../src/rules/single-public-export.ts","../src/index.ts"],"sourcesContent":["import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"incorrectOrder\" | \"useServerDirective\";\ntype Options = readonly [];\n\n/**\n * Section ordinals — lower numbers must appear before higher numbers.\n *\n * Per the stepdown rule (see `plugins/sarj-audit/commands/stepdown.md`), only\n * *function* ordering is a violation. Top-level imports, type aliases,\n * interfaces, enums, classes, and value constants are all \"declarations\" and\n * belong together at the top in any order — so they share a single ordinal and\n * are never flagged relative to one another.\n */\nconst SECTION = {\n declarations: 0,\n functions: 1,\n exports: 2,\n} as const;\n\nconst SECTION_NAMES = [\"declarations\", \"functions\", \"exports\"] as const;\n\ntype SectionOrdinal = (typeof SECTION)[keyof typeof SECTION];\n\nconst sectionName = (ordinal: SectionOrdinal): string => {\n const name = SECTION_NAMES[ordinal];\n // SECTION_NAMES is indexed by SectionOrdinal (0..2) — always defined, but\n // noUncheckedIndexedAccess widens to `string | undefined`, so fall back.\n return name ?? \"unknown\";\n};\n\n// Server-action files: anchored to an `/actions/` path segment, a `*.action.ts`\n// filename, or a bare `actions.ts` file. Substrings like `transaction-service`\n// or `redaction.ts` deliberately do NOT match.\nconst SERVER_ACTION_FILE_RE =\n /(?:^|\\/)actions\\/|\\.action\\.[jt]sx?$|(?:^|\\/)actions\\.[jt]sx?$/;\n\nconst isFunctionExpression = (node: TSESTree.Expression): boolean =>\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.FunctionExpression;\n\n/**\n * A `const/let/var` declaration counts as a *function* when every declarator is\n * initialized with a function/arrow expression (`const helper = () => {}`).\n * A value const (`const x = 1`, `const MAX = 5`) is a declaration, not a\n * function — it must not be mis-bucketed.\n */\nconst isFunctionLikeVariable = (\n statement: TSESTree.VariableDeclaration,\n): boolean =>\n statement.declarations.length > 0 &&\n statement.declarations.every(\n (decl) => decl.init !== null && isFunctionExpression(decl.init),\n );\n\nconst getStatementSection = (\n statement: TSESTree.ProgramStatement,\n): SectionOrdinal => {\n switch (statement.type) {\n case AST_NODE_TYPES.ImportDeclaration:\n case AST_NODE_TYPES.TSTypeAliasDeclaration:\n case AST_NODE_TYPES.TSInterfaceDeclaration:\n case AST_NODE_TYPES.TSEnumDeclaration:\n case AST_NODE_TYPES.ClassDeclaration:\n return SECTION.declarations;\n case AST_NODE_TYPES.VariableDeclaration:\n return isFunctionLikeVariable(statement)\n ? SECTION.functions\n : SECTION.declarations;\n case AST_NODE_TYPES.FunctionDeclaration:\n return SECTION.functions;\n case AST_NODE_TYPES.ExportNamedDeclaration:\n case AST_NODE_TYPES.ExportDefaultDeclaration:\n case AST_NODE_TYPES.ExportAllDeclaration:\n return SECTION.exports;\n default:\n // Executable top-level statements group with functions.\n return SECTION.functions;\n }\n};\n\nconst isUseServerDirective = (\n statement: TSESTree.ProgramStatement | undefined,\n): boolean => {\n if (statement === undefined) return false;\n if (statement.type !== AST_NODE_TYPES.ExpressionStatement) return false;\n const expr = statement.expression;\n if (expr.type !== AST_NODE_TYPES.Literal) return false;\n return expr.value === \"use server\";\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"enforce-file-structure\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce that function definitions follow the file's top-of-file declarations (imports, types, constants, classes) — the stepdown rule. Ordering among non-function declarations is not enforced. Server-action files (under `/actions/`, named `*.action.ts`, or `actions.ts`) must also begin with a `use server` directive.\",\n },\n schema: [],\n messages: {\n incorrectOrder:\n \"File structure violation: {{current}} should come before {{expected}}\",\n useServerDirective:\n \"Server action files must start with 'use server' directive\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n const isServerAction = SERVER_ACTION_FILE_RE.test(filename);\n\n return {\n Program(node: TSESTree.Program): void {\n const body = node.body;\n\n if (isServerAction) {\n const firstNode = body[0];\n if (!isUseServerDirective(firstNode)) {\n context.report({\n node,\n messageId: \"useServerDirective\",\n });\n }\n }\n\n let currentSection: SectionOrdinal = SECTION.declarations;\n\n for (const statement of body) {\n // Skip top-of-file string directives ('use server', 'use client',\n // 'use strict', ...) so they don't get classified as a section.\n if (\n statement.type === AST_NODE_TYPES.ExpressionStatement &&\n statement.expression.type === AST_NODE_TYPES.Literal &&\n typeof statement.expression.value === \"string\" &&\n statement.expression.value.startsWith(\"use \")\n ) {\n continue;\n }\n\n const statementSection = getStatementSection(statement);\n\n if (statementSection < currentSection) {\n context.report({\n node: statement,\n messageId: \"incorrectOrder\",\n data: {\n current: sectionName(statementSection),\n expected: sectionName(currentSection),\n },\n });\n } else if (statementSection > currentSection) {\n currentSection = statementSection;\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow data fetching inside `useEffect` / `useLayoutEffect`.\n *\n * Anti-pattern:\n *\n * useEffect(() => { fetch('/data').then(setData); }, []);\n *\n * Causes a client-side waterfall (render → effect → fetch → re-render),\n * forfeits server-side caching, and produces layout shift. In Next.js App\n * Router, prefer:\n * - a React Server Component that fetches at render time, or\n * - a Server Action invoked from a form / onClick handler, or\n * - client-side caching libraries like SWR or React Query.\n *\n * Detection covers:\n * - `fetch(...)` (default + when explicit `method: \"GET\"`)\n * - `axios.<method>(...)` for actual HTTP verbs only:\n * get / post / put / delete / patch / request / head / options\n * (i.e. NOT `axios.create` / `axios.defaults`)\n * - `ky.<method>(...)` / `superagent.<method>(...)` (same verbs)\n * - bare `axios(...)` / `ky(...)` calls (when treated as a GET)\n *\n * Analytics / telemetry endpoints whose URL has a whole path segment of\n * `track` / `log` / `ping` / `event` / ... are intentionally exempt because\n * they aren't render-blocking data fetches. (Matched per-segment, so\n * `/api/login`, `/blog`, `/api/events`, `/catalog`, `/api/shipping` are NOT\n * exempt.)\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/data-fetching\n * - https://react.dev/reference/react/useEffect#fetching-data-with-effects\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noClientFetch\";\ntype Options = readonly [];\n\nconst FETCH_LIBS: ReadonlySet<string> = new Set([\"axios\", \"ky\", \"superagent\"]);\n\n// Real HTTP verbs only. Explicitly excludes `create`, `defaults`,\n// `interceptors`, `isAxiosError`, etc.\nconst HTTP_METHOD_NAMES: ReadonlySet<string> = new Set([\n \"get\",\n \"post\",\n \"put\",\n \"delete\",\n \"patch\",\n \"request\",\n \"head\",\n \"options\",\n]);\n\n// Matched against whole path SEGMENTS (split on `/` and `.`), never as raw\n// substrings — otherwise `/api/login` (\"log\"), `/blog` (\"log\"), `/api/events`\n// (\"event\"), `/catalog` (\"log\"), and `/api/shipping` (\"ping\") would be wrongly\n// exempted.\nconst ANALYTICS_SEGMENTS: ReadonlySet<string> = new Set([\n \"analytics\",\n \"telemetry\",\n \"track\",\n \"log\",\n \"ping\",\n \"beacon\",\n \"metrics\",\n \"event\",\n]);\n\nfunction isEffectHookCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n\n // useEffect(...) / useLayoutEffect(...)\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name === \"useEffect\" || callee.name === \"useLayoutEffect\";\n }\n\n // React.useEffect(...) / React.useLayoutEffect(...)\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.object.type === AST_NODE_TYPES.Identifier &&\n callee.object.name === \"React\" &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return (\n callee.property.name === \"useEffect\" ||\n callee.property.name === \"useLayoutEffect\"\n );\n }\n\n return false;\n}\n\n/**\n * Reads the `method` property of an options object passed to `fetch` / `axios`.\n * Returns the uppercased method name, or `null` if not statically determinable.\n */\nfunction readMethodProperty(\n optionsArg: TSESTree.Node | undefined,\n): string | null {\n if (!optionsArg || optionsArg.type !== AST_NODE_TYPES.ObjectExpression) {\n return null;\n }\n for (const prop of optionsArg.properties) {\n if (prop.type !== AST_NODE_TYPES.Property) continue;\n if (prop.computed) continue;\n const key = prop.key;\n const matchesMethodKey =\n (key.type === AST_NODE_TYPES.Identifier && key.name === \"method\") ||\n (key.type === AST_NODE_TYPES.Literal && key.value === \"method\");\n if (!matchesMethodKey) continue;\n if (\n prop.value.type === AST_NODE_TYPES.Literal &&\n typeof prop.value.value === \"string\"\n ) {\n return prop.value.value.toUpperCase();\n }\n return null;\n }\n return null;\n}\n\nfunction isFetchCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n\n // fetch(url, options?)\n if (\n callee.type === AST_NODE_TYPES.Identifier &&\n callee.name === \"fetch\"\n ) {\n const method = readMethodProperty(node.arguments[1]);\n if (method !== null && method !== \"GET\") {\n return false;\n }\n return true;\n }\n\n // axios.get(...), ky.post(...), superagent.delete(...), ...\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.object.type === AST_NODE_TYPES.Identifier &&\n FETCH_LIBS.has(callee.object.name) &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n // Only flag actual HTTP method calls — NOT `axios.create`, `axios.defaults`,\n // `axios.interceptors`, `axios.isAxiosError`, etc.\n return HTTP_METHOD_NAMES.has(callee.property.name);\n }\n\n // axios(config) / ky(config) — treat as request unless method is explicitly non-GET.\n if (\n callee.type === AST_NODE_TYPES.Identifier &&\n (callee.name === \"axios\" || callee.name === \"ky\")\n ) {\n const firstArg = node.arguments[0];\n const secondArg = node.arguments[1];\n let configArg: TSESTree.Node | undefined;\n if (firstArg?.type === AST_NODE_TYPES.ObjectExpression) {\n configArg = firstArg;\n } else if (secondArg?.type === AST_NODE_TYPES.ObjectExpression) {\n configArg = secondArg;\n }\n const method = readMethodProperty(configArg);\n if (method !== null && method !== \"GET\") {\n return false;\n }\n return true;\n }\n\n return false;\n}\n\nfunction extractUrlString(node: TSESTree.CallExpression): string {\n const firstArg = node.arguments[0];\n if (!firstArg) return \"\";\n\n if (\n firstArg.type === AST_NODE_TYPES.Literal &&\n typeof firstArg.value === \"string\"\n ) {\n return firstArg.value;\n }\n if (firstArg.type === AST_NODE_TYPES.TemplateLiteral) {\n return firstArg.quasis.map((q) => q.value.cooked).join(\"\");\n }\n if (firstArg.type === AST_NODE_TYPES.Identifier) {\n return firstArg.name;\n }\n return \"\";\n}\n\nfunction isAnalyticsCall(node: TSESTree.CallExpression): boolean {\n const url = extractUrlString(node).toLowerCase();\n if (url === \"\") return false;\n // Split into path segments and file-extension parts; exempt only when a\n // WHOLE segment is a known analytics keyword.\n return url\n .split(/[/.]/)\n .some((segment) => ANALYTICS_SEGMENTS.has(segment));\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-client-side-data-fetching\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow data fetching inside `useEffect` / `useLayoutEffect`; prefer React Server Components, Server Actions, or a client-side cache (SWR / React Query).\",\n },\n schema: [],\n messages: {\n noClientFetch:\n \"Avoid direct data fetching inside useEffect / useLayoutEffect. This causes waterfalls and layout shifts. Prefer React Server Components, Server Actions, or client-side caching libraries like SWR or React Query.\",\n },\n },\n defaultOptions: [],\n create(context) {\n let effectDepth = 0;\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (isEffectHookCall(node)) {\n effectDepth += 1;\n return;\n }\n if (effectDepth === 0) return;\n if (!isFetchCall(node)) return;\n if (isAnalyticsCall(node)) return;\n context.report({ node, messageId: \"noClientFetch\" });\n },\n \"CallExpression:exit\"(node: TSESTree.CallExpression): void {\n if (isEffectHookCall(node)) {\n effectDepth -= 1;\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag comment cruft — commented-out code, section banners, and\n * leading file-header comment preambles. Code carries the *what*; comments are\n * reserved for the *why*. The fuzzier \"this comment merely restates the code\"\n * judgment stays in review, not this rule — only these deterministic shapes are\n * flagged. JSDoc (`/** ... *\\/`) is never flagged, and directive comments\n * (`eslint-`, `@ts-`, `prettier-`, `biome-`, `c8`, `<reference`, `TODO`,\n * `FIXME`) are ignored.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"commentedOutCode\" | \"sectionBanner\" | \"fileHeaderPreamble\";\ntype Options = readonly [];\n\nconst LEADING_PREAMBLE_MIN = 4;\n\nconst DIRECTIVE_RE =\n /^(eslint\\b|eslint-|@ts-|prettier-ignore|prettier\\b|biome-|c8\\b|v8\\b|istanbul\\b|@type\\b|@vite|webpack|<reference|global\\b|noinspection|todo\\b|fixme\\b|hack\\b|xxx\\b)/i;\n\nconst LICENSE_RE =\n /copyright|licen[cs]ed?|spdx|permission is hereby granted|all rights reserved/i;\n\nconst BANNER_FULL_RE = /^[\\s\\-=*#~_+.]{4,}$/;\n// `={4,}` not `={3,}`: `===` is TS strict-equality and appears in prose comments.\nconst BANNER_RUN_RE = /={4,}|-{4,}|#{4,}|\\*{4,}|~{4,}/;\nconst REGION_RE = /^#?(?:end)?region\\b/i;\n\nconst CODE_KEYWORD_RE =\n /^(import |export |const |let |var |function\\b|class |interface |type \\w|enum |return\\b|throw |await |async |if\\s*\\(|for\\s*\\(|while\\s*\\(|switch\\s*\\(|new |console\\.)/;\nconst CODE_TAIL_RE = /[;{}()]\\s*$|=>\\s*$|,\\s*$/;\n// LHS must be a real identifier (not a number literal — `0=Monday` in prose is\n// not an assignment) and `=` must not be `==`/`===`/`=>` (comparison/arrow).\n// The assignment branch additionally requires a code-tail — the line must end\n// with `;`, `)`, `}` or `]` — so plain prose like `count = number of items`\n// (which has no code-tail) is not mistaken for commented-out code.\nconst CALL_OR_ASSIGN_RE =\n /^[A-Za-z_$][\\w.$[\\]]*\\s*(?:=(?![=>])|\\+=|-=|\\*=)\\s*\\S.*[;)}\\]]\\s*$|^[A-Za-z_$][\\w.$]*\\([^)]*\\)\\s*;?\\s*$/;\n\nfunction stripCommentMarker(line: string): string {\n return line.replace(/^\\s*\\/\\//, \"\").replace(/^\\s*\\*+/, \"\").trim();\n}\n\nfunction isDirective(text: string): boolean {\n return DIRECTIVE_RE.test(text.trim());\n}\n\nfunction isBanner(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return BANNER_FULL_RE.test(t) || BANNER_RUN_RE.test(t) || REGION_RE.test(t);\n}\n\nfunction looksLikeCode(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n if (CODE_KEYWORD_RE.test(t) && CODE_TAIL_RE.test(t)) return true;\n return CALL_OR_ASSIGN_RE.test(t);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-comment-cruft\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag commented-out code, section-banner comments, and leading file-header comment preambles.\",\n },\n schema: [],\n messages: {\n commentedOutCode:\n \"Commented-out code — delete it; git history remembers.\",\n sectionBanner:\n \"Section-banner / region comment — structure code with functions, not ASCII rules.\",\n fileHeaderPreamble:\n \"File-header comment preamble — use a brief doc comment for the why, not a block of `//` lines.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const sourceCode = context.sourceCode;\n\n function isStandalone(comment: TSESTree.Comment): boolean {\n const before = sourceCode.getTokenBefore(comment, {\n includeComments: false,\n });\n return !before || before.loc.end.line < comment.loc.start.line;\n }\n\n function isJsDoc(comment: TSESTree.Comment): boolean {\n return comment.type === \"Block\" && /^\\*/.test(comment.value);\n }\n\n function reportLeadingPreamble(\n comments: readonly TSESTree.Comment[],\n firstCodeLine: number,\n ): void {\n const leading: TSESTree.Comment[] = [];\n let prevLine: number | null = null;\n for (const comment of comments) {\n if (comment.type !== \"Line\") break;\n if (comment.loc.start.line >= firstCodeLine) break;\n if (!isStandalone(comment)) break;\n const body = stripCommentMarker(comment.value);\n if (isDirective(body) || body.startsWith(\"!\")) continue;\n if (prevLine !== null && comment.loc.start.line !== prevLine + 1) break;\n leading.push(comment);\n prevLine = comment.loc.start.line;\n }\n const first = leading[0];\n if (first === undefined || leading.length < LEADING_PREAMBLE_MIN) return;\n const isLicense = leading.some((c) =>\n LICENSE_RE.test(stripCommentMarker(c.value)),\n );\n if (!isLicense) {\n context.report({ node: first, messageId: \"fileHeaderPreamble\" });\n }\n }\n\n return {\n Program(): void {\n const comments = sourceCode.getAllComments();\n const firstCodeLine =\n sourceCode.ast.tokens[0]?.loc.start.line ?? Number.MAX_SAFE_INTEGER;\n\n for (const comment of comments) {\n if (isJsDoc(comment) || !isStandalone(comment)) continue;\n const texts = comment.value\n .split(\"\\n\")\n .map(stripCommentMarker)\n .filter((l) => l.length > 0 && !isDirective(l));\n if (texts.some(isBanner)) {\n context.report({ node: comment, messageId: \"sectionBanner\" });\n } else if (texts.some(looksLikeCode)) {\n context.report({ node: comment, messageId: \"commentedOutCode\" });\n }\n }\n\n reportLeadingPreamble(comments, firstCodeLine);\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow TypeScript `enum` declarations. Use string-literal\n * union types (e.g. `type Status = \"active\" | \"inactive\"`) or `as const`\n * objects instead — enums generate runtime code, have unintuitive numeric\n * defaults, and don't tree-shake cleanly.\n *\n * Generated files can opt out either by living under a path matched by\n * `ignoreFiles` (default: `**\\/generated/**`, `**\\/*.gen.ts`, `**\\/*.generated.ts`)\n * or by including a `@generated` marker comment near the top of the file.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noEnum\";\ntype Options = readonly [\n {\n ignoreFiles?: readonly string[];\n }?,\n];\n\nconst DEFAULT_IGNORE_PATTERNS: readonly RegExp[] = [\n /[\\\\/]generated[\\\\/]/,\n /\\.gen\\.tsx?$/,\n /\\.generated\\.tsx?$/,\n];\n\nfunction matchesAnyPattern(\n filename: string,\n patterns: readonly string[],\n): boolean {\n for (const pattern of patterns) {\n // Convert minimatch-ish globs to regex: ** -> .*, * -> [^/\\\\]*\n const regexSource = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"::DOUBLESTAR::\")\n .replace(/\\*/g, \"[^/\\\\\\\\]*\")\n .replace(/::DOUBLESTAR::/g, \".*\");\n if (new RegExp(`^${regexSource}$`).test(filename)) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasGeneratedMarker(sourceText: string): boolean {\n // Look only in the first 1KB to keep this cheap.\n const head = sourceText.slice(0, 1024);\n return /@generated\\b/.test(head);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-enum\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow TypeScript `enum`; use string-literal unions or `as const` objects instead.\",\n },\n schema: [\n {\n type: \"object\",\n additionalProperties: false,\n properties: {\n ignoreFiles: {\n type: \"array\",\n items: { type: \"string\" },\n },\n },\n },\n ],\n messages: {\n noEnum:\n 'Enums are discouraged. Use a string-literal union (e.g. `type Status = \"active\" | \"inactive\"`) or an `as const` object instead.',\n },\n },\n defaultOptions: [{}],\n create(context, [optionsArg]) {\n const options = optionsArg ?? {};\n const ignoreFiles = options.ignoreFiles ?? [];\n const filename = context.filename;\n const sourceText = context.sourceCode.getText();\n\n const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS.some((re) =>\n re.test(filename),\n );\n const isIgnoredByOption =\n ignoreFiles.length > 0 && matchesAnyPattern(filename, ignoreFiles);\n const isGenerated = hasGeneratedMarker(sourceText);\n\n if (isIgnoredByDefault || isIgnoredByOption || isGenerated) {\n return {};\n }\n\n return {\n TSEnumDeclaration(node: TSESTree.TSEnumDeclaration): void {\n context.report({\n node,\n messageId: \"noEnum\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow using `Math.random()` to generate identifiers,\n * tokens, keys, or other security-sensitive values. `Math.random()` is not\n * cryptographically secure and is predictable — using it for IDs/tokens/secrets\n * can lead to collisions and trivially guessable values. Prefer\n * `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\n *\n * The rule is intentionally conservative and only flags two precise patterns:\n * 1. A `Math.random()` result fed into a `.toString(36)` chain — the classic\n * insecure random-id idiom (e.g. `Math.random().toString(36).slice(2)`).\n * 2. A `Math.random()` call whose nearest enclosing binding or property NAME\n * looks identifier/secret-like (matches `/id|token|key|secret|uuid|nonce|\n * session|password|salt/i`).\n *\n * Bare `Math.random()` used for non-identifier purposes (jitter, sampling,\n * rolls, etc.) is NOT flagged.\n *\n * KNOWN GAP (false-negative): an arithmetic expression between `Math.random()`\n * and `.toString(36)` breaks the member-chain walk, e.g.\n * `(Math.random() * 1e9).toString(36)`. The intervening `BinaryExpression`\n * means `Math.random()` is no longer the object end of the `.toString` chain,\n * so trigger 1 does not fire. Such code is only caught if its binding/property\n * name looks identifier/secret-like (trigger 2). See the documented test case.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"insecureRandomId\";\ntype Options = readonly [];\n\nconst NAME_PATTERN = /id|token|key|secret|uuid|nonce|session|password|salt/i;\n\n/**\n * Returns true if `node` is a `Math.random()` CallExpression.\n */\nfunction isMathRandomCall(node: TSESTree.Node): node is TSESTree.CallExpression {\n if (node.type !== \"CallExpression\") {\n return false;\n }\n const callee = node.callee;\n if (callee.type !== \"MemberExpression\" || callee.computed) {\n return false;\n }\n const { object, property } = callee;\n return (\n object.type === \"Identifier\" &&\n object.name === \"Math\" &&\n property.type === \"Identifier\" &&\n property.name === \"random\"\n );\n}\n\n/**\n * Returns true if `node` (a `Math.random()` call) is the base of a member\n * chain that calls `.toString(36)` somewhere above it, e.g.\n * `Math.random().toString(36)` or `Math.random().toString(36).slice(2)`.\n */\nfunction isPartOfToString36Chain(node: TSESTree.Node): boolean {\n let current: TSESTree.Node = node;\n let parent = current.parent;\n\n while (parent) {\n if (\n parent.type === \"MemberExpression\" &&\n parent.object === current &&\n !parent.computed &&\n parent.property.type === \"Identifier\" &&\n parent.property.name === \"toString\"\n ) {\n // The MemberExpression `<current>.toString` should be called with a\n // radix argument of `36`.\n const grandparent = parent.parent;\n if (\n grandparent &&\n grandparent.type === \"CallExpression\" &&\n grandparent.callee === parent\n ) {\n const firstArg = grandparent.arguments[0];\n if (\n firstArg &&\n firstArg.type === \"Literal\" &&\n firstArg.value === 36\n ) {\n return true;\n }\n }\n }\n\n // Keep walking up only while we remain the \"object\" of a member/call\n // chain. If we are anything other than the object end of the chain, the\n // `.toString(36)` (if any) does not apply to this `Math.random()`.\n if (\n parent.type === \"MemberExpression\" &&\n parent.object === current\n ) {\n current = parent;\n parent = current.parent;\n continue;\n }\n if (parent.type === \"CallExpression\" && parent.callee === current) {\n current = parent;\n parent = current.parent;\n continue;\n }\n break;\n }\n\n return false;\n}\n\n/**\n * Walks up from `node` to find the name of the nearest enclosing binding\n * (VariableDeclarator id) or property (Property / PropertyDefinition key),\n * and returns it. Returns `undefined` if no such name is found before leaving\n * the enclosing initializer/value context.\n */\nfunction findEnclosingName(node: TSESTree.Node): string | undefined {\n let current: TSESTree.Node = node;\n let parent = current.parent;\n\n while (parent) {\n // const sessionToken = Math.random()...\n if (parent.type === \"VariableDeclarator\" && parent.init === current) {\n if (parent.id.type === \"Identifier\") {\n return parent.id.name;\n }\n return undefined;\n }\n\n // { sessionToken: Math.random()... }\n if (parent.type === \"Property\" && parent.value === current) {\n const key = parent.key;\n if (!parent.computed && key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n }\n\n // class { sessionToken = Math.random()...; }\n if (parent.type === \"PropertyDefinition\" && parent.value === current) {\n const key = parent.key;\n if (!parent.computed && key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n }\n\n // Stop walking once we cross a boundary where the name no longer reflects\n // a binding/property whose value is being initialized.\n if (\n parent.type === \"FunctionDeclaration\" ||\n parent.type === \"FunctionExpression\" ||\n parent.type === \"ArrowFunctionExpression\" ||\n parent.type === \"BlockStatement\" ||\n parent.type === \"ReturnStatement\" ||\n parent.type === \"ExpressionStatement\"\n ) {\n return undefined;\n }\n\n current = parent;\n parent = current.parent;\n }\n\n return undefined;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-insecure-random-id\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow using `Math.random()` to generate identifiers, tokens, or secrets; use `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\",\n },\n schema: [],\n messages: {\n insecureRandomId:\n \"`Math.random()` is not cryptographically secure and is predictable; do not use it to generate IDs, tokens, or secrets. Use `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isMathRandomCall(node)) {\n return;\n }\n\n // Trigger 1: classic `.toString(36)` insecure id idiom.\n if (isPartOfToString36Chain(node)) {\n context.report({ node, messageId: \"insecureRandomId\" });\n return;\n }\n\n // Trigger 2: enclosing binding/property name looks id/secret-like.\n const name = findEnclosingName(node);\n if (name !== undefined && NAME_PATTERN.test(name)) {\n context.report({ node, messageId: \"insecureRandomId\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `JSON.stringify(err)` on a (heuristically detected)\n * Error value. `JSON.stringify` on an Error produces `\"{}\"` because the\n * `message` and `stack` properties are non-enumerable, silently throwing away\n * the very information you were trying to log.\n *\n * This is a purely syntactic rule (no type information). It flags\n * `JSON.stringify(x)` only when the first argument is an Identifier whose name\n * either:\n * 1. is the binding of an enclosing `catch (x)` clause in scope, OR\n * 2. matches the conventional error-name pattern /^(e|err|error|ex|exc)$/i.\n *\n * It is deliberately conservative: member expressions (`JSON.stringify(err.message)`),\n * object literals, and arbitrary identifiers (`JSON.stringify(user)`) are not flagged.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"noJsonStringifyError\";\ntype Options = readonly [];\n\nconst ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;\n\n/**\n * Walk up the scope chain looking for a `catch` clause whose binding matches\n * `name`. We rely on the scope analysis provided by the parser rather than\n * type information, keeping the rule type-free.\n */\nfunction isCatchBinding(scope: Scope.Scope, name: string): boolean {\n let current: Scope.Scope | null = scope;\n while (current) {\n const variable = current.set.get(name);\n if (variable) {\n for (const def of variable.defs) {\n if (def.type === \"CatchClause\") {\n return true;\n }\n }\n }\n current = current.upper;\n }\n return false;\n}\n\nfunction isJsonStringify(callee: TSESTree.Expression): boolean {\n return (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.object.type === \"Identifier\" &&\n callee.object.name === \"JSON\" &&\n callee.property.type === \"Identifier\" &&\n callee.property.name === \"stringify\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-json-stringify-error\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `JSON.stringify` on an Error value; it yields `{}` because `message`/`stack` are non-enumerable.\",\n },\n schema: [],\n messages: {\n noJsonStringifyError:\n \"`JSON.stringify` on an Error yields `{}` because `message`/`stack` are non-enumerable. Log `err.message` / `err.stack`, or use a proper error serializer.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isJsonStringify(node.callee)) {\n return;\n }\n\n const firstArg = node.arguments[0];\n if (!firstArg || firstArg.type !== \"Identifier\") {\n return;\n }\n\n const name = firstArg.name;\n const scope = context.sourceCode.getScope(firstArg);\n\n if (ERROR_NAME_PATTERN.test(name) || isCatchBinding(scope, name)) {\n context.report({\n node,\n messageId: \"noJsonStringifyError\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `catch` clauses that only log (via `console.*`) or do\n * nothing and then swallow the error. A catch that logs and falls through —\n * with no `throw`, no `return`, and no real recovery — hides failures: the\n * program keeps running in a broken state while the only signal is a log line\n * that is easy to miss. Either rethrow the error or handle it for real.\n *\n * This rule is deliberately conservative: it flags ONLY catches whose body is\n * empty or consists exclusively of `console.log/error/warn/info/debug` call\n * statements. Any other statement (a `throw`, a `return`, a fallback\n * assignment, a non-console call, etc.) means the catch is doing something and\n * is left alone — we prefer a false negative over a false positive.\n *\n * Test files opt out by default (filenames containing `.test.`, `.spec.`, or a\n * `__tests__/` path segment) since swallow-and-log is common and acceptable in\n * test scaffolding.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noLogOnlyCatch\";\ntype Options = readonly [];\n\nconst DEFAULT_IGNORE_PATTERNS: readonly RegExp[] = [\n /\\.test\\./,\n /\\.spec\\./,\n /[\\\\/]__tests__[\\\\/]/,\n];\n\nconst CONSOLE_METHODS: ReadonlySet<string> = new Set([\n \"log\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n]);\n\n/**\n * True when a statement is exactly a bare `console.<method>(...)` call, e.g.\n * `console.error(err);`. Anything else (other objects, optional chaining on a\n * non-`console` base, awaited/returned calls, etc.) returns false so the catch\n * is treated as doing real work.\n */\nfunction isConsoleCallStatement(statement: TSESTree.Statement): boolean {\n if (statement.type !== \"ExpressionStatement\") {\n return false;\n }\n const expr = statement.expression;\n if (expr.type !== \"CallExpression\") {\n return false;\n }\n const callee = expr.callee;\n if (callee.type !== \"MemberExpression\") {\n return false;\n }\n const { object, property } = callee;\n if (object.type !== \"Identifier\" || object.name !== \"console\") {\n return false;\n }\n if (callee.computed) {\n // console[\"log\"](...) — not a plain identifier method; be conservative.\n return false;\n }\n if (property.type !== \"Identifier\") {\n return false;\n }\n return CONSOLE_METHODS.has(property.name);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-log-only-catch\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `catch` clauses that only log (or do nothing) and then swallow the error; rethrow or handle it instead.\",\n },\n schema: [],\n messages: {\n noLogOnlyCatch:\n \"Logging then swallowing the error hides failures. Rethrow the error or handle it for real.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n\n const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS.some((re) =>\n re.test(filename),\n );\n\n if (isIgnoredByDefault) {\n return {};\n }\n\n return {\n CatchClause(node: TSESTree.CatchClause): void {\n const statements = node.body.body;\n\n // Empty catch: swallows the error silently.\n if (statements.length === 0) {\n context.report({ node, messageId: \"noLogOnlyCatch\" });\n return;\n }\n\n // Flag only if EVERY statement is a bare console.* call. Any other\n // statement (throw, return, fallback, real handler, etc.) means the\n // catch is doing something — leave it alone.\n const everyStatementIsConsoleLog = statements.every((statement) =>\n isConsoleCallStatement(statement),\n );\n\n if (everyStatementIsConsoleLog) {\n context.report({ node, messageId: \"noLogOnlyCatch\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow direct `process.env` access. Force all env reads\n * through a Zod-validated env module so configuration is typed and validated\n * at startup.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noRawEnv\";\ntype Options = readonly [];\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-raw-env\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow direct `process.env` access; use a Zod-validated env module instead.\",\n },\n schema: [],\n messages: {\n noRawEnv:\n \"Do not read from `process.env` directly. Import the Zod-validated env module instead so values are typed and validated at startup.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n MemberExpression(node: TSESTree.MemberExpression): void {\n if (node.computed) {\n // Skip dynamic accesses like process[\"env\"] — extremely rare and out of scope.\n return;\n }\n if (\n node.object.type === \"Identifier\" &&\n node.object.name === \"process\" &&\n node.property.type === \"Identifier\" &&\n node.property.name === \"env\"\n ) {\n context.report({\n node,\n messageId: \"noRawEnv\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow silently swallowing an error in a `catch` clause by\n * returning a \"sentinel\" empty value as the final/only statement.\n *\n * A `catch` block whose last statement is `return null` / `return undefined` /\n * `return false` / `return []` / `return {}` (and which never `throw`s) discards\n * the caught error entirely. Downstream callers can't distinguish a genuine\n * empty result from a failure, which is a frequent source of silent data loss\n * and broken idempotency decisions.\n *\n * This rule is deliberately conservative — it prefers false negatives over\n * false positives. It does NOT flag:\n * - catch blocks that `throw`/rethrow anywhere in their body,\n * - returns of a computed/meaningful value (calls, identifiers, member\n * expressions, non-empty literals),\n * - `return 0` / `return \"\"`, which are often legitimate results.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSentinelReturn\";\ntype Options = readonly [];\n\n/** Whether a returned expression is one of the swallowing sentinels. */\nfunction isSentinelArgument(arg: TSESTree.Expression | null): boolean {\n if (arg === null) {\n // `return;` — bare return is not in scope (no value-shaped sentinel).\n return false;\n }\n\n // `return null`\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === null) {\n return true;\n }\n\n // `return false`\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === false) {\n return true;\n }\n\n // `return undefined`\n if (arg.type === AST_NODE_TYPES.Identifier && arg.name === \"undefined\") {\n return true;\n }\n\n // `return []` — empty array literal only.\n if (arg.type === AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {\n return true;\n }\n\n // `return {}` — empty object literal only.\n if (\n arg.type === AST_NODE_TYPES.ObjectExpression &&\n arg.properties.length === 0\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Does this subtree contain a `throw` statement, ignoring nested functions\n * (a throw inside a nested function/arrow doesn't rethrow for *this* catch)?\n */\nfunction containsThrow(node: TSESTree.Node): boolean {\n let found = false;\n\n const visit = (current: TSESTree.Node): void => {\n if (found) {\n return;\n }\n\n if (current.type === AST_NODE_TYPES.ThrowStatement) {\n found = true;\n return;\n }\n\n // Do not descend into nested function scopes — a throw there does not\n // propagate out of the current catch synchronously.\n if (\n current.type === AST_NODE_TYPES.FunctionDeclaration ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return;\n }\n\n for (const key of Object.keys(current)) {\n if (key === \"parent\") {\n continue;\n }\n const value = (current as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child)) {\n visit(child);\n }\n }\n } else if (isNode(value)) {\n visit(value);\n }\n }\n };\n\n visit(node);\n return found;\n}\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-sentinel-return-on-catch\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow swallowing a caught error by returning an empty sentinel (`null`, `undefined`, `false`, `[]`, `{}`) as the final statement of a `catch` block.\",\n },\n schema: [],\n messages: {\n noSentinelReturn:\n \"This `catch` block swallows the error by returning an empty sentinel. Rethrow it, return a typed Result, or handle the error explicitly.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CatchClause(node: TSESTree.CatchClause): void {\n const body = node.body.body;\n if (body.length === 0) {\n return;\n }\n\n const last = body[body.length - 1];\n if (last === undefined || last.type !== AST_NODE_TYPES.ReturnStatement) {\n return;\n }\n\n if (!isSentinelArgument(last.argument)) {\n return;\n }\n\n // Conservative: if the catch body throws/rethrows anywhere, it's not\n // silently swallowing the error.\n if (containsThrow(node.body)) {\n return;\n }\n\n context.report({\n node: last,\n messageId: \"noSentinelReturn\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `await` expressions located directly inside the body\n * of a `for` / `for-of` / `for-in` / `while` loop within the same function\n * scope. Awaiting serially inside a loop serializes I/O that is often better\n * expressed as `await Promise.all(xs.map(async (x) => ...))`, letting the\n * operations run concurrently.\n *\n * This rule is intentionally conservative — it prefers a false negative over a\n * false positive:\n * - `for await...of` is NOT flagged (async iteration is the correct tool).\n * - awaits inside a function/arrow defined within the loop are NOT flagged\n * (they belong to a different function scope).\n * - awaits not inside any loop are NOT flagged.\n * At most one report is emitted per offending loop.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSequentialAwait\";\ntype Options = readonly [];\n\n/**\n * Node types that introduce a new function scope. We never descend across one\n * of these when looking for awaits belonging to a loop, because an `await`\n * inside a nested function/arrow is awaited by *that* function, not by the loop.\n */\nfunction isFunctionLike(node: TSESTree.Node): boolean {\n return (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n );\n}\n\n/**\n * Loop node types whose bodies we scan. `ForOfStatement` is handled specially\n * by the caller so that `for await...of` is excluded.\n */\ntype LoopNode =\n | TSESTree.ForStatement\n | TSESTree.ForOfStatement\n | TSESTree.ForInStatement\n | TSESTree.WhileStatement\n | TSESTree.DoWhileStatement;\n\n/**\n * Statement node types that introduce a nested loop. When scanning a loop's\n * body we must NOT descend into another loop — that inner loop's awaits belong\n * to it and are reported when the inner loop is visited. This keeps reporting\n * at one-per-loop and avoids double-flagging an outer loop for an await that\n * only appears inside a nested loop.\n */\nfunction isLoop(node: TSESTree.Node): boolean {\n return (\n node.type === \"ForStatement\" ||\n node.type === \"ForOfStatement\" ||\n node.type === \"ForInStatement\" ||\n node.type === \"WhileStatement\" ||\n node.type === \"DoWhileStatement\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-sequential-await\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow serial `await` inside a loop; use `await Promise.all(...)` to run the operations concurrently.\",\n },\n schema: [],\n messages: {\n noSequentialAwait:\n \"Avoid `await` inside a loop — it serializes I/O. Collect the promises and `await Promise.all(xs.map(async (x) => ...))` instead.\",\n },\n },\n defaultOptions: [],\n create(context) {\n /**\n * Walks the subtree rooted at `node`, returning the first `AwaitExpression`\n * that belongs to *this* loop's scope — i.e. reachable without crossing a\n * nested function/arrow boundary or descending into a nested loop. Returns\n * `null` if none.\n *\n * Stopping at function boundaries excludes awaits in nested functions\n * (awaited by that function, not the loop). Stopping at nested-loop\n * boundaries means each loop only \"owns\" its own direct awaits, so an outer\n * loop isn't flagged for an await that lives solely in an inner loop, and\n * every report stays one-per-loop.\n */\n function findAwaitInScope(\n node: TSESTree.Node,\n ): TSESTree.AwaitExpression | null {\n if (node.type === \"AwaitExpression\") {\n return node;\n }\n if (isFunctionLike(node)) {\n // Crossing into a different function scope — its awaits aren't ours.\n return null;\n }\n\n for (const key of Object.keys(node) as (keyof TSESTree.Node)[]) {\n if (key === \"parent\") {\n continue;\n }\n const value = node[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child) && !isLoop(child)) {\n const found = findAwaitInScope(child);\n if (found) {\n return found;\n }\n }\n }\n } else if (isNode(value) && !isLoop(value)) {\n const found = findAwaitInScope(value);\n if (found) {\n return found;\n }\n }\n }\n\n return null;\n }\n\n function isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n }\n\n /**\n * Reports the loop if its body contains an `await` belonging to the same\n * function scope. The loop's `body` (and, for the C-style `for`, its init /\n * test / update expressions) are the only places an \"await in this loop\"\n * can live; awaits in a *nested* loop are caught when that nested loop is\n * itself visited, keeping reports at one-per-loop.\n */\n function checkLoop(node: LoopNode): void {\n const parts: (TSESTree.Node | null)[] = [node.body];\n\n if (node.type === \"ForStatement\") {\n parts.push(node.init, node.test, node.update);\n } else if (\n node.type === \"ForOfStatement\" ||\n node.type === \"ForInStatement\"\n ) {\n parts.push(node.right);\n } else {\n // While / DoWhile.\n parts.push(node.test);\n }\n\n for (const part of parts) {\n // A part that is itself a loop (e.g. `for (...) for (...) await f()`)\n // is owned by that inner loop and checked when it is visited.\n if (part && !isLoop(part) && findAwaitInScope(part)) {\n context.report({ node, messageId: \"noSequentialAwait\" });\n return;\n }\n }\n }\n\n return {\n ForStatement: checkLoop,\n ForInStatement: checkLoop,\n WhileStatement: checkLoop,\n DoWhileStatement: checkLoop,\n ForOfStatement(node: TSESTree.ForOfStatement): void {\n // `for await...of` is correct async iteration — never flag it.\n if (node.await) {\n return;\n }\n checkLoop(node);\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow string accumulation via `+=` inside a loop, which is\n * the classic O(n^2) string-building antipattern: each `+=` rebuilds the whole\n * string. Push the parts onto an array and `arr.join(\"\")` after the loop\n * instead.\n *\n * This is a purely SYNTACTIC rule — it uses scope analysis (not the type\n * service) to confirm the left-hand side was declared with a string-literal\n * initializer (`let s = \"\"`, `= \"...\"`, or a template literal). It is\n * deliberately conservative: when the initializer type cannot be determined\n * (no initializer, a non-literal expression, a parameter, etc.) the `+=` is\n * NOT flagged. This mirrors the Python rule SARJ002.\n *\n * KNOWN GAP (false-negative): only the compound `+=` operator is detected. The\n * equivalent longhand `s = s + x` (a plain `=` assignment whose RHS is a\n * `BinaryExpression` referencing the LHS) has the same O(n^2) behavior but is\n * NOT flagged. Left as a deliberate scope limit to keep the rule conservative.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"noStringConcatInLoop\";\ntype Options = readonly [];\n\nconst LOOP_NODE_TYPES = new Set<string>([\n \"ForStatement\",\n \"ForOfStatement\",\n \"ForInStatement\",\n \"WhileStatement\",\n \"DoWhileStatement\",\n]);\n\n/**\n * Returns true if the given expression node is a string-producing literal:\n * a string `Literal` (`\"\"`, `\"...\"`, `'...'`) or a `TemplateLiteral`.\n */\nfunction isStringLiteralInit(node: TSESTree.Expression | null): boolean {\n if (node === null) {\n return false;\n }\n if (node.type === \"TemplateLiteral\") {\n return true;\n }\n if (node.type === \"Literal\") {\n return typeof node.value === \"string\";\n }\n return false;\n}\n\n/**\n * Walk the chain of enclosing scopes to find the variable definition for the\n * given identifier name. Returns the resolved `Variable`, or `undefined` if it\n * cannot be found (e.g. an undeclared global or an out-of-scope reference).\n */\nfunction findVariable(\n scope: Scope.Scope,\n name: string,\n): Scope.Variable | undefined {\n let current: Scope.Scope | null = scope;\n while (current !== null) {\n const variable = current.variables.find((v) => v.name === name);\n if (variable !== undefined) {\n return variable;\n }\n current = current.upper;\n }\n return undefined;\n}\n\n/**\n * Returns true if the variable was declared with a string-literal initializer.\n * Conservative: if the variable has no single string-initialized declarator\n * (no init, non-literal init, multiple conflicting declarators), returns false.\n */\nfunction isStringInitializedVariable(variable: Scope.Variable): boolean {\n // A variable can technically have multiple declarators (e.g. via `var`\n // hoisting / redeclaration). Only treat it as string-initialized when there\n // is exactly one declarator and it has a string-literal initializer.\n if (variable.defs.length !== 1) {\n return false;\n }\n const def = variable.defs[0];\n if (def === undefined || def.type !== \"Variable\") {\n // Parameters, function names, imports, etc. — type unknown, don't flag.\n return false;\n }\n const declarator = def.node;\n if (declarator.type !== \"VariableDeclarator\") {\n return false;\n }\n return isStringLiteralInit(declarator.init);\n}\n\n/**\n * Returns true if `node` is contained within the body of a loop statement.\n * Walks ancestors and, for each loop, ensures the node is inside the loop's\n * BODY (not its test/init/update clauses, which run a bounded number of times\n * relative to the body and aren't the antipattern we target).\n */\nfunction isInsideLoopBody(node: TSESTree.Node): boolean {\n let child: TSESTree.Node = node;\n let parent = node.parent;\n while (parent !== undefined && parent !== null) {\n if (LOOP_NODE_TYPES.has(parent.type)) {\n // `body` is the property that holds the looped statements for every\n // loop variant we care about.\n const loop = parent as\n | TSESTree.ForStatement\n | TSESTree.ForOfStatement\n | TSESTree.ForInStatement\n | TSESTree.WhileStatement\n | TSESTree.DoWhileStatement;\n if (loop.body === child) {\n return true;\n }\n }\n child = parent;\n parent = parent.parent;\n }\n return false;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-string-concat-in-loop\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow O(n^2) string building via `+=` on a string variable inside a loop; push parts to an array and `join` instead.\",\n },\n schema: [],\n messages: {\n noStringConcatInLoop:\n \"Avoid building a string with `+=` inside a loop — this is O(n^2). Push the parts onto an array and use `arr.join(\\\"\\\")` after the loop.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n AssignmentExpression(node: TSESTree.AssignmentExpression): void {\n // Only the compound `+=` operator builds up a value.\n if (node.operator !== \"+=\") {\n return;\n }\n // The LHS must be a plain variable reference.\n if (node.left.type !== \"Identifier\") {\n return;\n }\n // Must occur inside a loop body, else it's a one-shot append.\n if (!isInsideLoopBody(node)) {\n return;\n }\n\n const scope = context.sourceCode.getScope(node);\n const variable = findVariable(scope, node.left.name);\n // Conservative: can't resolve the declaration -> don't flag.\n if (variable === undefined) {\n return;\n }\n // Only flag when we can confirm the LHS was string-initialized; a\n // numeric initializer (or anything non-string) is intentionally\n // excluded to avoid false positives.\n if (!isStringInitializedVariable(variable)) {\n return;\n }\n\n context.report({\n node,\n messageId: \"noStringConcatInLoop\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Flag `'use client'` files with no hooks or event handlers.\n *\n * If a file is marked `'use client'` but contains no hook calls\n * (`useState`/`useEffect`/etc.), no JSX event handlers (`onClick`,\n * `onChange`, etc.), no browser globals, no client-only imports, and no\n * other client-side indicators (classes, re-exports), the directive is\n * likely unnecessary and the file could be a React Server Component —\n * improving cold-start, bundle size, and SEO.\n *\n * False-positive watch: components that only use client-side context\n * (e.g. theme providers) without hooks or events still need `'use client'`.\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/rendering/client-components\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"unnecessaryUseClient\";\ntype Options = readonly [];\n\nconst HOOK_REGEX = /^use([A-Z]|$)/;\nconst EVENT_PROP_REGEX = /^on[A-Z]/;\nconst ERROR_FILE_REGEX = /\\b(?:global-)?error\\.[jt]sx?$/;\n\nconst BROWSER_GLOBALS: ReadonlySet<string> = new Set([\n \"window\",\n \"document\",\n \"navigator\",\n \"localStorage\",\n \"sessionStorage\",\n \"location\",\n \"history\",\n \"screen\",\n \"requestAnimationFrame\",\n \"cancelAnimationFrame\",\n \"CustomEvent\",\n \"Event\",\n \"MouseEvent\",\n \"KeyboardEvent\",\n \"TouchEvent\",\n]);\n\nconst CLIENT_ONLY_PACKAGES_REGEX =\n /^(?:@radix-ui\\/|framer-motion|react-dom|react-day-picker|@floating-ui\\/|react-select|react-toastify|react-hook-form|recharts|react-dropzone|react-slick|react-swipeable|react-resizable|react-draggable|react-beautiful-dnd|@hello-pangea\\/dnd|react-virtualized|react-window|@tanstack\\/react-table|@tanstack\\/react-query|react-redux|recoil|jotai|zustand|@tippyjs\\/react|react-color|react-datepicker|next-themes|react-helmet|react-helmet-async|styled-components|@emotion\\/)/;\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\nconst isUseClientDirective = (\n node: TSESTree.Statement,\n): node is TSESTree.ExpressionStatement => {\n return (\n node.type === AST_NODE_TYPES.ExpressionStatement &&\n node.expression.type === AST_NODE_TYPES.Literal &&\n node.expression.value === \"use client\"\n );\n};\n\nconst isGlobalReference = (\n node: TSESTree.Identifier,\n context: Ctx,\n): boolean => {\n if (!BROWSER_GLOBALS.has(node.name)) return false;\n\n const parent = node.parent;\n if (parent !== undefined) {\n // `obj.window` — `window` is a property name, not a global reference.\n if (\n parent.type === AST_NODE_TYPES.MemberExpression &&\n parent.property === node &&\n !parent.computed\n ) {\n return false;\n }\n // `{ window: ... }` — property key, not a global reference.\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === node &&\n !parent.computed\n ) {\n return false;\n }\n // Type annotations / type-only positions are not runtime references.\n if (parent.type.startsWith(\"TS\")) {\n return false;\n }\n }\n\n // If there's a local binding for this name anywhere up the chain, it's not\n // a reference to the browser global.\n let scope: Scope.Scope | null = context.sourceCode.getScope(node);\n while (scope !== null) {\n const variable = scope.set.get(node.name);\n if (variable !== undefined && variable.defs.length > 0) {\n return false;\n }\n scope = scope.upper;\n }\n\n return true;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-unnecessary-use-client\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag `'use client'` files with no hooks or event handlers — they could be RSC.\",\n },\n schema: [],\n messages: {\n unnecessaryUseClient:\n \"'use client' directive but no hooks (use*), JSX event handlers (on*), browser globals, or client-only imports found. Consider removing the directive and serving as a React Server Component.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n if (ERROR_FILE_REGEX.test(filename)) {\n return {};\n }\n\n let directiveNode: TSESTree.ExpressionStatement | null = null;\n let hasClientIndicator = false;\n\n const markIfHookOrContext = (\n callee: TSESTree.CallExpression[\"callee\"],\n ): void => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n if (HOOK_REGEX.test(callee.name) || callee.name === \"createContext\") {\n hasClientIndicator = true;\n }\n return;\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n const name = callee.property.name;\n if (HOOK_REGEX.test(name) || name === \"createContext\") {\n hasClientIndicator = true;\n }\n }\n };\n\n return {\n Program(node): void {\n for (const stmt of node.body) {\n // Directives must be the first statements; once we see a non-\n // ExpressionStatement, stop scanning.\n if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) break;\n if (isUseClientDirective(stmt)) {\n directiveNode = stmt;\n break;\n }\n }\n },\n CallExpression(node): void {\n // The `Program` visitor (entered first) has already determined whether\n // this file has a `'use client'` directive. If it doesn't, the result\n // can't change — skip all of the per-node indicator work, including the\n // hot scope-resolution in the `Identifier` visitor below.\n if (directiveNode === null) return;\n markIfHookOrContext(node.callee);\n },\n JSXAttribute(node): void {\n if (directiveNode === null) return;\n if (\n node.name.type === AST_NODE_TYPES.JSXIdentifier &&\n EVENT_PROP_REGEX.test(node.name.name)\n ) {\n hasClientIndicator = true;\n }\n },\n ImportDeclaration(node): void {\n if (directiveNode === null) return;\n if (\n typeof node.source.value === \"string\" &&\n CLIENT_ONLY_PACKAGES_REGEX.test(node.source.value)\n ) {\n hasClientIndicator = true;\n }\n },\n ExportNamedDeclaration(node): void {\n if (directiveNode === null) return;\n if (node.source !== null) {\n hasClientIndicator = true;\n }\n },\n ExportAllDeclaration(node): void {\n if (directiveNode === null) return;\n if (node.source !== null) {\n hasClientIndicator = true;\n }\n },\n ClassDeclaration(): void {\n if (directiveNode === null) return;\n hasClientIndicator = true;\n },\n ClassExpression(): void {\n if (directiveNode === null) return;\n hasClientIndicator = true;\n },\n Identifier(node): void {\n if (directiveNode === null) return;\n if (isGlobalReference(node, context)) {\n hasClientIndicator = true;\n }\n },\n \"Program:exit\"(): void {\n if (directiveNode !== null && !hasClientIndicator) {\n context.report({\n node: directiveNode,\n messageId: \"unnecessaryUseClient\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag object types that model mutually-exclusive states with a\n * boolean status flag plus many optional members. A shape like\n * `{ success: boolean; data?: T; error?: E; code?: number }` encodes \"success\n * vs. error\" implicitly and lets illegal states (e.g. `success: true` with an\n * `error`) be representable.\n *\n * Such shapes should be modelled as a discriminated union, e.g.\n * `{ ok: true; data: T } | { ok: false; error: E }`, so the compiler enforces\n * that exactly one branch's fields are present.\n *\n * This is the TypeScript mirror of the Python rule SARJ005.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport { AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"preferDiscriminatedUnion\";\ntype Options = readonly [];\n\n/**\n * Boolean-typed member names that read as a success/error status discriminant.\n */\nconst STATUS_MEMBER_NAMES: ReadonlySet<string> = new Set([\n \"success\",\n \"ok\",\n \"error\",\n \"failed\",\n \"isError\",\n]);\n\nconst MIN_OPTIONAL_MEMBERS = 2;\n\n/**\n * Returns the property key name for a member if it is a plain identifier or\n * string-literal property signature, otherwise `null`.\n */\nfunction getMemberName(member: TSESTree.TypeElement): string | null {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return null;\n }\n const { key } = member;\n if (key.type === AST_NODE_TYPES.Identifier) {\n return key.name;\n }\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") {\n return key.value;\n }\n return null;\n}\n\n/**\n * Whether a property signature is annotated with `boolean`.\n */\nfunction isBooleanTyped(member: TSESTree.TSPropertySignature): boolean {\n return (\n member.typeAnnotation?.typeAnnotation.type ===\n AST_NODE_TYPES.TSBooleanKeyword\n );\n}\n\n/**\n * Returns true when the object type literal has BOTH a boolean-typed status\n * member AND at least `MIN_OPTIONAL_MEMBERS` optional members.\n */\nfunction looksLikeMutuallyExclusiveState(\n typeLiteral: TSESTree.TSTypeLiteral,\n): boolean {\n let hasStatusBoolean = false;\n let optionalCount = 0;\n\n for (const member of typeLiteral.members) {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n continue;\n }\n\n if (member.optional) {\n optionalCount += 1;\n }\n\n const name = getMemberName(member);\n if (\n name !== null &&\n STATUS_MEMBER_NAMES.has(name) &&\n isBooleanTyped(member)\n ) {\n hasStatusBoolean = true;\n }\n }\n\n return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-discriminated-union\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag object types with a boolean status flag and many optionals; model them as a discriminated union instead.\",\n },\n schema: [],\n messages: {\n preferDiscriminatedUnion:\n \"This object type uses a boolean status flag alongside several optional fields, which lets illegal states be representable. Model it as a `z.discriminatedUnion` / discriminated union (e.g. `{ ok: true; data: T } | { ok: false; error: E }`) to make illegal states unrepresentable.\",\n },\n },\n defaultOptions: [],\n create(context) {\n function checkTypeLiteral(\n typeLiteral: TSESTree.TSTypeLiteral,\n reportNode: TSESTree.Node,\n ): void {\n if (looksLikeMutuallyExclusiveState(typeLiteral)) {\n context.report({\n node: reportNode,\n messageId: \"preferDiscriminatedUnion\",\n });\n }\n }\n\n return {\n TSInterfaceDeclaration(\n node: TSESTree.TSInterfaceDeclaration,\n ): void {\n // An interface body is structurally an object type literal; reuse the\n // same membership analysis by treating its `body.body` as members.\n const synthetic: TSESTree.TSTypeLiteral = {\n ...node.body,\n type: AST_NODE_TYPES.TSTypeLiteral,\n members: node.body.body,\n } as TSESTree.TSTypeLiteral;\n checkTypeLiteral(synthetic, node);\n },\n \"TSTypeAliasDeclaration > TSTypeLiteral\"(\n node: TSESTree.TSTypeLiteral,\n ): void {\n checkTypeLiteral(node, node.parent);\n },\n };\n },\n});\n","/**\n * @fileoverview Don't access `response.json()` fields without a Zod parse first.\n *\n * Pattern flagged:\n * const data = await response.json();\n * doSomething(data.foo); // <-- unvalidated property access\n *\n * Encouraged:\n * const data = MySchema.parse(await response.json());\n * doSomething(data.foo); // typed + validated\n *\n * Heuristic:\n * - Track variables initialized to `await someCall.json()` using ESLint's scope manager.\n * - Untrack if reassigned to anything other than another raw `json()` call.\n * - Flag MemberExpression reads and destructuring off tracked variables.\n * - `.parse()` / `.safeParse()` chained directly on the json call are legit\n * and never produce a tracked binding in the first place.\n *\n * References:\n * - https://zod.dev/?id=parse\n * - https://www.totaltypescript.com/parse-don-t-validate\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"unparsedJsonAccess\";\ntype Options = readonly [];\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\n/**\n * Peel TypeScript wrapper nodes that don't affect the underlying value\n * (`as Foo`, `<Foo>x`, `x!`, `x satisfies Foo`, parentheses, optional chain\n * wrappers). Returns the inner expression we actually care about.\n */\nconst unwrap = (\n node: TSESTree.Node | null | undefined,\n): TSESTree.Node | null => {\n let current: TSESTree.Node | null | undefined = node;\n while (current !== null && current !== undefined) {\n if (\n current.type === AST_NODE_TYPES.TSAsExpression ||\n current.type === AST_NODE_TYPES.TSTypeAssertion ||\n current.type === AST_NODE_TYPES.TSNonNullExpression ||\n current.type === AST_NODE_TYPES.TSSatisfiesExpression\n ) {\n current = current.expression;\n } else if (current.type === AST_NODE_TYPES.ChainExpression) {\n current = current.expression;\n } else {\n break;\n }\n }\n return current ?? null;\n};\n\n/**\n * Returns true if the expression is (optionally awaited) `<x>.json()`.\n */\nconst isJsonCall = (\n node: TSESTree.Node | null | undefined,\n): boolean => {\n let current = unwrap(node);\n if (current === null) return false;\n if (current.type === AST_NODE_TYPES.AwaitExpression) {\n current = unwrap(current.argument);\n }\n if (current === null || current.type !== AST_NODE_TYPES.CallExpression) {\n return false;\n }\n const callee = unwrap(current.callee);\n if (callee === null || callee.type !== AST_NODE_TYPES.MemberExpression) {\n return false;\n }\n const property = unwrap(callee.property);\n return (\n property !== null &&\n property.type === AST_NODE_TYPES.Identifier &&\n property.name === \"json\"\n );\n};\n\nconst findVariable = (\n scope: Scope.Scope | null,\n name: string,\n): Scope.Variable | null => {\n let current: Scope.Scope | null = scope;\n while (current !== null) {\n const variable = current.set.get(name);\n if (variable !== undefined) return variable;\n current = current.upper;\n }\n return null;\n};\n\nconst isUnvalidatedVariableRef = (\n node: TSESTree.Node | null | undefined,\n scope: Scope.Scope,\n tracked: ReadonlySet<Scope.Variable>,\n): boolean => {\n const unwrapped = unwrap(node);\n if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES.Identifier) {\n return false;\n }\n const variable = findVariable(scope, unwrapped.name);\n return variable !== null && tracked.has(variable);\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-schema-for-api-payload\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require Zod (or similar) schema validation on `response.json()` before property access.\",\n },\n schema: [],\n messages: {\n unparsedJsonAccess:\n \"Property access on the result of `response.json()` without a schema parse. Pipe through `XSchema.parse(...)` (Zod) before reading fields.\",\n },\n },\n defaultOptions: [],\n create(context: Ctx) {\n const unvalidatedVariables = new Set<Scope.Variable>();\n\n const trackInitializer = (\n declarator: TSESTree.VariableDeclarator,\n ): void => {\n if (!isJsonCall(declarator.init)) return;\n const declaredVars = context.sourceCode.getDeclaredVariables(declarator);\n const variable = declaredVars[0];\n if (variable !== undefined) {\n unvalidatedVariables.add(variable);\n }\n };\n\n return {\n VariableDeclarator(node): void {\n const scope = context.sourceCode.getScope(node);\n\n if (node.id.type === AST_NODE_TYPES.Identifier) {\n trackInitializer(node);\n return;\n }\n\n if (\n node.id.type === AST_NODE_TYPES.ObjectPattern ||\n node.id.type === AST_NODE_TYPES.ArrayPattern\n ) {\n if (isJsonCall(node.init)) {\n context.report({ node: node.id, messageId: \"unparsedJsonAccess\" });\n return;\n }\n if (\n isUnvalidatedVariableRef(node.init, scope, unvalidatedVariables)\n ) {\n context.report({ node: node.id, messageId: \"unparsedJsonAccess\" });\n }\n }\n },\n AssignmentExpression(node): void {\n const scope = context.sourceCode.getScope(node);\n\n if (node.left.type === AST_NODE_TYPES.Identifier) {\n const variable = findVariable(scope, node.left.name);\n if (variable === null) return;\n if (isJsonCall(node.right)) {\n unvalidatedVariables.add(variable);\n } else {\n // Reassigned to a parse call or something else: drop tracking.\n unvalidatedVariables.delete(variable);\n }\n return;\n }\n\n if (\n node.left.type === AST_NODE_TYPES.ObjectPattern ||\n node.left.type === AST_NODE_TYPES.ArrayPattern\n ) {\n if (isJsonCall(node.right)) {\n context.report({\n node: node.left,\n messageId: \"unparsedJsonAccess\",\n });\n return;\n }\n if (\n isUnvalidatedVariableRef(node.right, scope, unvalidatedVariables)\n ) {\n context.report({\n node: node.left,\n messageId: \"unparsedJsonAccess\",\n });\n }\n }\n },\n MemberExpression(node): void {\n const scope = context.sourceCode.getScope(node);\n const obj = unwrap(node.object);\n\n if (isJsonCall(obj)) {\n // Direct `.foo` access on `(await r.json()).foo` is always bad,\n // unless the parent call is a `.parse()`/`.safeParse()` — in which\n // case it's a validation, not an unvalidated read.\n const parent = node.parent;\n if (\n parent.type === AST_NODE_TYPES.CallExpression &&\n parent.callee === node &&\n node.property.type === AST_NODE_TYPES.Identifier &&\n (node.property.name === \"parse\" ||\n node.property.name === \"safeParse\")\n ) {\n return;\n }\n context.report({ node, messageId: \"unparsedJsonAccess\" });\n return;\n }\n\n if (\n obj !== null &&\n obj.type === AST_NODE_TYPES.Identifier &&\n isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)\n ) {\n context.report({ node, messageId: \"unparsedJsonAccess\" });\n const variable = findVariable(scope, obj.name);\n if (variable !== null) {\n unvalidatedVariables.delete(variable);\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Enforce design-system semantic color tokens over raw Tailwind\n * palette classes and hardcoded color values.\n *\n * Scoped to genuine className positions to avoid false positives on non-class\n * strings (Tailwind `safelist`, `toHaveClass(...)` test assertions, prose, color\n * maps): JSX `className`, the args of `cn()`/`clsx()`/`cva()`/`tv()`/`cx()`/\n * `twMerge()` (recursing into cva variant objects), and `*class*`-named\n * variables/object properties. Plus inline color literals on JSX `style`/`fill`/\n * `stroke`.\n *\n * Flags:\n * - raw palette classes: `text-red-500`, `bg-slate-200/50`\n * - arbitrary color values: `bg-[#fff]`, `text-[rgb(...)]`, `ring-[oklch(...)]`\n * - inline color literals: `style={{ color: \"#111827\" }}`, `fill=\"#000\"`\n *\n * Allowed: semantic tokens (`bg-primary`, `text-muted-foreground`, `bg-chart-1`),\n * `white`/`black` (the `bg-black/50` overlay idiom rarely has a token), `var(--…)`,\n * `currentColor`, and non-color arbitraries (`w-[437px]`, `grid-cols-[auto_1fr]`).\n * No autofix — use a semantic token, or for charts / standalone pages / 3rd-party\n * config add `// eslint-disable-next-line @sarj/prefer-semantic-colors -- <reason>`.\n */\n\nimport { AST_NODE_TYPES, ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\nimport { classTokens, tailwindBase } from \"./_tailwind.js\";\n\ntype MessageIds = \"rawPalette\" | \"arbitraryColor\" | \"inlineColor\";\ntype Options = readonly [];\n\nconst COLOR_PREFIXES =\n \"text|bg|border(?:-[trblxyse])?|ring(?:-offset)?|fill|stroke|from|via|to|divide|decoration|placeholder|accent|caret|shadow|outline\";\nconst PALETTE =\n \"red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|slate|gray|zinc|neutral|stone\";\nconst COLOR_FN = \"rgba?|hsla?|hwb|oklch|oklab|lab|lch|color\";\n\nconst RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-\\\\d{2,3}(?:/\\\\d{1,3})?$`);\nconst ARBITRARY_COLOR_RE = new RegExp(\n `^(?:${COLOR_PREFIXES})-\\\\[(?:#[0-9a-fA-F]{3,8}|(?:${COLOR_FN})\\\\([^\\\\]]*\\\\))\\\\]$`,\n \"i\",\n);\n\n/** Call expressions whose string args are className fragments. */\nconst CLASS_FNS = new Set<string>([\"cn\", \"clsx\", \"cva\", \"tv\", \"cx\", \"twMerge\", \"classnames\", \"classNames\"]);\nconst CLASS_NAME_RE = /class/i;\n\n/** CSS color-bearing properties, in their JSX (camelCase) and SVG-attribute forms. */\nconst STYLE_COLOR_PROPS = new Set<string>([\n \"color\",\n \"background\",\n \"backgroundColor\",\n \"borderColor\",\n \"borderTopColor\",\n \"borderRightColor\",\n \"borderBottomColor\",\n \"borderLeftColor\",\n \"outlineColor\",\n \"caretColor\",\n \"textDecorationColor\",\n \"columnRuleColor\",\n \"fill\",\n \"stroke\",\n \"stopColor\",\n \"floodColor\",\n \"lightingColor\",\n]);\nconst RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\\\b|\\\\b(?:${COLOR_FN})\\\\s*\\\\(`, \"i\");\n\nconst propName = (key: TSESTree.Property[\"key\"]): string | null => {\n if (key.type === AST_NODE_TYPES.Identifier) return key.name;\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") return key.value;\n return null;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-semantic-colors\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce design-system semantic color tokens (bg-primary, text-destructive, …) over raw Tailwind palette classes (text-red-500), arbitrary color values (bg-[#fff]), and inline color literals.\",\n },\n schema: [],\n messages: {\n rawPalette:\n \"Raw palette class '{{class}}' — use a semantic token (e.g. text-foreground, bg-primary, text-destructive, bg-muted).\",\n arbitraryColor:\n \"Hardcoded color '{{class}}' — use a semantic token, or var(--…). For charts/brand add an eslint-disable with a reason.\",\n inlineColor:\n \"Hardcoded color '{{value}}' — use a semantic token / CSS variable. For charts/standalone pages add an eslint-disable with a reason.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const reportClasses = (value: string, node: TSESTree.Node): void => {\n for (const token of classTokens(value)) {\n const base = tailwindBase(token);\n if (RAW_PALETTE_RE.test(base)) {\n context.report({ node, messageId: \"rawPalette\", data: { class: token } });\n } else if (ARBITRARY_COLOR_RE.test(base)) {\n context.report({ node, messageId: \"arbitraryColor\", data: { class: token } });\n }\n }\n };\n\n // Walk a node that holds className fragments: strings, templates, arrays, cva\n // variant objects, and conditionals. CallExpressions are handled separately, so\n // they're not recursed here (avoids double-reporting cn()/cva() args).\n const checkClassNode = (node: TSESTree.Node | null): void => {\n if (node === null) return;\n switch (node.type) {\n case AST_NODE_TYPES.Literal:\n if (typeof node.value === \"string\") reportClasses(node.value, node);\n break;\n case AST_NODE_TYPES.TemplateLiteral:\n for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? \"\", quasi);\n break;\n case AST_NODE_TYPES.ArrayExpression:\n for (const element of node.elements) {\n if (element !== null && element.type !== AST_NODE_TYPES.SpreadElement) checkClassNode(element);\n }\n break;\n case AST_NODE_TYPES.ObjectExpression:\n for (const property of node.properties) {\n if (property.type === AST_NODE_TYPES.Property) checkClassNode(property.value);\n }\n break;\n case AST_NODE_TYPES.ConditionalExpression:\n checkClassNode(node.consequent);\n checkClassNode(node.alternate);\n break;\n case AST_NODE_TYPES.LogicalExpression:\n checkClassNode(node.right);\n break;\n default:\n break;\n }\n };\n\n const checkColorValueNode = (node: TSESTree.Node): void => {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === \"string\" &&\n RAW_COLOR_VALUE_RE.test(node.value)\n ) {\n context.report({ node, messageId: \"inlineColor\", data: { value: node.value } });\n }\n };\n\n return {\n \"JSXAttribute[name.name='className']\"(node: TSESTree.JSXAttribute): void {\n if (node.value === null) return;\n if (node.value.type === AST_NODE_TYPES.Literal) checkClassNode(node.value);\n else if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer) {\n if (node.value.expression.type !== AST_NODE_TYPES.JSXEmptyExpression) {\n checkClassNode(node.value.expression);\n }\n }\n },\n CallExpression(node: TSESTree.CallExpression): void {\n if (node.callee.type === AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {\n for (const arg of node.arguments) {\n if (arg.type !== AST_NODE_TYPES.SpreadElement) checkClassNode(arg);\n }\n }\n },\n VariableDeclarator(node: TSESTree.VariableDeclarator): void {\n if (node.id.type === AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {\n checkClassNode(node.init);\n }\n },\n Property(node: TSESTree.Property): void {\n const name = propName(node.key);\n if (name !== null && CLASS_NAME_RE.test(name)) checkClassNode(node.value);\n },\n // SVG presentation attributes: <path fill=\"#000\" stroke=\"#fff\" />\n \"JSXAttribute[name.name=/^(fill|stroke|color)$/]\"(node: TSESTree.JSXAttribute): void {\n if (node.value?.type === AST_NODE_TYPES.Literal) checkColorValueNode(node.value);\n },\n // Inline style objects: style={{ color: \"#111827\", backgroundColor: \"#fff\" }}\n \"JSXAttribute[name.name='style'] ObjectExpression > Property\"(node: TSESTree.Property): void {\n const name = propName(node.key);\n if (name !== null && STYLE_COLOR_PROPS.has(name)) checkColorValueNode(node.value);\n },\n };\n },\n});\n","/**\n * @fileoverview Shared helpers for the Tailwind-className rules. className values\n * are reachable as plain string `Literal`s (attribute values, `cn()`/`clsx()`/\n * `cva()`/`tv()` args, and className-holding constants) and as the static quasis of\n * `TemplateLiteral`s — so the rules visit both node types and run these helpers.\n */\n\n/**\n * Strip Tailwind variant prefixes (`hover:`, `dark:`, `focus-visible:`, …) and a\n * leading `!` important marker, leaving the bare utility (`bg-red-500`). Variants are\n * `[a-z0-9-]+:` runs at the start; bracketed arbitrary values never start a token, so\n * a `:` inside `[url(http://…)]` is not mistaken for a variant separator.\n */\nexport const tailwindBase = (token: string): string =>\n token.replace(/^(?:[a-z0-9-]+:)+/i, \"\").replace(/^!/, \"\");\n\n/** Split a className string into its non-empty class tokens. */\nexport const classTokens = (value: string): readonly string[] =>\n value.split(/\\s+/).filter(Boolean);\n","/**\n * @fileoverview Prefer Next.js Server Actions over /api/* mutations.\n *\n * Flags mutations against internal `/api/*` URLs (POST/PUT/DELETE/PATCH) via\n * `fetch`, axios-style helpers, or direct axios/request calls. GET requests\n * and external URLs are ignored. Tests, scripts, and Next.js route handlers\n * are skipped because Server Actions don't apply there.\n *\n * The member branch (`api.post('/api/x')`) intentionally skips calls that pass\n * a function argument (e.g. `router.post('/api/x', handler)`) so Express-style\n * route *definitions* aren't mistaken for client-side mutations.\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"preferServerAction\";\ntype Options = readonly [];\n\nconst MUTATION_METHODS = new Set([\"POST\", \"PUT\", \"DELETE\", \"PATCH\"]);\nconst AXIOS_MUTATION_METHODS = new Set([\"post\", \"put\", \"delete\", \"patch\"]);\n\nconst SKIP_FILE_REGEX =\n /(?:\\.test\\.[jt]sx?$|\\.spec\\.[jt]sx?$|\\/tests?\\/|\\/__tests__\\/|\\/scripts?\\/|\\/app\\/api\\/.*\\/route\\.[jt]sx?$|\\/pages\\/api\\/)/;\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\nfunction getScope(\n context: Ctx,\n node: TSESTree.Node,\n): Scope.Scope {\n return context.sourceCode.getScope(node);\n}\n\n/**\n * Walk up the scope chain looking for a variable declared with a single\n * initializer; if found, return the initializer expression so we can analyze\n * it. Falls back to the original node when resolution is not possible.\n */\nfunction resolveNode(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): TSESTree.Node | null {\n if (!node) return null;\n if (node.type !== \"Identifier\") return node;\n\n let scope: Scope.Scope | null = getScope(context, node);\n while (scope) {\n const variable = scope.set.get(node.name);\n if (variable && variable.defs.length === 1) {\n const def = variable.defs[0];\n if (def && def.type === \"Variable\") {\n const declarator = def.node;\n if (\n declarator.type === \"VariableDeclarator\" &&\n declarator.init\n ) {\n return declarator.init;\n }\n }\n }\n scope = scope.upper;\n }\n return node;\n}\n\nfunction isApiUrl(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): boolean {\n const resolved = resolveNode(node, context);\n if (!resolved) return false;\n\n if (resolved.type === \"Literal\" && typeof resolved.value === \"string\") {\n return resolved.value.startsWith(\"/api/\");\n }\n if (resolved.type === \"TemplateLiteral\") {\n const firstQuasi = resolved.quasis[0];\n const cooked = firstQuasi?.value.cooked;\n return typeof cooked === \"string\" && cooked.startsWith(\"/api/\");\n }\n if (resolved.type === \"BinaryExpression\" && resolved.operator === \"+\") {\n return isApiUrl(resolved.left, context);\n }\n return false;\n}\n\nfunction isMutationMethod(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): boolean {\n const resolved = resolveNode(node, context);\n if (!resolved) return false;\n\n if (resolved.type === \"Literal\" && typeof resolved.value === \"string\") {\n return MUTATION_METHODS.has(resolved.value.toUpperCase());\n }\n\n if (\n resolved.type === \"TemplateLiteral\" &&\n resolved.expressions.length === 0\n ) {\n const val = resolved.quasis.map((q) => q.value.cooked).join(\"\");\n return MUTATION_METHODS.has(val.toUpperCase());\n }\n\n if (resolved.type === \"ConditionalExpression\") {\n return (\n isMutationMethod(resolved.consequent, context) ||\n isMutationMethod(resolved.alternate, context)\n );\n }\n\n if (resolved.type === \"LogicalExpression\" && resolved.operator === \"||\") {\n return (\n isMutationMethod(resolved.left, context) ||\n isMutationMethod(resolved.right, context)\n );\n }\n\n return false;\n}\n\nfunction getPropertyNode(\n objNode: TSESTree.Node | null | undefined,\n propName: string,\n): TSESTree.Node | null {\n if (!objNode || objNode.type !== \"ObjectExpression\") return null;\n for (const prop of objNode.properties) {\n if (prop.type !== \"Property\") continue;\n let keyName: string | null = null;\n if (prop.key.type === \"Identifier\" && !prop.computed) {\n keyName = prop.key.name;\n } else if (\n prop.key.type === \"Literal\" &&\n typeof prop.key.value === \"string\"\n ) {\n keyName = prop.key.value;\n }\n if (keyName === propName) {\n // Skip destructuring patterns — they're not valid as config values.\n if (\n prop.value.type === \"AssignmentPattern\" ||\n prop.value.type === \"ArrayPattern\" ||\n prop.value.type === \"ObjectPattern\"\n ) {\n return null;\n }\n return prop.value;\n }\n }\n return null;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-server-actions\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Prefer Next.js Server Actions over /api/* mutations.\",\n },\n schema: [],\n messages: {\n preferServerAction:\n \"Mutation against /api/* — prefer a Next.js Server Action for type-safety and to avoid the JSON round-trip.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n if (SKIP_FILE_REGEX.test(filename)) {\n return {};\n }\n\n return {\n CallExpression(node) {\n let isMutation = false;\n\n // 1. Standard fetch('/api/orders', { method: 'POST' })\n if (\n node.callee.type === \"Identifier\" &&\n node.callee.name === \"fetch\"\n ) {\n const urlArg = node.arguments[0];\n if (urlArg && urlArg.type !== \"SpreadElement\" && isApiUrl(urlArg, context)) {\n const initArg = node.arguments[1];\n if (initArg && initArg.type !== \"SpreadElement\") {\n const resolvedInit = resolveNode(initArg, context);\n const methodNode = getPropertyNode(resolvedInit, \"method\");\n if (methodNode && isMutationMethod(methodNode, context)) {\n isMutation = true;\n }\n }\n }\n }\n // 2. Custom wrappers or Axios: api.post('/api/orders') or axios.put('/api/orders')\n else if (\n node.callee.type === \"MemberExpression\" &&\n node.callee.property.type === \"Identifier\" &&\n !node.callee.computed\n ) {\n const methodName = node.callee.property.name.toLowerCase();\n if (AXIOS_MUTATION_METHODS.has(methodName)) {\n const urlArg = node.arguments[0];\n // Skip Express-style route definitions like\n // `router.post('/api/x', handler)`: a function argument means this\n // is registering a handler, not issuing a client mutation.\n const hasHandlerArg = node.arguments.some(\n (arg) =>\n arg.type === \"ArrowFunctionExpression\" ||\n arg.type === \"FunctionExpression\",\n );\n if (\n urlArg &&\n urlArg.type !== \"SpreadElement\" &&\n !hasHandlerArg &&\n isApiUrl(urlArg, context)\n ) {\n isMutation = true;\n }\n }\n }\n // 3. Direct axios/request call: axios({ method: 'post', url: '/api/orders' })\n else if (\n node.callee.type === \"Identifier\" &&\n (node.callee.name === \"axios\" || node.callee.name === \"request\")\n ) {\n const firstArg = node.arguments[0];\n if (firstArg && firstArg.type !== \"SpreadElement\") {\n const configArg = resolveNode(firstArg, context);\n if (configArg && configArg.type === \"ObjectExpression\") {\n const urlNode = getPropertyNode(configArg, \"url\");\n const methodNode = getPropertyNode(configArg, \"method\");\n if (\n urlNode &&\n isApiUrl(urlNode, context) &&\n methodNode &&\n isMutationMethod(methodNode, context)\n ) {\n isMutation = true;\n }\n }\n }\n }\n\n if (isMutation) {\n context.report({ node, messageId: \"preferServerAction\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Prefer shadcn/ui form primitives over their native HTML\n * counterparts. Limited to form/dialog elements — `<button>` and `<table>`\n * have been removed from the forbid list because they produced 100% false\n * positives during bulbul validation (icon buttons, layout tables).\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"preferShadcn\";\ntype Options = readonly [];\n\nconst REPLACEMENTS: Readonly<Record<string, string>> = {\n input: \"Input\",\n select: \"Select\",\n textarea: \"Textarea\",\n dialog: \"Dialog\",\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-shadcn\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Prefer shadcn/ui form primitives over native `<input>`, `<select>`, `<textarea>`, and `<dialog>` elements.\",\n },\n schema: [],\n messages: {\n preferShadcn:\n \"Use the shadcn <{{replacement}}> component from @/components/ui/{{lowercase}} instead of native <{{element}}>.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n JSXOpeningElement(node: TSESTree.JSXOpeningElement): void {\n // Only lowercase JSXIdentifier names represent native HTML elements.\n // Member expressions (`Foo.Bar`) and namespaces (`svg:path`) are skipped.\n if (node.name.type !== \"JSXIdentifier\") {\n return;\n }\n\n const elementName = node.name.name;\n const replacement = REPLACEMENTS[elementName];\n\n if (replacement === undefined) {\n return;\n }\n\n context.report({\n node,\n messageId: \"preferShadcn\",\n data: {\n element: elementName,\n replacement,\n lowercase: elementName,\n },\n });\n },\n };\n },\n});\n","import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"missingAssertNever\";\ntype Options = readonly [];\n\n/**\n * Matches a call to `assertNever(...)` — either the bare identifier form\n * (`assertNever(x)`) or a namespaced member form (`utils.assertNever(x)`).\n */\nconst isAssertNeverCall = (expression: TSESTree.Expression): boolean => {\n if (expression.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = expression.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name === \"assertNever\";\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name === \"assertNever\";\n }\n return false;\n};\n\nconst statementContainsAssertNever = (\n statement: TSESTree.Statement,\n): boolean => {\n if (statement.type === AST_NODE_TYPES.ExpressionStatement) {\n return isAssertNeverCall(statement.expression);\n }\n if (statement.type === AST_NODE_TYPES.ThrowStatement) {\n return isAssertNeverCall(statement.argument);\n }\n if (statement.type === AST_NODE_TYPES.ReturnStatement) {\n return (\n statement.argument !== null && isAssertNeverCall(statement.argument)\n );\n }\n // Recurse into block-scoped default bodies like `default: { ... }`\n if (statement.type === AST_NODE_TYPES.BlockStatement) {\n return statement.body.some(statementContainsAssertNever);\n }\n return false;\n};\n\n/**\n * Returns true if the statement performs some runtime work. An empty statement\n * or an empty block does nothing; everything else (`return`, `throw`, `break`,\n * a function call, an `if`, ...) is treated as legitimate runtime handling of\n * the default case.\n */\nconst isRuntimeHandlingStatement = (statement: TSESTree.Statement): boolean => {\n if (statement.type === AST_NODE_TYPES.EmptyStatement) return false;\n if (statement.type === AST_NODE_TYPES.BlockStatement) {\n return statement.body.some(isRuntimeHandlingStatement);\n }\n return true;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"require-assert-never\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require an exhaustive-style switch whose `default` case does no runtime work to call `assertNever(_)` so that discriminated unions are exhaustively checked at compile time. Switches with a legitimate runtime default (a reducer's `return state`, an HTTP-status `return fallback()`, a `break`, a `throw`, etc.) are left alone.\",\n },\n schema: [],\n messages: {\n missingAssertNever:\n \"Empty switch `default` case — add runtime handling or call `assertNever()` so the discriminated union is exhaustively checked at compile time.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n SwitchStatement(node: TSESTree.SwitchStatement): void {\n const defaultCase = node.cases.find(\n (caseNode): caseNode is TSESTree.SwitchCase => caseNode.test === null,\n );\n // No `default` at all is fine — we don't demand exhaustiveness of every\n // switch, only of those that opted into a (no-op) default.\n if (!defaultCase) return;\n\n // An explicit `assertNever(...)` is the canonical exhaustiveness check.\n if (defaultCase.consequent.some(statementContainsAssertNever)) return;\n\n // A default that does real runtime work (return a fallback, break,\n // throw, log, ...) is legitimate — don't demand assertNever there.\n if (defaultCase.consequent.some(isRuntimeHandlingStatement)) return;\n\n // Otherwise the default is empty / a pure no-op: flag it.\n context.report({\n node: defaultCase,\n messageId: \"missingAssertNever\",\n });\n },\n };\n },\n});\n","import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"missingZodValidation\";\ntype Options = readonly [];\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\n// A receiver name that looks like a Zod schema: ends in `Schema`, or uses the\n// `Z<Capital>` house convention (e.g. `ZUser`), or the bare `z` builder.\nconst ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;\n\n/**\n * Walk down a (possibly chained) receiver expression and decide whether it\n * originates from something that looks like a Zod schema — the bare `z` builder\n * (`z.object({...}).parse(...)`), a `Schema`-suffixed identifier\n * (`userSchema.parse(...)`), or a `Z`-prefixed identifier (`ZUser.parse(...)`).\n * Non-Zod receivers like `JSON` / `Date` are intentionally rejected.\n */\nconst looksLikeZodSchema = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n while (true) {\n if (current.type === AST_NODE_TYPES.Identifier) {\n return current.name === \"z\" || ZOD_SCHEMA_NAME_RE.test(current.name);\n }\n if (current.type === AST_NODE_TYPES.CallExpression) {\n current = current.callee;\n continue;\n }\n if (current.type === AST_NODE_TYPES.MemberExpression) {\n current = current.object;\n continue;\n }\n return false;\n }\n};\n\n/**\n * Matches a Zod validation call: `<ZodSchema>.parse(...)` or\n * `<ZodSchema>.safeParse(...)`. Keys off the *receiver* looking like a Zod\n * schema rather than the method name alone, so `JSON.parse(...)` /\n * `Date.parse(...)` are NOT treated as validation.\n */\nconst isZodParseCall = (node: TSESTree.Node): boolean => {\n if (node.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;\n if (callee.computed) return false;\n if (callee.property.type !== AST_NODE_TYPES.Identifier) return false;\n const method = callee.property.name;\n if (method !== \"parse\" && method !== \"safeParse\") return false;\n return looksLikeZodSchema(callee.object);\n};\n\n/**\n * Matches an (optionally awaited) `<x>.formData()` call — the canonical way a\n * `FormData` object is obtained from a `Request` / `Response`.\n */\nconst isFormDataMethodCall = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n if (current.type === AST_NODE_TYPES.AwaitExpression) {\n current = current.argument;\n }\n if (current.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = current.callee;\n return (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier &&\n callee.property.name === \"formData\"\n );\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"require-zod-form-validation\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.\",\n },\n schema: [],\n messages: {\n missingZodValidation:\n \"FormData parsing must use Zod schema validation (e.g., Schema.parse() / Schema.safeParse())\",\n },\n },\n defaultOptions: [],\n create(context: Ctx) {\n // A receiver is a FormData source if its name reads like form data, or if\n // it is a binding initialized from a `.formData()` call.\n const isFormSourceIdentifier = (node: TSESTree.Node): boolean => {\n if (node.type !== AST_NODE_TYPES.Identifier) return false;\n if (/formdata/i.test(node.name)) return true;\n\n let scope: Scope.Scope | null = context.sourceCode.getScope(node);\n while (scope !== null) {\n const variable = scope.set.get(node.name);\n if (variable !== undefined && variable.defs.length === 1) {\n const def = variable.defs[0];\n if (\n def !== undefined &&\n def.type === \"Variable\" &&\n def.node.type === AST_NODE_TYPES.VariableDeclarator &&\n def.node.init !== null\n ) {\n return isFormDataMethodCall(def.node.init);\n }\n return false;\n }\n scope = scope.upper;\n }\n return false;\n };\n\n const isFormDataGetCall = (node: TSESTree.CallExpression): boolean => {\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;\n if (\n callee.property.type !== AST_NODE_TYPES.Identifier ||\n callee.property.name !== \"get\"\n ) {\n return false;\n }\n return isFormSourceIdentifier(callee.object);\n };\n\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isFormDataGetCall(node)) return;\n\n // Walk up the parent chain to find a surrounding Zod `.parse(...)` /\n // `.safeParse(...)` call. `.parent` is `null` at the Program root, so we\n // must guard for both null and undefined.\n let parent: TSESTree.Node | null | undefined = node.parent;\n while (parent !== null && parent !== undefined) {\n if (isZodParseCall(parent)) return;\n parent = parent.parent;\n }\n\n context.report({\n node,\n messageId: \"missingZodValidation\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Enforce the `Z`-prefix naming convention for Zod schemas\n * (`ZUser = z.object({...})`).\n *\n * NOTE on audit backing: this is an intentional org-wide convention, not a\n * direct mapping of `readability-and-naming.md` (which governs property-name\n * casing, not schema-variable prefixes). The `Z` prefix lets schemas and their\n * inferred types share a base name (`ZUser` / `type User = z.infer<typeof\n * ZUser>`) without collision. Kept as-is by design.\n */\n\nimport { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"zPrefix\";\ntype Options = readonly [];\n\n/**\n * Walks down a (possibly chained) callee like `z.object().extend().refine()` and\n * returns `true` if the chain originates from a bare `z` identifier — i.e. the\n * outermost MemberExpression on the chain has `z` as its receiver.\n */\nconst calleeChainStartsWithZ = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n\n while (current.type === AST_NODE_TYPES.MemberExpression) {\n const receiver: TSESTree.Node = current.object;\n if (receiver.type === AST_NODE_TYPES.Identifier && receiver.name === \"z\") {\n return true;\n }\n if (receiver.type === AST_NODE_TYPES.CallExpression) {\n current = receiver.callee;\n continue;\n }\n return false;\n }\n\n return false;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"zod-naming-convention\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce Zod schemas to be named with a Z prefix (e.g. `ZUser = z.object({...})`).\",\n },\n schema: [],\n messages: {\n zPrefix: \"Zod schema names should start with Z\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n VariableDeclarator(node: TSESTree.VariableDeclarator): void {\n const init = node.init;\n if (init === null || init === undefined) return;\n if (init.type !== AST_NODE_TYPES.CallExpression) return;\n\n const callee = init.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return;\n\n if (!calleeChainStartsWithZ(callee)) return;\n\n if (node.id.type !== AST_NODE_TYPES.Identifier) return;\n const variableName = node.id.name;\n if (variableName.startsWith(\"Z\")) return;\n\n context.report({\n node: node.id,\n messageId: \"zPrefix\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview TS port of Python SARJ028\n * (`no-cors-wildcard-with-credentials`). Flags CORS configuration that reflects\n * ANY origin (`\"*\"`) while ALSO allowing credentials. The browser treats\n * `Access-Control-Allow-Origin: *` together with\n * `Access-Control-Allow-Credentials: true` as a directive to reflect the\n * request's Origin and expose authenticated (cookie/session) responses — which\n * lets any website read them cross-origin. That is a credential-theft surface.\n *\n * Two shapes are detected, and BOTH the wildcard origin and credentials=true\n * must co-occur before the rule fires (a `\"*\"` origin without credentials, or\n * credentials with a specific origin, is safe and is NOT reported):\n *\n * 1. A `cors(...)` / `new Cors(...)` call whose options `ObjectExpression`\n * has `credentials: true` AND an `origin` property whose value subtree\n * contains a `\"*\"` string literal anywhere — the bare `\"*\"`, the `[\"*\"]`\n * array, or a `flag ? origins : \"*\"` conditional branch. Reported at the\n * call.\n *\n * 2. Manual header setting where, within the SAME function (or module) scope,\n * `Access-Control-Allow-Origin` is set to `\"*\"` AND\n * `Access-Control-Allow-Credentials` is set to `\"true\"` — via\n * `res.setHeader(...)`, `headers.set(...)` / `.append(...)` (covers\n * `NextResponse` header objects), or a single object literal\n * `{ \"Access-Control-Allow-Origin\": \"*\", \"Access-Control-Allow-Credentials\": \"true\" }`.\n * Header-name matching is case-insensitive. The object-literal form is\n * reported at the object; the split `setHeader`/`set` form is reported at\n * the wildcard-origin call.\n *\n * References:\n * - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"corsWildcardWithCredentials\";\ntype Options = readonly [];\n\nconst ACAO_HEADER = \"access-control-allow-origin\";\nconst ACAC_HEADER = \"access-control-allow-credentials\";\nconst HEADER_SET_METHODS = new Set([\"setheader\", \"set\", \"append\"]);\n\n/**\n * True only for the boolean literal `true` (not `1`, not a truthy expression).\n */\nfunction isTrueLiteral(node: TSESTree.Node): boolean {\n return node.type === \"Literal\" && node.value === true;\n}\n\n/**\n * True if `node` is a string literal whose value equals `\"true\"`\n * (case-insensitive), or the boolean literal `true`. Header values are strings,\n * but some frameworks coerce a boolean, so both are accepted.\n */\nfunction isCredentialsTrueValue(node: TSESTree.Node): boolean {\n if (node.type === \"Literal\") {\n if (node.value === true) {\n return true;\n }\n if (typeof node.value === \"string\") {\n return node.value.trim().toLowerCase() === \"true\";\n }\n }\n return false;\n}\n\n/**\n * True if `node` is the string literal `\"*\"`.\n */\nfunction isStarLiteral(node: TSESTree.Node): boolean {\n return node.type === \"Literal\" && node.value === \"*\";\n}\n\n/**\n * True if a `\"*\"` string literal appears anywhere in `node`'s subtree. Walking\n * the whole subtree catches `\"*\"`, `[\"*\"]`, and the `flag ? origins : \"*\"`\n * conditional branch. A dynamic `origin: someVar` has no `\"*\"` literal, so it\n * does not fire.\n */\nfunction subtreeContainsStarLiteral(node: TSESTree.Node): boolean {\n if (isStarLiteral(node)) {\n return true;\n }\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") {\n continue;\n }\n const value = (node as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child) && subtreeContainsStarLiteral(child)) {\n return true;\n }\n }\n } else if (isNode(value) && subtreeContainsStarLiteral(value)) {\n return true;\n }\n }\n return false;\n}\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\n/**\n * Returns the (non-computed) string name of a property key, or `undefined`.\n */\nfunction propertyKeyName(prop: TSESTree.Property): string | undefined {\n if (prop.computed) {\n return undefined;\n }\n const key = prop.key;\n if (key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n}\n\n/**\n * Extracts the callee's terminal identifier name for a call/new expression\n * (`cors` for `cors(...)` and `app.cors(...)`, `Cors` for `new Cors(...)`).\n */\nfunction calleeName(\n node: TSESTree.CallExpression | TSESTree.NewExpression,\n): string | undefined {\n const callee = node.callee;\n if (callee.type === \"Identifier\") {\n return callee.name;\n }\n if (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.property.type === \"Identifier\"\n ) {\n return callee.property.name;\n }\n return undefined;\n}\n\n/**\n * Detects the `cors({ origin: \"*\", credentials: true })` shape. Returns true\n * when the callee is `cors` / `Cors` and the first ObjectExpression argument\n * has `credentials: true` AND an `origin` whose subtree contains `\"*\"`.\n */\nfunction isCorsWildcardCredentialsCall(\n node: TSESTree.CallExpression | TSESTree.NewExpression,\n): boolean {\n const name = calleeName(node);\n if (name === undefined || name.toLowerCase() !== \"cors\") {\n return false;\n }\n const options = node.arguments.find(\n (arg): arg is TSESTree.ObjectExpression => arg.type === \"ObjectExpression\",\n );\n if (options === undefined) {\n return false;\n }\n let hasCredentials = false;\n let hasWildcardOrigin = false;\n for (const prop of options.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const key = propertyKeyName(prop);\n if (key === \"credentials\" && isTrueLiteral(prop.value)) {\n hasCredentials = true;\n } else if (key === \"origin\" && subtreeContainsStarLiteral(prop.value)) {\n hasWildcardOrigin = true;\n }\n }\n return hasCredentials && hasWildcardOrigin;\n}\n\n/**\n * True if the ObjectExpression is a header map setting BOTH\n * `Access-Control-Allow-Origin: \"*\"` and\n * `Access-Control-Allow-Credentials: \"true\"` (case-insensitive keys).\n */\nfunction isWildcardCredentialsHeaderObject(\n node: TSESTree.ObjectExpression,\n): boolean {\n let wildcardOrigin = false;\n let credentialsTrue = false;\n for (const prop of node.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const key = propertyKeyName(prop);\n if (key === undefined) {\n continue;\n }\n const header = key.toLowerCase();\n if (header === ACAO_HEADER && isStarLiteral(prop.value)) {\n wildcardOrigin = true;\n } else if (header === ACAC_HEADER && isCredentialsTrueValue(prop.value)) {\n credentialsTrue = true;\n }\n }\n return wildcardOrigin && credentialsTrue;\n}\n\ntype HeaderSetKind = \"origin\" | \"credentials\";\n\n/**\n * Classifies a `x.setHeader(name, value)` / `x.set(name, value)` /\n * `x.append(name, value)` call as an ACAO-wildcard set, an ACAC-true set, or\n * neither.\n */\nfunction classifyHeaderSetCall(\n node: TSESTree.CallExpression,\n): HeaderSetKind | undefined {\n const callee = node.callee;\n if (\n callee.type !== \"MemberExpression\" ||\n callee.computed ||\n callee.property.type !== \"Identifier\" ||\n !HEADER_SET_METHODS.has(callee.property.name.toLowerCase())\n ) {\n return undefined;\n }\n const [nameArg, valueArg] = node.arguments;\n if (\n nameArg === undefined ||\n valueArg === undefined ||\n nameArg.type !== \"Literal\" ||\n typeof nameArg.value !== \"string\"\n ) {\n return undefined;\n }\n const header = nameArg.value.toLowerCase();\n if (header === ACAO_HEADER && isStarLiteral(valueArg)) {\n return \"origin\";\n }\n if (header === ACAC_HEADER && isCredentialsTrueValue(valueArg)) {\n return \"credentials\";\n }\n return undefined;\n}\n\n/**\n * Nearest enclosing function node, or `undefined` for module scope. Used to\n * group split `setHeader`/`set` header assignments so a wildcard origin and a\n * credentials=true set only pair up when they live in the same scope.\n */\nfunction enclosingScope(node: TSESTree.Node): TSESTree.Node | undefined {\n let current: TSESTree.Node | undefined = node.parent;\n while (current) {\n if (\n current.type === \"FunctionDeclaration\" ||\n current.type === \"FunctionExpression\" ||\n current.type === \"ArrowFunctionExpression\"\n ) {\n return current;\n }\n current = current.parent;\n }\n return undefined;\n}\n\ninterface ScopeHeaderSets {\n originNodes: TSESTree.CallExpression[];\n credentialsNodes: TSESTree.CallExpression[];\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-cors-wildcard-with-credentials\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n 'Disallow CORS that reflects any Origin (`\"*\"`) while allowing credentials; any site could then read authenticated responses. Enumerate explicit trusted origins instead.',\n },\n schema: [],\n messages: {\n corsWildcardWithCredentials:\n 'CORS reflects any Origin (`\"*\"`) while allowing credentials — any site can read authenticated responses. Enumerate explicit trusted origins instead of using `\"*\"` with credentials.',\n },\n },\n defaultOptions: [],\n create(context) {\n const scopeHeaderSets = new Map<TSESTree.Node | \"module\", ScopeHeaderSets>();\n\n function recordHeaderSet(\n node: TSESTree.CallExpression,\n kind: HeaderSetKind,\n ): void {\n const key = enclosingScope(node) ?? \"module\";\n let entry = scopeHeaderSets.get(key);\n if (entry === undefined) {\n entry = { originNodes: [], credentialsNodes: [] };\n scopeHeaderSets.set(key, entry);\n }\n if (kind === \"origin\") {\n entry.originNodes.push(node);\n } else {\n entry.credentialsNodes.push(node);\n }\n }\n\n return {\n NewExpression(node: TSESTree.NewExpression): void {\n if (isCorsWildcardCredentialsCall(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n }\n },\n CallExpression(node: TSESTree.CallExpression): void {\n if (isCorsWildcardCredentialsCall(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n return;\n }\n const kind = classifyHeaderSetCall(node);\n if (kind !== undefined) {\n recordHeaderSet(node, kind);\n }\n },\n ObjectExpression(node: TSESTree.ObjectExpression): void {\n if (isWildcardCredentialsHeaderObject(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n }\n },\n \"Program:exit\"(): void {\n for (const { originNodes, credentialsNodes } of scopeHeaderSets.values()) {\n if (originNodes.length > 0 && credentialsNodes.length > 0) {\n for (const node of originNodes) {\n context.report({\n node,\n messageId: \"corsWildcardWithCredentials\",\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `try` blocks whose body contains more than three\n * top-level statements that can throw (TS port of Python's SARJ007).\n *\n * A fat `try` body obscures which statement is actually expected to throw and\n * widens the blast radius of the `catch` handler: unrelated failures get caught\n * (and often swallowed or mis-reported) by a handler written for a different\n * operation. Keep the `try` skinny — isolate the throwing statement(s) and move\n * the non-throwing setup and follow-up work outside.\n *\n * Only top-level statements that can *throw* are counted. What counts, and the\n * guards that keep the count aligned with intent (tuned against ~5.6k real TS\n * files to drive false positives to ~zero):\n *\n * - An `await` always counts — awaiting a promise is the canonical throwing\n * operation in async TS. A statement with an `await` in its same-scope\n * subtree counts.\n * - A synchronous call / `new` whose value is *used* (assigned, returned,\n * branched on, or passed as an argument) counts — e.g. `const x = parse(s)`,\n * `return build(x)`, `if (!validate(x))`.\n * - A bare fire-and-forget call statement with no `await` does NOT count. In\n * idiomatic TS these are side effects — React state setters (`setOpen(false)`),\n * toasts (`toast.error(...)`), `router.refresh()`, logging, optional\n * callbacks (`onSuccess?.()`). They are the post-success UI work that\n * naturally trails the one awaited action; counting them flagged nearly\n * every event handler.\n * - Pure, non-throwing array / string / `Map` / `Object` / `Math` / `JSON`\n * helpers (`.map`, `.filter`, `.push`, `.get`, `.join`, `Object.keys`, ...)\n * do NOT count — they are data plumbing, not the operation being guarded.\n * - Calls inside a nested function / arrow body do not run when the `try`\n * executes, so they are not counted (same-scope walk).\n *\n * Two structural exemptions match the Python rule:\n *\n * - A `finally` clause is a deliberate cleanup contract that couples the body\n * to the handler — exempt.\n * - A `catch` handler guaranteed to re-throw (its body's last statement is a\n * `throw`) makes the wide body uniform error-context wrapping, not an\n * over-broad swallow — exempt.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"fatTryBlock\";\ntype Options = readonly [];\n\nconst MAX_TRY_BODY_STATEMENTS = 3;\n\nconst NESTED_FUNCTION_TYPES = new Set<AST_NODE_TYPES>([\n AST_NODE_TYPES.FunctionDeclaration,\n AST_NODE_TYPES.FunctionExpression,\n AST_NODE_TYPES.ArrowFunctionExpression,\n]);\n\n/** Non-throwing member methods — array / string / Map / Set data plumbing. */\nconst PURE_METHODS = new Set<string>([\n \"map\", \"filter\", \"forEach\", \"reduce\", \"reduceRight\", \"find\", \"findIndex\",\n \"findLast\", \"findLastIndex\", \"some\", \"every\", \"push\", \"pop\", \"shift\",\n \"unshift\", \"slice\", \"splice\", \"concat\", \"flat\", \"flatMap\", \"join\", \"reverse\",\n \"sort\", \"fill\", \"includes\", \"indexOf\", \"lastIndexOf\", \"at\", \"keys\", \"values\",\n \"entries\", \"has\", \"get\", \"set\", \"add\", \"delete\", \"clear\", \"toString\",\n \"toLocaleString\", \"valueOf\", \"charAt\", \"charCodeAt\", \"codePointAt\", \"split\",\n \"padStart\", \"padEnd\", \"repeat\", \"trim\", \"trimStart\", \"trimEnd\", \"toUpperCase\",\n \"toLowerCase\", \"toFixed\", \"toPrecision\", \"startsWith\", \"endsWith\",\n]);\n\n/** Non-throwing global namespaces called as `X.method(...)`. */\nconst PURE_NAMESPACES = new Set<string>([\n \"Object\", \"Array\", \"Math\", \"JSON\", \"Number\", \"String\", \"Boolean\", \"console\",\n]);\n\n/** Constructors that do not throw on construction. */\nconst PURE_CONSTRUCTORS = new Set<string>([\n \"Map\", \"Set\", \"WeakMap\", \"WeakSet\", \"Date\", \"Error\", \"TypeError\",\n \"RangeError\", \"Array\", \"Object\", \"Headers\", \"URLSearchParams\", \"FormData\",\n \"TextEncoder\", \"TextDecoder\", \"Blob\", \"ReadableStream\", \"WritableStream\",\n \"TransformStream\", \"Response\", \"AbortController\",\n]);\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\n/** A call whose value is a known pure, non-throwing helper. */\nfunction isPureCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) {\n return false;\n }\n const property = callee.property;\n if (property.type !== AST_NODE_TYPES.Identifier) {\n return false;\n }\n if (\n callee.object.type === AST_NODE_TYPES.Identifier &&\n PURE_NAMESPACES.has(callee.object.name)\n ) {\n return true;\n }\n return PURE_METHODS.has(property.name);\n}\n\nfunction isPureNew(node: TSESTree.NewExpression): boolean {\n return (\n node.callee.type === AST_NODE_TYPES.Identifier &&\n PURE_CONSTRUCTORS.has(node.callee.name)\n );\n}\n\n/**\n * Walk `stmt`'s same-scope subtree (not descending into nested function/arrow\n * bodies) until `predicate` matches a node.\n */\nfunction subtreeMatches(\n stmt: TSESTree.Node,\n predicate: (node: TSESTree.Node) => boolean,\n): boolean {\n let found = false;\n\n const visit = (current: TSESTree.Node): void => {\n if (found) {\n return;\n }\n if (predicate(current)) {\n found = true;\n return;\n }\n for (const key of Object.keys(current)) {\n if (key === \"parent\") {\n continue;\n }\n if (NESTED_FUNCTION_TYPES.has(current.type) && key === \"body\") {\n continue;\n }\n const value = (current as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child)) {\n visit(child);\n }\n }\n } else if (isNode(value)) {\n visit(value);\n }\n if (found) {\n return;\n }\n }\n };\n\n visit(stmt);\n return found;\n}\n\nconst hasAwait = (stmt: TSESTree.Statement): boolean =>\n subtreeMatches(stmt, (n) => n.type === AST_NODE_TYPES.AwaitExpression);\n\nconst hasThrowingCallOrNew = (stmt: TSESTree.Statement): boolean =>\n subtreeMatches(\n stmt,\n (n) =>\n (n.type === AST_NODE_TYPES.CallExpression && !isPureCall(n)) ||\n (n.type === AST_NODE_TYPES.NewExpression && !isPureNew(n)),\n );\n\n/** Unwrap `await` / optional-chain / non-null wrappers to the core expression. */\nfunction unwrap(expr: TSESTree.Expression): TSESTree.Expression {\n let current = expr;\n while (\n current.type === AST_NODE_TYPES.ChainExpression ||\n current.type === AST_NODE_TYPES.TSNonNullExpression\n ) {\n current = current.expression;\n }\n return current;\n}\n\n/**\n * Whether a top-level try-body statement can plausibly throw when the `try`\n * runs. See the file overview for the guards; the key ones are: `await` always\n * counts, and a bare fire-and-forget call statement (no `await`) does not.\n */\nfunction canThrow(stmt: TSESTree.Statement): boolean {\n if (hasAwait(stmt)) {\n return true;\n }\n if (\n stmt.type === AST_NODE_TYPES.ExpressionStatement &&\n unwrap(stmt.expression).type === AST_NODE_TYPES.CallExpression\n ) {\n return false;\n }\n return hasThrowingCallOrNew(stmt);\n}\n\n/**\n * Conservative: is the `catch` handler guaranteed to re-throw? True when a\n * handler is present and its body's last statement is a `throw`.\n */\nfunction handlerRethrows(handler: TSESTree.CatchClause | null): boolean {\n if (handler === null) {\n return false;\n }\n const body = handler.body.body;\n const last = body[body.length - 1];\n return last !== undefined && last.type === AST_NODE_TYPES.ThrowStatement;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-fat-try-blocks\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `try` blocks with more than three top-level statements that can throw — isolate the throwing statement and move non-throwing work outside.\",\n },\n schema: [],\n messages: {\n fatTryBlock:\n \"This `try` block has {{count}} statements that can throw (max {{max}}). Isolate the throwing statement(s); move non-throwing work outside the `try`.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const sourceCode = context.sourceCode;\n\n return {\n TryStatement(node: TSESTree.TryStatement): void {\n if (node.finalizer !== null) {\n return;\n }\n if (handlerRethrows(node.handler)) {\n return;\n }\n\n const count = node.block.body.filter(canThrow).length;\n if (count <= MAX_TRY_BODY_STATEMENTS) {\n return;\n }\n\n const tryKeyword = sourceCode.getFirstToken(node);\n context.report({\n node: tryKeyword ?? node,\n messageId: \"fatTryBlock\",\n data: { count, max: MAX_TRY_BODY_STATEMENTS },\n });\n },\n };\n },\n});\n","/**\n * @fileoverview TS port of SARJ012 (`no-secret-in-log`). Passing a secret value\n * (token, password, api key, jwt, credential, signature, ...) to a logging call\n * leaks it into log sinks — files, stdout, log aggregators — where it persists\n * far beyond its intended lifetime and is readable by anyone with log access.\n * Prefer redaction (`tokenPrefix: token.slice(0, 6)`) or omission.\n *\n * We fire on a logging call (`logger.info(...)`, `log.error(...)`, loguru/bind\n * builder chains, etc.) that passes a secret-named value either as a property of\n * an object argument (`logger.error(\"msg\", { token, apiKey })`) or as a bare\n * secret-named positional identifier (`logger.info(\"x\", password)`).\n *\n * The secret-name predicate matches a secret word only as a WHOLE token (after\n * snake_case / camelCase splitting) and disqualifies identifiers whose trailing\n * token is a counter / row-id / flag marker (`tokenCount`, `apiKeyId`,\n * `passwordEnabled`), so metadata *about* a secret is not mistaken for the\n * secret itself. Redaction markers (prefix/mask/hash/redact/tag) are exempt.\n *\n * References:\n * - https://owasp.org/www-community/vulnerabilities/Information_exposure_through_log_files\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSecretInLog\";\ntype Options = readonly [];\n\nconst LOG_METHODS: ReadonlySet<string> = new Set([\n \"debug\",\n \"info\",\n \"warn\",\n \"warning\",\n \"error\",\n \"exception\",\n \"critical\",\n \"trace\",\n \"log\",\n \"fatal\",\n \"success\",\n]);\n\nconst LOGGER_NAMES: ReadonlySet<string> = new Set([\n \"logger\",\n \"log\",\n \"logging\",\n \"loguru\",\n \"console\",\n \"_logger\",\n \"_log\",\n]);\n\nconst LOGGER_FACTORIES: ReadonlySet<string> = new Set([\"getlogger\", \"get_logger\"]);\n\nconst SECRET_WORDS: ReadonlySet<string> = new Set([\n \"token\",\n \"secret\",\n \"password\",\n \"passwd\",\n \"jwt\",\n \"secrets\",\n \"passwords\",\n \"credential\",\n \"credentials\",\n \"authorization\",\n \"signature\",\n \"hmac\",\n \"digest\",\n \"hash\",\n \"apikey\",\n]);\n\nconst INNOCUOUS_WORDS: ReadonlySet<string> = new Set([\n \"count\",\n \"counts\",\n \"budget\",\n \"limit\",\n \"limits\",\n \"id\",\n \"ids\",\n \"enabled\",\n \"disabled\",\n \"flag\",\n \"flags\",\n \"present\",\n \"set\",\n \"unset\",\n \"configured\",\n \"missing\",\n \"required\",\n \"valid\",\n \"invalid\",\n \"exists\",\n \"type\",\n \"types\",\n \"name\",\n \"names\",\n \"label\",\n \"labels\",\n \"title\",\n \"expiry\",\n \"expiration\",\n \"expires\",\n \"ttl\",\n \"version\",\n \"versions\",\n \"policy\",\n \"rotation\",\n \"arn\",\n \"path\",\n \"paths\",\n \"issuer\",\n \"audience\",\n \"strength\",\n \"manager\",\n \"service\",\n \"services\",\n \"repository\",\n \"provider\",\n \"providers\",\n \"store\",\n \"factory\",\n \"handler\",\n \"controller\",\n \"bucket\",\n \"url\",\n \"uri\",\n \"endpoint\",\n \"endpoints\",\n \"scope\",\n \"scopes\",\n \"event\",\n \"events\",\n \"format\",\n \"at\",\n \"len\",\n \"length\",\n]);\n\nconst REDACTION_RE = /prefix|suffix|redact|mask|hash|hint|_len|length/i;\nconst WHOLE_TOKEN_REDACTION_MARKERS: ReadonlySet<string> = new Set([\"tag\"]);\n\nconst CAMEL_RE = /[A-Z]+(?=[A-Z][a-z])|[A-Z]?[a-z]+|[A-Z]+|\\d+/g;\nconst SEGMENT_RE = /[^A-Za-z0-9]+/;\n\n/**\n * Ordered lowercase tokens from snake_case + camelCase decomposition. Also\n * yields each whole snake/kebab segment lowercased, so a pathological mixed-case\n * word still surfaces its intended form.\n */\nfunction tokenize(identifier: string): string[] {\n const tokens: string[] = [];\n for (const segment of identifier.split(SEGMENT_RE)) {\n if (!segment) {\n continue;\n }\n tokens.push(segment.toLowerCase());\n for (const part of segment.match(CAMEL_RE) ?? []) {\n tokens.push(part.toLowerCase());\n }\n }\n return tokens;\n}\n\n/** True if `api` is immediately followed by `key` (the split form of `api_key`). */\nfunction hasApiKey(tokens: readonly string[]): boolean {\n for (let i = 0; i + 1 < tokens.length; i++) {\n if (tokens[i] === \"api\" && tokens[i + 1] === \"key\") {\n return true;\n }\n }\n return false;\n}\n\n/** True if `identifier` names raw secret material (a credential, not metadata). */\nfunction isSecretName(identifier: string): boolean {\n const tokens = tokenize(identifier);\n const last = tokens.at(-1);\n if (last !== undefined && INNOCUOUS_WORDS.has(last)) {\n return false;\n }\n if (tokens.some((tok) => SECRET_WORDS.has(tok))) {\n return true;\n }\n return hasApiKey(tokens);\n}\n\n/** True if the name names a raw secret and is not a redacted derivative. */\nfunction isSecretKeyword(name: string): boolean {\n if (REDACTION_RE.test(name)) {\n return false;\n }\n if (tokenize(name).some((tok) => WHOLE_TOKEN_REDACTION_MARKERS.has(tok))) {\n return false;\n }\n return isSecretName(name);\n}\n\n/**\n * True if `expr` evaluates to a logger. Resolves the whole receiver chain so\n * adapter/builder/factory calls are caught: `logger.bind(...).info(...)`,\n * `logging.getLogger(name).info(...)`, `this.logger.error(...)`.\n */\nfunction isLoggerExpr(expr: TSESTree.Expression | TSESTree.PrivateIdentifier): boolean {\n switch (expr.type) {\n case \"Identifier\":\n return LOGGER_NAMES.has(expr.name.toLowerCase());\n case \"MemberExpression\": {\n const { property, object } = expr;\n if (!expr.computed && property.type === \"Identifier\") {\n const lowered = property.name.toLowerCase();\n if (LOGGER_NAMES.has(lowered) || LOGGER_FACTORIES.has(lowered)) {\n return true;\n }\n }\n return isLoggerExpr(object);\n }\n case \"CallExpression\": {\n const callee = expr.callee;\n if (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.property.type === \"Identifier\" &&\n LOGGER_FACTORIES.has(callee.property.name.toLowerCase())\n ) {\n return true;\n }\n if (callee.type !== \"Super\") {\n return isLoggerExpr(callee);\n }\n return false;\n }\n default:\n return false;\n }\n}\n\n/**\n * True if `prop`'s value is the raw secret rather than a redacted/derived form.\n * Shorthand (`{ token }`), a bare identifier (`{ apiKey: theKey }`), or a plain\n * member access (`{ apiKey: config.apiKey }`) all carry the secret verbatim. A\n * call (`token.slice(0, 6)`, `mask(token)`), template literal, ternary, concat,\n * or literal placeholder (`\"***\"`) is already redacted — logging it is safe.\n */\nfunction isRawSecretValue(prop: TSESTree.Property): boolean {\n if (prop.shorthand) {\n return true;\n }\n return prop.value.type === \"Identifier\" || prop.value.type === \"MemberExpression\";\n}\n\n/** The static string name of an object-property key, or null when not statically named. */\nfunction propertyKeyName(prop: TSESTree.Property): string | null {\n if (prop.computed) {\n return null;\n }\n if (prop.key.type === \"Identifier\") {\n return prop.key.name;\n }\n if (prop.key.type === \"Literal\" && typeof prop.key.value === \"string\") {\n return prop.key.value;\n }\n return null;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-secret-in-log\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow passing a secret-named value to a logging call; it leaks to log sinks. Redact or omit it.\",\n },\n schema: [],\n messages: {\n noSecretInLog:\n \"Secret `{{name}}` passed to a logging call leaks it to log sinks. Redact (e.g. `{{name}}Prefix: {{name}}.slice(0, 6)`) or omit it.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n const callee = node.callee;\n if (\n callee.type !== \"MemberExpression\" ||\n callee.computed ||\n callee.property.type !== \"Identifier\" ||\n !LOG_METHODS.has(callee.property.name)\n ) {\n return;\n }\n if (!isLoggerExpr(callee.object)) {\n return;\n }\n\n for (const arg of node.arguments) {\n if (arg.type === \"Identifier\") {\n if (isSecretKeyword(arg.name)) {\n context.report({\n node: arg,\n messageId: \"noSecretInLog\",\n data: { name: arg.name },\n });\n }\n continue;\n }\n if (arg.type === \"ObjectExpression\") {\n for (const prop of arg.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const keyName = propertyKeyName(prop);\n if (keyName !== null && isSecretKeyword(keyName) && isRawSecretValue(prop)) {\n context.report({\n node: prop,\n messageId: \"noSecretInLog\",\n data: { name: keyName },\n });\n }\n }\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag raw `string` used where a closed enumeration is clearly\n * intended, and comparison clusters against a fixed set of string literals.\n * The prescribed replacement is a string-literal union type\n * (`type Status = \"active\" | \"inactive\"`) — NOT a `StrEnum`/`enum`, since the\n * companion `no-enum` rule bans TypeScript enums.\n *\n * This is the TypeScript analog of the Python rule SARJ006 (prefer-str-enum).\n * It fires on two shapes:\n *\n * 1. **Choice-like field** — a `TSPropertySignature` (interface / type literal)\n * or class `PropertyDefinition` whose key's last word is one of the\n * high-precision CHOICE tokens (`status`, `state`, `kind`, `role`,\n * `priority`, `severity`, `direction`, `tier`, `stage`, `type`, `mode`,\n * `level`) and whose type annotation is the bare `string` keyword. Because\n * open-set API DTO fields (`status: string` from an untyped backend) are the\n * dominant false positive, a bare field fires ONLY when CORROBORATED by a\n * sibling string-literal-union member in the SAME interface / class / object\n * type. A file-wide comparison cluster on the field's name is deliberately\n * NOT used to corroborate: it flags unrelated same-named fields (DB-row casts\n * like `as Array<{ status: string }>`, passthrough DTOs). The closed-set fact\n * is still surfaced — as a `comparisonCluster` diagnostic at the comparison\n * site, which is the actionable location.\n *\n * 2. **Comparison cluster** — within one function scope, the same identifier or\n * member expression compared (`===` / `!==` / `==` / `!=`, or a `switch`)\n * against 2+ distinct short lowercase string literals (each matching\n * `^[a-z][a-z0-9_-]{0,30}$`). One diagnostic per cluster.\n *\n * `Literal`-union types (`type X = \"a\" | \"b\"`) are the target state and never\n * fire. Generated files (`*.gen.ts`, `**\\/generated/**`, `*.d.ts`, or a\n * `@generated` marker) opt out.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"bareChoiceField\" | \"comparisonCluster\";\ntype Options = readonly [];\n\nconst CHOICE_TOKENS: ReadonlySet<string> = new Set([\n \"status\",\n \"state\",\n \"kind\",\n \"role\",\n \"priority\",\n \"severity\",\n \"direction\",\n \"tier\",\n \"stage\",\n \"type\",\n \"mode\",\n \"level\",\n]);\n\nconst LOWER_TOKEN_RE = /^[a-z][a-z0-9_-]{0,30}$/;\nconst MIN_CLUSTER_SIZE = 2;\n\nconst BOOLEANISH: ReadonlySet<string> = new Set([\"true\", \"false\"]);\n\n/**\n * An enum-shaped token worth a string-literal union: a short lowercase word of\n * 2+ chars that isn't a boolean-string. Single characters (`'a'`), file\n * paths/URLs/i18n keys (contain `/`, `:`, `.`), and `'true'`/`'false'` are NOT\n * closed-enum members — comparing against them is a flag/path/boolean guard.\n */\nfunction isEnumToken(lit: string): boolean {\n return LOWER_TOKEN_RE.test(lit) && lit.length >= 2 && !BOOLEANISH.has(lit);\n}\n\nconst IGNORE_PATTERNS: readonly RegExp[] = [\n /[\\\\/]generated[\\\\/]/,\n /\\.gen\\.tsx?$/,\n /\\.generated\\.tsx?$/,\n /\\.d\\.ts$/,\n];\n\nfunction isIgnoredFile(filename: string, sourceText: string): boolean {\n if (IGNORE_PATTERNS.some((re) => re.test(filename))) {\n return true;\n }\n return /@generated\\b/.test(sourceText.slice(0, 1024));\n}\n\n/**\n * The trailing word of a camelCase / snake_case identifier, lowercased.\n * `callStatus` -> `status`, `user_role` -> `role`, `estate` -> `estate`.\n */\nfunction lastWord(name: string): string {\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/[_\\s]+/)\n .filter((w) => w.length > 0);\n const last = words[words.length - 1] ?? name;\n return last.toLowerCase();\n}\n\nfunction isChoiceLikeName(name: string): boolean {\n return CHOICE_TOKENS.has(lastWord(name));\n}\n\nfunction keyName(\n key: TSESTree.PropertyDefinition[\"key\"] | TSESTree.PropertyName,\n): string | null {\n if (key.type === AST_NODE_TYPES.Identifier) {\n return key.name;\n }\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") {\n return key.value;\n }\n return null;\n}\n\nfunction isStringLiteralMember(t: TSESTree.TypeNode): boolean {\n return (\n t.type === AST_NODE_TYPES.TSLiteralType &&\n t.literal.type === AST_NODE_TYPES.Literal &&\n typeof t.literal.value === \"string\"\n );\n}\n\n/** Whether a type node is a union of 2+ string-literal types. */\nfunction isStringLiteralUnion(node: TSESTree.TypeNode | undefined): boolean {\n if (node?.type !== AST_NODE_TYPES.TSUnionType) {\n return false;\n }\n return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;\n}\n\n/**\n * A union annotation that already expresses a closed set — it contains at least\n * one string-literal member, even mixed with a named type reference\n * (`AgentState | \"connecting\"`). Used to suppress comparison clusters on refs\n * the author has already given a union type; looser than\n * {@link isStringLiteralUnion}, which gates the DTO-sibling corroboration.\n */\nfunction isLikelyClosedUnion(node: TSESTree.TypeNode | undefined): boolean {\n return (\n node?.type === AST_NODE_TYPES.TSUnionType &&\n node.types.some(isStringLiteralMember)\n );\n}\n\ntype FunctionLike =\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression;\n\n/**\n * Property names in a type node that are themselves string-literal unions,\n * descending through inline object-type literals and their `&` / `|`\n * combinations (e.g. `Props & { side: \"a\" | \"b\" }` -> `{ side }`). Type\n * references to named types (`Props`) can't be resolved without type info and\n * are skipped.\n */\nfunction unionMemberNames(\n typeNode: TSESTree.TypeNode | undefined,\n out: Set<string>,\n): void {\n if (typeNode === undefined) {\n return;\n }\n if (\n typeNode.type === AST_NODE_TYPES.TSIntersectionType ||\n typeNode.type === AST_NODE_TYPES.TSUnionType\n ) {\n for (const t of typeNode.types) {\n unionMemberNames(t, out);\n }\n return;\n }\n if (typeNode.type !== AST_NODE_TYPES.TSTypeLiteral) {\n return;\n }\n for (const member of typeNode.members) {\n if (\n member.type === AST_NODE_TYPES.TSPropertySignature &&\n isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)\n ) {\n const propName = keyName(member.key);\n if (propName !== null) {\n out.add(propName);\n }\n }\n }\n}\n\nfunction bindingName(node: TSESTree.Node): string | null {\n const id = node.type === AST_NODE_TYPES.AssignmentPattern ? node.left : node;\n return id.type === AST_NODE_TYPES.Identifier ? id.name : null;\n}\n\n/**\n * Ref keys already declared with a string-literal union type — a comparison\n * cluster on such a ref is the target state, not a violation. Covers an\n * identifier param typed as a union (`m: \"a\" | \"b\"` -> `m`), an object-type\n * param property typed as a union (`o: { tier: \"a\" | \"b\" }` -> `o.tier`), and a\n * destructured prop typed as a union (`{ side }: Props & { side: \"a\" | \"b\" }`\n * -> `side`).\n */\nfunction addUnionRefsFromBinding(\n param: TSESTree.Parameter,\n out: Set<string>,\n): void {\n const binding =\n param.type === AST_NODE_TYPES.AssignmentPattern ? param.left : param;\n\n if (binding.type === AST_NODE_TYPES.ObjectPattern) {\n const members = new Set<string>();\n unionMemberNames(binding.typeAnnotation?.typeAnnotation, members);\n if (members.size === 0) {\n return;\n }\n for (const prop of binding.properties) {\n if (prop.type !== AST_NODE_TYPES.Property) {\n continue;\n }\n const propKey = keyName(prop.key);\n const local = bindingName(prop.value);\n if (propKey !== null && local !== null && members.has(propKey)) {\n out.add(local);\n }\n }\n return;\n }\n\n if (binding.type !== AST_NODE_TYPES.Identifier) {\n return;\n }\n const typeNode = binding.typeAnnotation?.typeAnnotation;\n if (isLikelyClosedUnion(typeNode)) {\n out.add(binding.name);\n return;\n }\n if (typeNode?.type === AST_NODE_TYPES.TSTypeLiteral) {\n for (const member of typeNode.members) {\n if (\n member.type === AST_NODE_TYPES.TSPropertySignature &&\n isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)\n ) {\n const propName = keyName(member.key);\n if (propName !== null) {\n out.add(`${binding.name}.${propName}`);\n }\n }\n }\n }\n}\n\nfunction unionRefsFromParams(fn: FunctionLike): Set<string> {\n const out = new Set<string>();\n for (const param of fn.params) {\n addUnionRefsFromBinding(param, out);\n }\n return out;\n}\n\n/** A stable key for a plain identifier or non-computed member chain, else null. */\nfunction refKey(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Identifier) {\n return node.name;\n }\n if (node.type === AST_NODE_TYPES.MemberExpression && !node.computed) {\n const inner = refKey(node.object);\n if (inner === null || node.property.type !== AST_NODE_TYPES.Identifier) {\n return null;\n }\n return `${inner}.${node.property.name}`;\n }\n return null;\n}\n\nfunction strLiteral(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Literal && typeof node.value === \"string\") {\n return node.value;\n }\n return null;\n}\n\ninterface ClusterEntry {\n node: TSESTree.Node;\n literals: Set<string>;\n allTokens: boolean;\n}\n\ninterface Scope {\n clusters: Map<string, ClusterEntry>;\n unionRefs: Set<string>;\n}\n\ninterface CollectedProperty {\n name: string;\n container: TSESTree.Node;\n node: TSESTree.Node;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-string-literal-union\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag raw `string` choice fields and string-literal comparison clusters; prefer a string-literal union type.\",\n },\n schema: [],\n messages: {\n bareChoiceField:\n '`{{name}}: string` looks like a choice field — prefer a string-literal union type (e.g. `type X = \"a\" | \"b\"`). Enums are banned by `no-enum`; use a union.',\n comparisonCluster:\n '`{{key}}` is compared against a closed set of string literals — define a string-literal union type (e.g. `type X = \"a\" | \"b\"`).',\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n const sourceText = context.sourceCode.getText();\n if (isIgnoredFile(filename, sourceText)) {\n return {};\n }\n\n const scopeStack: Scope[] = [];\n const validClusters: TSESTree.Node[] = [];\n const bareChoiceProps: CollectedProperty[] = [];\n const containersWithUnion = new Set<TSESTree.Node>();\n\n function pushScope(fn: FunctionLike): void {\n scopeStack.push({\n clusters: new Map(),\n unionRefs: unionRefsFromParams(fn),\n });\n }\n\n function isUnionTypedRef(key: string, current: Set<string>): boolean {\n if (current.has(key)) {\n return true;\n }\n return scopeStack.some((s) => s.unionRefs.has(key));\n }\n\n function popScope(): void {\n const scope = scopeStack.pop();\n if (scope === undefined) {\n return;\n }\n for (const [key, entry] of scope.clusters) {\n if (\n entry.allTokens &&\n entry.literals.size >= MIN_CLUSTER_SIZE &&\n !isUnionTypedRef(key, scope.unionRefs)\n ) {\n validClusters.push(entry.node);\n }\n }\n }\n\n function accumulate(\n key: string,\n literals: string[],\n node: TSESTree.Node,\n ): void {\n const scope = scopeStack[scopeStack.length - 1];\n if (scope === undefined) {\n return;\n }\n const allTokens = literals.every((lit) => isEnumToken(lit));\n const existing = scope.clusters.get(key);\n if (existing === undefined) {\n scope.clusters.set(key, {\n node,\n literals: new Set(literals),\n allTokens,\n });\n return;\n }\n for (const lit of literals) {\n existing.literals.add(lit);\n }\n existing.allTokens = existing.allTokens && allTokens;\n }\n\n function collectProperty(\n key: TSESTree.PropertyDefinition[\"key\"] | TSESTree.PropertyName,\n typeNode: TSESTree.TypeNode | undefined,\n container: TSESTree.Node,\n node: TSESTree.Node,\n ): void {\n if (isStringLiteralUnion(typeNode)) {\n containersWithUnion.add(container);\n return;\n }\n if (typeNode?.type !== AST_NODE_TYPES.TSStringKeyword) {\n return;\n }\n const name = keyName(key);\n if (name === null || !isChoiceLikeName(name)) {\n return;\n }\n bareChoiceProps.push({ name, container, node });\n }\n\n return {\n FunctionDeclaration: pushScope,\n \"FunctionDeclaration:exit\": popScope,\n FunctionExpression: pushScope,\n \"FunctionExpression:exit\": popScope,\n ArrowFunctionExpression: pushScope,\n \"ArrowFunctionExpression:exit\": popScope,\n\n VariableDeclarator(node: TSESTree.VariableDeclarator): void {\n const scope = scopeStack[scopeStack.length - 1];\n if (\n scope === undefined ||\n node.id.type !== AST_NODE_TYPES.Identifier\n ) {\n return;\n }\n if (isLikelyClosedUnion(node.id.typeAnnotation?.typeAnnotation)) {\n scope.unionRefs.add(node.id.name);\n }\n },\n\n BinaryExpression(node: TSESTree.BinaryExpression): void {\n if (\n node.operator !== \"===\" &&\n node.operator !== \"!==\" &&\n node.operator !== \"==\" &&\n node.operator !== \"!=\"\n ) {\n return;\n }\n const leftKey = refKey(node.left);\n const rightLit = strLiteral(node.right);\n const rightKey = refKey(node.right);\n const leftLit = strLiteral(node.left);\n if (leftKey !== null && rightLit !== null) {\n accumulate(leftKey, [rightLit], node);\n } else if (rightKey !== null && leftLit !== null) {\n accumulate(rightKey, [leftLit], node);\n }\n },\n\n SwitchStatement(node: TSESTree.SwitchStatement): void {\n const key = refKey(node.discriminant);\n if (key === null) {\n return;\n }\n const literals: string[] = [];\n for (const c of node.cases) {\n if (c.test !== null) {\n const lit = strLiteral(c.test);\n if (lit !== null) {\n literals.push(lit);\n }\n }\n }\n if (literals.length > 0) {\n accumulate(key, literals, node);\n }\n },\n\n TSPropertySignature(node: TSESTree.TSPropertySignature): void {\n collectProperty(\n node.key,\n node.typeAnnotation?.typeAnnotation,\n node.parent,\n node,\n );\n },\n\n PropertyDefinition(node: TSESTree.PropertyDefinition): void {\n collectProperty(\n node.key,\n node.typeAnnotation?.typeAnnotation,\n node.parent,\n node,\n );\n },\n\n \"Program:exit\"(): void {\n for (const clusterNode of validClusters) {\n context.report({\n node: clusterNode,\n messageId: \"comparisonCluster\",\n data: { key: refKeyText(clusterNode) },\n });\n }\n for (const prop of bareChoiceProps) {\n if (containersWithUnion.has(prop.container)) {\n context.report({\n node: prop.node,\n messageId: \"bareChoiceField\",\n data: { name: prop.name },\n });\n }\n }\n },\n };\n\n function refKeyText(node: TSESTree.Node): string {\n if (node.type === AST_NODE_TYPES.BinaryExpression) {\n return refKey(node.left) ?? refKey(node.right) ?? \"value\";\n }\n if (node.type === AST_NODE_TYPES.SwitchStatement) {\n return refKey(node.discriminant) ?? \"value\";\n }\n return \"value\";\n }\n },\n});\n","/**\n * @fileoverview Flag a junk-drawer module stem that has a single public export.\n * TS port of Python SARJ022. Fires ONLY when BOTH hold:\n *\n * (a) the file's basename stem is a generic \"junk-drawer\" name that describes\n * no responsibility (`utils`, `helpers`, `types`, `models`, ...), AND\n * (b) the module has exactly one public export, and that export is a named\n * function / class / function-const, so the rename target is unambiguous.\n *\n * When both hold, the sole export's name is the information-rich replacement for\n * the meaningless stem (`utils.ts` exporting `snakeCaseText` -> `snake-case-text.ts`).\n *\n * A junk-drawer stem carries no domain to lose, so replacing it with the export\n * name is strictly an improvement; an informative stem (`pagination.ts`) names a\n * domain broader than its one current export and is deliberately never flagged.\n */\n\nimport { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"renameJunkDrawer\";\ntype Options = readonly [];\n\n// Generic module stems that describe no responsibility. `index` is deliberately\n// excluded: barrel files legitimately re-export many symbols under that name.\nconst JUNK_DRAWER_STEMS = new Set([\n \"util\",\n \"utils\",\n \"helper\",\n \"helpers\",\n \"common\",\n \"constant\",\n \"constants\",\n \"type\",\n \"types\",\n \"model\",\n \"models\",\n \"shared\",\n \"misc\",\n]);\n\n// Exports whose name is an idiomatic ecosystem convention that lives in a\n// junk-drawer bucket by design — flagging them fights the convention and the\n// bucket is expected to grow. `cn` is the shadcn/ui tailwind-merge className\n// helper that scaffolds into `lib/utils.ts`; renaming to `cn.ts` breaks every\n// `import { cn } from \"@/lib/utils\"`.\nconst CONVENTIONAL_BUCKET_EXPORTS = new Set([\"cn\"]);\n\n// Multi-word acronyms whose accepted kebab-case is a single token rather than a\n// letter-by-letter split (`OAuth` -> `oauth`, not `o-auth`).\nconst ACRONYM_OVERRIDES: ReadonlyArray<readonly [RegExp, string]> = [\n [/OAuth/g, \"Oauth\"],\n [/GraphQL/g, \"Graphql\"],\n [/gRPC/g, \"Grpc\"],\n];\n\n// Split on camelCase boundaries while keeping runs of capitals (acronyms)\n// together: `HTTPServer` -> `HTTP` + `Server`, `JWTHandler` -> `JWT` + `Handler`.\nconst CAMEL_BOUNDARY_RE = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;\n\nconst TEST_FILE_RE = /\\.(test|spec)\\.[cm]?[jt]sx?$/i;\nconst SCRIPT_EXT_RE = /\\.[cm]?[jt]sx?$/i;\n\ninterface ExportSummary {\n readonly names: number;\n readonly hasReExport: boolean;\n readonly candidate: { name: string; node: TSESTree.Node } | null;\n}\n\nconst basename = (filename: string): string =>\n filename.split(/[/\\\\]/).pop() ?? filename;\n\nconst stemOf = (base: string): string => base.replace(SCRIPT_EXT_RE, \"\");\n\nconst kebabCase = (name: string): string => {\n let normalized = name;\n for (const [pattern, replacement] of ACRONYM_OVERRIDES) {\n normalized = normalized.replace(pattern, replacement);\n }\n return normalized.replace(CAMEL_BOUNDARY_RE, \"-\").toLowerCase();\n};\n\nconst isFunctionExpression = (node: TSESTree.Expression | null): boolean =>\n node !== null &&\n (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.FunctionExpression);\n\n// A `const foo = () => {}` is a rename candidate; a value const (`const MAX = 5`)\n// is not — renaming a file after a bare constant loses more than it gains.\nconst functionConstName = (\n decl: TSESTree.VariableDeclaration,\n): string | null => {\n if (decl.declarations.length !== 1) return null;\n const [declarator] = decl.declarations;\n if (declarator === undefined) return null;\n if (declarator.id.type !== AST_NODE_TYPES.Identifier) return null;\n if (!isFunctionExpression(declarator.init)) return null;\n return declarator.id.name;\n};\n\nconst summarizeExports = (body: readonly TSESTree.ProgramStatement[]): ExportSummary => {\n let names = 0;\n let hasReExport = false;\n let candidate: { name: string; node: TSESTree.Node } | null = null;\n\n const addCandidate = (name: string, node: TSESTree.Node): void => {\n names += 1;\n candidate = { name, node };\n };\n\n for (const statement of body) {\n switch (statement.type) {\n case AST_NODE_TYPES.ExportAllDeclaration:\n hasReExport = true;\n break;\n case AST_NODE_TYPES.ExportDefaultDeclaration: {\n names += 1;\n const decl = statement.declaration;\n if (\n decl.type === AST_NODE_TYPES.FunctionDeclaration &&\n decl.id !== null\n ) {\n candidate = { name: decl.id.name, node: statement };\n } else if (\n decl.type === AST_NODE_TYPES.ClassDeclaration &&\n decl.id !== null\n ) {\n candidate = { name: decl.id.name, node: statement };\n }\n break;\n }\n case AST_NODE_TYPES.ExportNamedDeclaration: {\n if (statement.source !== null) {\n hasReExport = true;\n break;\n }\n const decl = statement.declaration;\n if (decl === null) {\n names += statement.specifiers.length;\n break;\n }\n switch (decl.type) {\n case AST_NODE_TYPES.FunctionDeclaration:\n if (decl.id !== null) addCandidate(decl.id.name, statement);\n else names += 1;\n break;\n case AST_NODE_TYPES.ClassDeclaration:\n if (decl.id !== null) addCandidate(decl.id.name, statement);\n else names += 1;\n break;\n case AST_NODE_TYPES.VariableDeclaration: {\n const fnName = functionConstName(decl);\n if (fnName !== null && decl.declarations.length === 1) {\n addCandidate(fnName, statement);\n } else {\n names += decl.declarations.length;\n }\n break;\n }\n default:\n names += 1;\n }\n break;\n }\n default:\n break;\n }\n }\n\n return { names, hasReExport, candidate };\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"single-public-export\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"A junk-drawer module stem (`utils`, `helpers`, `types`, ...) with a single public function/class/const export should be renamed after that export.\",\n },\n schema: [],\n messages: {\n renameJunkDrawer:\n \"Module stem `{{stem}}` is a generic junk-drawer name; its sole public export is `{{name}}` — rename the file to `{{expected}}.ts` to describe its responsibility.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const base = basename(context.filename);\n\n if (base.endsWith(\".d.ts\")) return {};\n if (TEST_FILE_RE.test(base)) return {};\n\n const stem = stemOf(base);\n if (!JUNK_DRAWER_STEMS.has(stem.toLowerCase())) return {};\n\n return {\n Program(node: TSESTree.Program): void {\n const { names, hasReExport, candidate } = summarizeExports(node.body);\n if (hasReExport) return;\n if (names !== 1 || candidate === null) return;\n if (CONVENTIONAL_BUCKET_EXPORTS.has(candidate.name)) return;\n\n const expected = kebabCase(candidate.name);\n if (stem === expected) return;\n\n context.report({\n node: candidate.node,\n messageId: \"renameJunkDrawer\",\n data: { stem, name: candidate.name, expected },\n });\n },\n };\n },\n});\n","import enforceFileStructure from \"./rules/enforce-file-structure.js\";\nimport noClientSideDataFetching from \"./rules/no-client-side-data-fetching.js\";\nimport noCommentCruft from \"./rules/no-comment-cruft.js\";\nimport noEnum from \"./rules/no-enum.js\";\nimport noInsecureRandomId from \"./rules/no-insecure-random-id.js\";\nimport noJsonStringifyError from \"./rules/no-json-stringify-error.js\";\nimport noLogOnlyCatch from \"./rules/no-log-only-catch.js\";\nimport noRawEnv from \"./rules/no-raw-env.js\";\nimport noSentinelReturnOnCatch from \"./rules/no-sentinel-return-on-catch.js\";\nimport noSequentialAwait from \"./rules/no-sequential-await.js\";\nimport noStringConcatInLoop from \"./rules/no-string-concat-in-loop.js\";\nimport noUnnecessaryUseClient from \"./rules/no-unnecessary-use-client.js\";\nimport preferDiscriminatedUnion from \"./rules/prefer-discriminated-union.js\";\nimport preferSchemaForApiPayload from \"./rules/prefer-schema-for-api-payload.js\";\nimport preferSemanticColors from \"./rules/prefer-semantic-colors.js\";\nimport preferServerActions from \"./rules/prefer-server-actions.js\";\nimport preferShadcn from \"./rules/prefer-shadcn.js\";\nimport requireAssertNever from \"./rules/require-assert-never.js\";\nimport requireZodFormValidation from \"./rules/require-zod-form-validation.js\";\nimport zodNamingConvention from \"./rules/zod-naming-convention.js\";\nimport noCorsWildcardWithCredentials from \"./rules/no-cors-wildcard-with-credentials.js\";\nimport noFatTryBlocks from \"./rules/no-fat-try-blocks.js\";\nimport noSecretInLog from \"./rules/no-secret-in-log.js\";\nimport preferStringLiteralUnion from \"./rules/prefer-string-literal-union.js\";\nimport singlePublicExport from \"./rules/single-public-export.js\";\n\nconst rules = {\n \"enforce-file-structure\": enforceFileStructure,\n \"no-client-side-data-fetching\": noClientSideDataFetching,\n \"no-comment-cruft\": noCommentCruft,\n \"no-enum\": noEnum,\n \"no-insecure-random-id\": noInsecureRandomId,\n \"no-json-stringify-error\": noJsonStringifyError,\n \"no-log-only-catch\": noLogOnlyCatch,\n \"no-raw-env\": noRawEnv,\n \"no-sentinel-return-on-catch\": noSentinelReturnOnCatch,\n \"no-sequential-await\": noSequentialAwait,\n \"no-string-concat-in-loop\": noStringConcatInLoop,\n \"no-unnecessary-use-client\": noUnnecessaryUseClient,\n \"prefer-discriminated-union\": preferDiscriminatedUnion,\n \"prefer-schema-for-api-payload\": preferSchemaForApiPayload,\n \"prefer-semantic-colors\": preferSemanticColors,\n \"prefer-server-actions\": preferServerActions,\n \"prefer-shadcn\": preferShadcn,\n \"require-assert-never\": requireAssertNever,\n \"require-zod-form-validation\": requireZodFormValidation,\n \"zod-naming-convention\": zodNamingConvention,\n \"no-cors-wildcard-with-credentials\": noCorsWildcardWithCredentials,\n \"no-fat-try-blocks\": noFatTryBlocks,\n \"no-secret-in-log\": noSecretInLog,\n \"prefer-string-literal-union\": preferStringLiteralUnion,\n \"single-public-export\": singlePublicExport,\n};\n\nconst plugin = {\n meta: {\n name: \"@sarj/eslint-plugin\",\n version: \"2.3.2\",\n },\n rules,\n configs: {\n recommended: {\n plugins: [\"@sarj\"],\n rules: {\n \"@sarj/zod-naming-convention\": \"warn\",\n \"@sarj/require-assert-never\": \"error\",\n \"@sarj/require-zod-form-validation\": \"error\",\n \"@sarj/enforce-file-structure\": \"warn\",\n \"@sarj/no-client-side-data-fetching\": \"warn\",\n \"@sarj/prefer-server-actions\": \"warn\",\n \"@sarj/no-unnecessary-use-client\": \"warn\",\n \"@sarj/prefer-schema-for-api-payload\": \"warn\",\n // Distilled from sarj-audit skills — warn in recommended, error in strict.\n \"@sarj/no-sequential-await\": \"warn\",\n \"@sarj/no-sentinel-return-on-catch\": \"warn\",\n \"@sarj/no-log-only-catch\": \"warn\",\n \"@sarj/no-insecure-random-id\": \"warn\",\n \"@sarj/no-json-stringify-error\": \"warn\",\n \"@sarj/no-string-concat-in-loop\": \"warn\",\n \"@sarj/prefer-discriminated-union\": \"warn\",\n \"@sarj/no-comment-cruft\": \"warn\",\n // Frontend / styling — distilled from frontend PR-review mining.\n \"@sarj/prefer-semantic-colors\": \"warn\",\n // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.\n \"@sarj/no-fat-try-blocks\": \"warn\",\n \"@sarj/no-cors-wildcard-with-credentials\": \"warn\",\n \"@sarj/no-secret-in-log\": \"warn\",\n \"@sarj/single-public-export\": \"warn\",\n \"@sarj/prefer-string-literal-union\": \"warn\",\n },\n },\n strict: {\n plugins: [\"@sarj\"],\n rules: {\n \"@sarj/zod-naming-convention\": \"error\",\n \"@sarj/require-assert-never\": \"error\",\n \"@sarj/require-zod-form-validation\": \"error\",\n \"@sarj/enforce-file-structure\": \"error\",\n \"@sarj/no-raw-env\": \"error\",\n \"@sarj/prefer-shadcn\": \"error\",\n \"@sarj/no-enum\": \"error\",\n \"@sarj/no-client-side-data-fetching\": \"error\",\n \"@sarj/prefer-server-actions\": \"error\",\n \"@sarj/no-unnecessary-use-client\": \"error\",\n \"@sarj/prefer-schema-for-api-payload\": \"error\",\n // Distilled from sarj-audit skills.\n \"@sarj/no-sequential-await\": \"error\",\n \"@sarj/no-sentinel-return-on-catch\": \"error\",\n \"@sarj/no-log-only-catch\": \"error\",\n \"@sarj/no-insecure-random-id\": \"error\",\n \"@sarj/no-json-stringify-error\": \"error\",\n \"@sarj/no-string-concat-in-loop\": \"error\",\n \"@sarj/prefer-discriminated-union\": \"error\",\n \"@sarj/no-comment-cruft\": \"error\",\n // Frontend / styling — distilled from frontend PR-review mining. Stylistic,\n // no autofix → warn (rollout should prove the FP rate before raising it).\n \"@sarj/prefer-semantic-colors\": \"warn\",\n // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.\n \"@sarj/no-fat-try-blocks\": \"error\",\n \"@sarj/no-cors-wildcard-with-credentials\": \"error\",\n \"@sarj/no-secret-in-log\": \"error\",\n \"@sarj/single-public-export\": \"error\",\n // High-volume/stylistic — warn until rollout proves FP rate.\n \"@sarj/prefer-string-literal-union\": \"warn\",\n },\n },\n },\n};\n\nexport default plugin;\nexport { rules };\n"],"mappings":"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","names":["AST_NODE_TYPES","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","DEFAULT_IGNORE_PATTERNS","ESLintUtils","ESLintUtils","AST_NODE_TYPES","ESLintUtils","isNode","ESLintUtils","AST_NODE_TYPES","ESLintUtils","ESLintUtils","AST_NODE_TYPES","AST_NODE_TYPES","ESLintUtils","findVariable","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","ESLintUtils","propName","keyName","ESLintUtils","ESLintUtils","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","isNode","ESLintUtils","AST_NODE_TYPES","isNode","unwrap","ESLintUtils","propertyKeyName","keyName","ESLintUtils","AST_NODE_TYPES","propName","ESLintUtils","AST_NODE_TYPES","isFunctionExpression"]}
1
+ {"version":3,"sources":["../src/rules/enforce-file-structure.ts","../src/rules/no-client-side-data-fetching.ts","../src/rules/no-comment-cruft.ts","../src/rules/no-enum.ts","../src/rules/no-insecure-random-id.ts","../src/rules/no-json-stringify-error.ts","../src/rules/no-log-only-catch.ts","../src/rules/no-raw-env.ts","../src/rules/no-sentinel-return-on-catch.ts","../src/rules/no-sequential-await.ts","../src/rules/no-string-concat-in-loop.ts","../src/rules/no-unnecessary-use-client.ts","../src/rules/prefer-discriminated-union.ts","../src/rules/prefer-schema-for-api-payload.ts","../src/rules/prefer-semantic-colors.ts","../src/rules/_tailwind.ts","../src/rules/prefer-server-actions.ts","../src/rules/prefer-shadcn.ts","../src/rules/require-assert-never.ts","../src/rules/require-zod-form-validation.ts","../src/rules/zod-naming-convention.ts","../src/rules/no-cors-wildcard-with-credentials.ts","../src/rules/no-fat-try-blocks.ts","../src/rules/no-secret-in-log.ts","../src/rules/prefer-string-literal-union.ts","../src/rules/single-public-export.ts","../src/index.ts"],"sourcesContent":["import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"incorrectOrder\" | \"useServerDirective\";\ntype Options = readonly [];\n\n/**\n * Section ordinals — lower numbers must appear before higher numbers.\n *\n * Per the stepdown rule (see `plugins/sarj-audit/commands/stepdown.md`), only\n * *function* ordering is a violation. Top-level imports, type aliases,\n * interfaces, enums, classes, and value constants are all \"declarations\" and\n * belong together at the top in any order — so they share a single ordinal and\n * are never flagged relative to one another.\n */\nconst SECTION = {\n declarations: 0,\n functions: 1,\n exports: 2,\n} as const;\n\nconst SECTION_NAMES = [\"declarations\", \"functions\", \"exports\"] as const;\n\ntype SectionOrdinal = (typeof SECTION)[keyof typeof SECTION];\n\nconst sectionName = (ordinal: SectionOrdinal): string => {\n const name = SECTION_NAMES[ordinal];\n // SECTION_NAMES is indexed by SectionOrdinal (0..2) — always defined, but\n // noUncheckedIndexedAccess widens to `string | undefined`, so fall back.\n return name ?? \"unknown\";\n};\n\n// Server-action files: anchored to an `/actions/` path segment, a `*.action.ts`\n// filename, or a bare `actions.ts` file. Substrings like `transaction-service`\n// or `redaction.ts` deliberately do NOT match.\nconst SERVER_ACTION_FILE_RE =\n /(?:^|\\/)actions\\/|\\.action\\.[jt]sx?$|(?:^|\\/)actions\\.[jt]sx?$/;\n\nconst isFunctionExpression = (node: TSESTree.Expression): boolean =>\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.FunctionExpression;\n\n/**\n * A `const/let/var` declaration counts as a *function* when every declarator is\n * initialized with a function/arrow expression (`const helper = () => {}`).\n * A value const (`const x = 1`, `const MAX = 5`) is a declaration, not a\n * function — it must not be mis-bucketed.\n */\nconst isFunctionLikeVariable = (\n statement: TSESTree.VariableDeclaration,\n): boolean =>\n statement.declarations.length > 0 &&\n statement.declarations.every(\n (decl) => decl.init !== null && isFunctionExpression(decl.init),\n );\n\nconst getStatementSection = (\n statement: TSESTree.ProgramStatement,\n): SectionOrdinal => {\n switch (statement.type) {\n case AST_NODE_TYPES.ImportDeclaration:\n case AST_NODE_TYPES.TSTypeAliasDeclaration:\n case AST_NODE_TYPES.TSInterfaceDeclaration:\n case AST_NODE_TYPES.TSEnumDeclaration:\n case AST_NODE_TYPES.ClassDeclaration:\n return SECTION.declarations;\n case AST_NODE_TYPES.VariableDeclaration:\n return isFunctionLikeVariable(statement)\n ? SECTION.functions\n : SECTION.declarations;\n case AST_NODE_TYPES.FunctionDeclaration:\n return SECTION.functions;\n case AST_NODE_TYPES.ExportNamedDeclaration:\n case AST_NODE_TYPES.ExportDefaultDeclaration:\n case AST_NODE_TYPES.ExportAllDeclaration:\n return SECTION.exports;\n default:\n // Executable top-level statements group with functions.\n return SECTION.functions;\n }\n};\n\nconst isUseServerDirective = (\n statement: TSESTree.ProgramStatement | undefined,\n): boolean => {\n if (statement === undefined) return false;\n if (statement.type !== AST_NODE_TYPES.ExpressionStatement) return false;\n const expr = statement.expression;\n if (expr.type !== AST_NODE_TYPES.Literal) return false;\n return expr.value === \"use server\";\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"enforce-file-structure\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce that function definitions follow the file's top-of-file declarations (imports, types, constants, classes) — the stepdown rule. Ordering among non-function declarations is not enforced. Server-action files (under `/actions/`, named `*.action.ts`, or `actions.ts`) must also begin with a `use server` directive.\",\n },\n schema: [],\n messages: {\n incorrectOrder:\n \"File structure violation: {{current}} should come before {{expected}}\",\n useServerDirective:\n \"Server action files must start with 'use server' directive\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n const isServerAction = SERVER_ACTION_FILE_RE.test(filename);\n\n return {\n Program(node: TSESTree.Program): void {\n const body = node.body;\n\n if (isServerAction) {\n const firstNode = body[0];\n if (!isUseServerDirective(firstNode)) {\n context.report({\n node,\n messageId: \"useServerDirective\",\n });\n }\n }\n\n let currentSection: SectionOrdinal = SECTION.declarations;\n\n for (const statement of body) {\n // Skip top-of-file string directives ('use server', 'use client',\n // 'use strict', ...) so they don't get classified as a section.\n if (\n statement.type === AST_NODE_TYPES.ExpressionStatement &&\n statement.expression.type === AST_NODE_TYPES.Literal &&\n typeof statement.expression.value === \"string\" &&\n statement.expression.value.startsWith(\"use \")\n ) {\n continue;\n }\n\n const statementSection = getStatementSection(statement);\n\n if (statementSection < currentSection) {\n context.report({\n node: statement,\n messageId: \"incorrectOrder\",\n data: {\n current: sectionName(statementSection),\n expected: sectionName(currentSection),\n },\n });\n } else if (statementSection > currentSection) {\n currentSection = statementSection;\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow data fetching inside `useEffect` / `useLayoutEffect`.\n *\n * Anti-pattern:\n *\n * useEffect(() => { fetch('/data').then(setData); }, []);\n *\n * Causes a client-side waterfall (render → effect → fetch → re-render),\n * forfeits server-side caching, and produces layout shift. In Next.js App\n * Router, prefer:\n * - a React Server Component that fetches at render time, or\n * - a Server Action invoked from a form / onClick handler, or\n * - client-side caching libraries like SWR or React Query.\n *\n * Detection covers:\n * - `fetch(...)` (default + when explicit `method: \"GET\"`)\n * - `axios.<method>(...)` for actual HTTP verbs only:\n * get / post / put / delete / patch / request / head / options\n * (i.e. NOT `axios.create` / `axios.defaults`)\n * - `ky.<method>(...)` / `superagent.<method>(...)` (same verbs)\n * - bare `axios(...)` / `ky(...)` calls (when treated as a GET)\n *\n * Analytics / telemetry endpoints whose URL has a whole path segment of\n * `track` / `log` / `ping` / `event` / ... are intentionally exempt because\n * they aren't render-blocking data fetches. (Matched per-segment, so\n * `/api/login`, `/blog`, `/api/events`, `/catalog`, `/api/shipping` are NOT\n * exempt.)\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/data-fetching\n * - https://react.dev/reference/react/useEffect#fetching-data-with-effects\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noClientFetch\";\ntype Options = readonly [];\n\nconst FETCH_LIBS: ReadonlySet<string> = new Set([\"axios\", \"ky\", \"superagent\"]);\n\n// Real HTTP verbs only. Explicitly excludes `create`, `defaults`,\n// `interceptors`, `isAxiosError`, etc.\nconst HTTP_METHOD_NAMES: ReadonlySet<string> = new Set([\n \"get\",\n \"post\",\n \"put\",\n \"delete\",\n \"patch\",\n \"request\",\n \"head\",\n \"options\",\n]);\n\n// Matched against whole path SEGMENTS (split on `/` and `.`), never as raw\n// substrings — otherwise `/api/login` (\"log\"), `/blog` (\"log\"), `/api/events`\n// (\"event\"), `/catalog` (\"log\"), and `/api/shipping` (\"ping\") would be wrongly\n// exempted.\nconst ANALYTICS_SEGMENTS: ReadonlySet<string> = new Set([\n \"analytics\",\n \"telemetry\",\n \"track\",\n \"log\",\n \"ping\",\n \"beacon\",\n \"metrics\",\n \"event\",\n]);\n\nfunction isEffectHookCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n\n // useEffect(...) / useLayoutEffect(...)\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name === \"useEffect\" || callee.name === \"useLayoutEffect\";\n }\n\n // React.useEffect(...) / React.useLayoutEffect(...)\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.object.type === AST_NODE_TYPES.Identifier &&\n callee.object.name === \"React\" &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return (\n callee.property.name === \"useEffect\" ||\n callee.property.name === \"useLayoutEffect\"\n );\n }\n\n return false;\n}\n\n/**\n * Reads the `method` property of an options object passed to `fetch` / `axios`.\n * Returns the uppercased method name, or `null` if not statically determinable.\n */\nfunction readMethodProperty(\n optionsArg: TSESTree.Node | undefined,\n): string | null {\n if (!optionsArg || optionsArg.type !== AST_NODE_TYPES.ObjectExpression) {\n return null;\n }\n for (const prop of optionsArg.properties) {\n if (prop.type !== AST_NODE_TYPES.Property) continue;\n if (prop.computed) continue;\n const key = prop.key;\n const matchesMethodKey =\n (key.type === AST_NODE_TYPES.Identifier && key.name === \"method\") ||\n (key.type === AST_NODE_TYPES.Literal && key.value === \"method\");\n if (!matchesMethodKey) continue;\n if (\n prop.value.type === AST_NODE_TYPES.Literal &&\n typeof prop.value.value === \"string\"\n ) {\n return prop.value.value.toUpperCase();\n }\n return null;\n }\n return null;\n}\n\nfunction isFetchCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n\n // fetch(url, options?)\n if (\n callee.type === AST_NODE_TYPES.Identifier &&\n callee.name === \"fetch\"\n ) {\n const method = readMethodProperty(node.arguments[1]);\n if (method !== null && method !== \"GET\") {\n return false;\n }\n return true;\n }\n\n // axios.get(...), ky.post(...), superagent.delete(...), ...\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.object.type === AST_NODE_TYPES.Identifier &&\n FETCH_LIBS.has(callee.object.name) &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n // Only flag actual HTTP method calls — NOT `axios.create`, `axios.defaults`,\n // `axios.interceptors`, `axios.isAxiosError`, etc.\n return HTTP_METHOD_NAMES.has(callee.property.name);\n }\n\n // axios(config) / ky(config) — treat as request unless method is explicitly non-GET.\n if (\n callee.type === AST_NODE_TYPES.Identifier &&\n (callee.name === \"axios\" || callee.name === \"ky\")\n ) {\n const firstArg = node.arguments[0];\n const secondArg = node.arguments[1];\n let configArg: TSESTree.Node | undefined;\n if (firstArg?.type === AST_NODE_TYPES.ObjectExpression) {\n configArg = firstArg;\n } else if (secondArg?.type === AST_NODE_TYPES.ObjectExpression) {\n configArg = secondArg;\n }\n const method = readMethodProperty(configArg);\n if (method !== null && method !== \"GET\") {\n return false;\n }\n return true;\n }\n\n return false;\n}\n\nfunction extractUrlString(node: TSESTree.CallExpression): string {\n const firstArg = node.arguments[0];\n if (!firstArg) return \"\";\n\n if (\n firstArg.type === AST_NODE_TYPES.Literal &&\n typeof firstArg.value === \"string\"\n ) {\n return firstArg.value;\n }\n if (firstArg.type === AST_NODE_TYPES.TemplateLiteral) {\n return firstArg.quasis.map((q) => q.value.cooked).join(\"\");\n }\n if (firstArg.type === AST_NODE_TYPES.Identifier) {\n return firstArg.name;\n }\n return \"\";\n}\n\nfunction isAnalyticsCall(node: TSESTree.CallExpression): boolean {\n const url = extractUrlString(node).toLowerCase();\n if (url === \"\") return false;\n // Split into path segments and file-extension parts; exempt only when a\n // WHOLE segment is a known analytics keyword.\n return url\n .split(/[/.]/)\n .some((segment) => ANALYTICS_SEGMENTS.has(segment));\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-client-side-data-fetching\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow data fetching inside `useEffect` / `useLayoutEffect`; prefer React Server Components, Server Actions, or a client-side cache (SWR / React Query).\",\n },\n schema: [],\n messages: {\n noClientFetch:\n \"Avoid direct data fetching inside useEffect / useLayoutEffect. This causes waterfalls and layout shifts. Prefer React Server Components, Server Actions, or client-side caching libraries like SWR or React Query.\",\n },\n },\n defaultOptions: [],\n create(context) {\n let effectDepth = 0;\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (isEffectHookCall(node)) {\n effectDepth += 1;\n return;\n }\n if (effectDepth === 0) return;\n if (!isFetchCall(node)) return;\n if (isAnalyticsCall(node)) return;\n context.report({ node, messageId: \"noClientFetch\" });\n },\n \"CallExpression:exit\"(node: TSESTree.CallExpression): void {\n if (isEffectHookCall(node)) {\n effectDepth -= 1;\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag comment cruft — commented-out code, section banners, and\n * leading file-header comment preambles. Code carries the *what*; comments are\n * reserved for the *why*. The fuzzier \"this comment merely restates the code\"\n * judgment stays in review, not this rule — only these deterministic shapes are\n * flagged. JSDoc (`/** ... *\\/`) is never flagged, and directive comments\n * (`eslint-`, `@ts-`, `prettier-`, `biome-`, `c8`, `<reference`, `TODO`,\n * `FIXME`) are ignored.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"commentedOutCode\" | \"sectionBanner\" | \"fileHeaderPreamble\";\ntype Options = readonly [];\n\nconst LEADING_PREAMBLE_MIN = 4;\n\nconst DIRECTIVE_RE =\n /^(eslint\\b|eslint-|@ts-|prettier-ignore|prettier\\b|biome-|c8\\b|v8\\b|istanbul\\b|@type\\b|@vite|webpack|<reference|global\\b|noinspection|todo\\b|fixme\\b|hack\\b|xxx\\b)/i;\n\nconst LICENSE_RE =\n /copyright|licen[cs]ed?|spdx|permission is hereby granted|all rights reserved/i;\n\nconst BANNER_FULL_RE = /^[\\s\\-=*#~_+.]{4,}$/;\n// `={4,}` not `={3,}`: `===` is TS strict-equality and appears in prose comments.\nconst BANNER_RUN_RE = /={4,}|-{4,}|#{4,}|\\*{4,}|~{4,}/;\nconst REGION_RE = /^#?(?:end)?region\\b/i;\n\nconst CODE_KEYWORD_RE =\n /^(import |export |const |let |var |function\\b|class |interface |type \\w|enum |return\\b|throw |await |async |if\\s*\\(|for\\s*\\(|while\\s*\\(|switch\\s*\\(|new |console\\.)/;\nconst CODE_TAIL_RE = /[;{}()]\\s*$|=>\\s*$|,\\s*$/;\n// LHS must be a real identifier (not a number literal — `0=Monday` in prose is\n// not an assignment) and `=` must not be `==`/`===`/`=>` (comparison/arrow).\n// The assignment branch additionally requires a code-tail — the line must end\n// with `;`, `)`, `}` or `]` — so plain prose like `count = number of items`\n// (which has no code-tail) is not mistaken for commented-out code.\nconst CALL_OR_ASSIGN_RE =\n /^[A-Za-z_$][\\w.$[\\]]*\\s*(?:=(?![=>])|\\+=|-=|\\*=)\\s*\\S.*[;)}\\]]\\s*$|^[A-Za-z_$][\\w.$]*\\([^)]*\\)\\s*;?\\s*$/;\n\nfunction stripCommentMarker(line: string): string {\n return line.replace(/^\\s*\\/\\//, \"\").replace(/^\\s*\\*+/, \"\").trim();\n}\n\nfunction isDirective(text: string): boolean {\n return DIRECTIVE_RE.test(text.trim());\n}\n\nfunction isBanner(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return BANNER_FULL_RE.test(t) || BANNER_RUN_RE.test(t) || REGION_RE.test(t);\n}\n\nfunction looksLikeCode(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n if (CODE_KEYWORD_RE.test(t) && CODE_TAIL_RE.test(t)) return true;\n return CALL_OR_ASSIGN_RE.test(t);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-comment-cruft\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag commented-out code, section-banner comments, and leading file-header comment preambles.\",\n },\n schema: [],\n messages: {\n commentedOutCode:\n \"Commented-out code — delete it; git history remembers.\",\n sectionBanner:\n \"Section-banner / region comment — structure code with functions, not ASCII rules.\",\n fileHeaderPreamble:\n \"File-header comment preamble — use a brief doc comment for the why, not a block of `//` lines.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const sourceCode = context.sourceCode;\n\n function isStandalone(comment: TSESTree.Comment): boolean {\n const before = sourceCode.getTokenBefore(comment, {\n includeComments: false,\n });\n return !before || before.loc.end.line < comment.loc.start.line;\n }\n\n function isJsDoc(comment: TSESTree.Comment): boolean {\n return comment.type === \"Block\" && /^\\*/.test(comment.value);\n }\n\n function reportLeadingPreamble(\n comments: readonly TSESTree.Comment[],\n firstCodeLine: number,\n ): void {\n const leading: TSESTree.Comment[] = [];\n let prevLine: number | null = null;\n for (const comment of comments) {\n if (comment.type !== \"Line\") break;\n if (comment.loc.start.line >= firstCodeLine) break;\n if (!isStandalone(comment)) break;\n const body = stripCommentMarker(comment.value);\n if (isDirective(body) || body.startsWith(\"!\")) continue;\n if (prevLine !== null && comment.loc.start.line !== prevLine + 1) break;\n leading.push(comment);\n prevLine = comment.loc.start.line;\n }\n const first = leading[0];\n if (first === undefined || leading.length < LEADING_PREAMBLE_MIN) return;\n const isLicense = leading.some((c) =>\n LICENSE_RE.test(stripCommentMarker(c.value)),\n );\n if (!isLicense) {\n context.report({ node: first, messageId: \"fileHeaderPreamble\" });\n }\n }\n\n return {\n Program(): void {\n const comments = sourceCode.getAllComments();\n const firstCodeLine =\n sourceCode.ast.tokens[0]?.loc.start.line ?? Number.MAX_SAFE_INTEGER;\n\n for (const comment of comments) {\n if (isJsDoc(comment) || !isStandalone(comment)) continue;\n const texts = comment.value\n .split(\"\\n\")\n .map(stripCommentMarker)\n .filter((l) => l.length > 0 && !isDirective(l));\n if (texts.some(isBanner)) {\n context.report({ node: comment, messageId: \"sectionBanner\" });\n } else if (texts.some(looksLikeCode)) {\n context.report({ node: comment, messageId: \"commentedOutCode\" });\n }\n }\n\n reportLeadingPreamble(comments, firstCodeLine);\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow TypeScript `enum` declarations. Use string-literal\n * union types (e.g. `type Status = \"active\" | \"inactive\"`) or `as const`\n * objects instead — enums generate runtime code, have unintuitive numeric\n * defaults, and don't tree-shake cleanly.\n *\n * Generated files can opt out either by living under a path matched by\n * `ignoreFiles` (default: `**\\/generated/**`, `**\\/*.gen.ts`, `**\\/*.generated.ts`)\n * or by including a `@generated` marker comment near the top of the file.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noEnum\";\ntype Options = readonly [\n {\n ignoreFiles?: readonly string[];\n }?,\n];\n\nconst DEFAULT_IGNORE_PATTERNS: readonly RegExp[] = [\n /[\\\\/]generated[\\\\/]/,\n /\\.gen\\.tsx?$/,\n /\\.generated\\.tsx?$/,\n];\n\nfunction matchesAnyPattern(\n filename: string,\n patterns: readonly string[],\n): boolean {\n for (const pattern of patterns) {\n // Convert minimatch-ish globs to regex: ** -> .*, * -> [^/\\\\]*\n const regexSource = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"::DOUBLESTAR::\")\n .replace(/\\*/g, \"[^/\\\\\\\\]*\")\n .replace(/::DOUBLESTAR::/g, \".*\");\n if (new RegExp(`^${regexSource}$`).test(filename)) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasGeneratedMarker(sourceText: string): boolean {\n // Look only in the first 1KB to keep this cheap.\n const head = sourceText.slice(0, 1024);\n return /@generated\\b/.test(head);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-enum\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow TypeScript `enum`; use string-literal unions or `as const` objects instead.\",\n },\n schema: [\n {\n type: \"object\",\n additionalProperties: false,\n properties: {\n ignoreFiles: {\n type: \"array\",\n items: { type: \"string\" },\n },\n },\n },\n ],\n messages: {\n noEnum:\n 'Enums are discouraged. Use a string-literal union (e.g. `type Status = \"active\" | \"inactive\"`) or an `as const` object instead.',\n },\n },\n defaultOptions: [{}],\n create(context, [optionsArg]) {\n const options = optionsArg ?? {};\n const ignoreFiles = options.ignoreFiles ?? [];\n const filename = context.filename;\n const sourceText = context.sourceCode.getText();\n\n const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS.some((re) =>\n re.test(filename),\n );\n const isIgnoredByOption =\n ignoreFiles.length > 0 && matchesAnyPattern(filename, ignoreFiles);\n const isGenerated = hasGeneratedMarker(sourceText);\n\n if (isIgnoredByDefault || isIgnoredByOption || isGenerated) {\n return {};\n }\n\n return {\n TSEnumDeclaration(node: TSESTree.TSEnumDeclaration): void {\n context.report({\n node,\n messageId: \"noEnum\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow using `Math.random()` to generate identifiers,\n * tokens, keys, or other security-sensitive values. `Math.random()` is not\n * cryptographically secure and is predictable — using it for IDs/tokens/secrets\n * can lead to collisions and trivially guessable values. Prefer\n * `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\n *\n * The rule is intentionally conservative and only flags two precise patterns:\n * 1. A `Math.random()` result fed into a `.toString(36)` chain — the classic\n * insecure random-id idiom (e.g. `Math.random().toString(36).slice(2)`).\n * 2. A `Math.random()` call whose nearest enclosing binding or property NAME\n * looks identifier/secret-like (matches `/id|token|key|secret|uuid|nonce|\n * session|password|salt/i`).\n *\n * Bare `Math.random()` used for non-identifier purposes (jitter, sampling,\n * rolls, etc.) is NOT flagged.\n *\n * KNOWN GAP (false-negative): an arithmetic expression between `Math.random()`\n * and `.toString(36)` breaks the member-chain walk, e.g.\n * `(Math.random() * 1e9).toString(36)`. The intervening `BinaryExpression`\n * means `Math.random()` is no longer the object end of the `.toString` chain,\n * so trigger 1 does not fire. Such code is only caught if its binding/property\n * name looks identifier/secret-like (trigger 2). See the documented test case.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"insecureRandomId\";\ntype Options = readonly [];\n\nconst NAME_PATTERN = /id|token|key|secret|uuid|nonce|session|password|salt/i;\n\n/**\n * Returns true if `node` is a `Math.random()` CallExpression.\n */\nfunction isMathRandomCall(node: TSESTree.Node): node is TSESTree.CallExpression {\n if (node.type !== \"CallExpression\") {\n return false;\n }\n const callee = node.callee;\n if (callee.type !== \"MemberExpression\" || callee.computed) {\n return false;\n }\n const { object, property } = callee;\n return (\n object.type === \"Identifier\" &&\n object.name === \"Math\" &&\n property.type === \"Identifier\" &&\n property.name === \"random\"\n );\n}\n\n/**\n * Returns true if `node` (a `Math.random()` call) is the base of a member\n * chain that calls `.toString(36)` somewhere above it, e.g.\n * `Math.random().toString(36)` or `Math.random().toString(36).slice(2)`.\n */\nfunction isPartOfToString36Chain(node: TSESTree.Node): boolean {\n let current: TSESTree.Node = node;\n let parent = current.parent;\n\n while (parent) {\n if (\n parent.type === \"MemberExpression\" &&\n parent.object === current &&\n !parent.computed &&\n parent.property.type === \"Identifier\" &&\n parent.property.name === \"toString\"\n ) {\n // The MemberExpression `<current>.toString` should be called with a\n // radix argument of `36`.\n const grandparent = parent.parent;\n if (\n grandparent &&\n grandparent.type === \"CallExpression\" &&\n grandparent.callee === parent\n ) {\n const firstArg = grandparent.arguments[0];\n if (\n firstArg &&\n firstArg.type === \"Literal\" &&\n firstArg.value === 36\n ) {\n return true;\n }\n }\n }\n\n // Keep walking up only while we remain the \"object\" of a member/call\n // chain. If we are anything other than the object end of the chain, the\n // `.toString(36)` (if any) does not apply to this `Math.random()`.\n if (\n parent.type === \"MemberExpression\" &&\n parent.object === current\n ) {\n current = parent;\n parent = current.parent;\n continue;\n }\n if (parent.type === \"CallExpression\" && parent.callee === current) {\n current = parent;\n parent = current.parent;\n continue;\n }\n break;\n }\n\n return false;\n}\n\n/**\n * Walks up from `node` to find the name of the nearest enclosing binding\n * (VariableDeclarator id) or property (Property / PropertyDefinition key),\n * and returns it. Returns `undefined` if no such name is found before leaving\n * the enclosing initializer/value context.\n */\nfunction findEnclosingName(node: TSESTree.Node): string | undefined {\n let current: TSESTree.Node = node;\n let parent = current.parent;\n\n while (parent) {\n // const sessionToken = Math.random()...\n if (parent.type === \"VariableDeclarator\" && parent.init === current) {\n if (parent.id.type === \"Identifier\") {\n return parent.id.name;\n }\n return undefined;\n }\n\n // { sessionToken: Math.random()... }\n if (parent.type === \"Property\" && parent.value === current) {\n const key = parent.key;\n if (!parent.computed && key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n }\n\n // class { sessionToken = Math.random()...; }\n if (parent.type === \"PropertyDefinition\" && parent.value === current) {\n const key = parent.key;\n if (!parent.computed && key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n }\n\n // Stop walking once we cross a boundary where the name no longer reflects\n // a binding/property whose value is being initialized.\n if (\n parent.type === \"FunctionDeclaration\" ||\n parent.type === \"FunctionExpression\" ||\n parent.type === \"ArrowFunctionExpression\" ||\n parent.type === \"BlockStatement\" ||\n parent.type === \"ReturnStatement\" ||\n parent.type === \"ExpressionStatement\"\n ) {\n return undefined;\n }\n\n current = parent;\n parent = current.parent;\n }\n\n return undefined;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-insecure-random-id\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow using `Math.random()` to generate identifiers, tokens, or secrets; use `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\",\n },\n schema: [],\n messages: {\n insecureRandomId:\n \"`Math.random()` is not cryptographically secure and is predictable; do not use it to generate IDs, tokens, or secrets. Use `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isMathRandomCall(node)) {\n return;\n }\n\n // Trigger 1: classic `.toString(36)` insecure id idiom.\n if (isPartOfToString36Chain(node)) {\n context.report({ node, messageId: \"insecureRandomId\" });\n return;\n }\n\n // Trigger 2: enclosing binding/property name looks id/secret-like.\n const name = findEnclosingName(node);\n if (name !== undefined && NAME_PATTERN.test(name)) {\n context.report({ node, messageId: \"insecureRandomId\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `JSON.stringify(err)` on a (heuristically detected)\n * Error value. `JSON.stringify` on an Error produces `\"{}\"` because the\n * `message` and `stack` properties are non-enumerable, silently throwing away\n * the very information you were trying to log.\n *\n * This is a purely syntactic rule (no type information). It flags\n * `JSON.stringify(x)` only when the first argument is an Identifier whose name\n * either:\n * 1. is the binding of an enclosing `catch (x)` clause in scope, OR\n * 2. matches the conventional error-name pattern /^(e|err|error|ex|exc)$/i.\n *\n * It is deliberately conservative: member expressions (`JSON.stringify(err.message)`),\n * object literals, and arbitrary identifiers (`JSON.stringify(user)`) are not flagged.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"noJsonStringifyError\";\ntype Options = readonly [];\n\nconst ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;\n\n/**\n * Walk up the scope chain looking for a `catch` clause whose binding matches\n * `name`. We rely on the scope analysis provided by the parser rather than\n * type information, keeping the rule type-free.\n */\nfunction isCatchBinding(scope: Scope.Scope, name: string): boolean {\n let current: Scope.Scope | null = scope;\n while (current) {\n const variable = current.set.get(name);\n if (variable) {\n for (const def of variable.defs) {\n if (def.type === \"CatchClause\") {\n return true;\n }\n }\n }\n current = current.upper;\n }\n return false;\n}\n\nfunction isJsonStringify(callee: TSESTree.Expression): boolean {\n return (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.object.type === \"Identifier\" &&\n callee.object.name === \"JSON\" &&\n callee.property.type === \"Identifier\" &&\n callee.property.name === \"stringify\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-json-stringify-error\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `JSON.stringify` on an Error value; it yields `{}` because `message`/`stack` are non-enumerable.\",\n },\n schema: [],\n messages: {\n noJsonStringifyError:\n \"`JSON.stringify` on an Error yields `{}` because `message`/`stack` are non-enumerable. Log `err.message` / `err.stack`, or use a proper error serializer.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isJsonStringify(node.callee)) {\n return;\n }\n\n const firstArg = node.arguments[0];\n if (!firstArg || firstArg.type !== \"Identifier\") {\n return;\n }\n\n const name = firstArg.name;\n const scope = context.sourceCode.getScope(firstArg);\n\n if (ERROR_NAME_PATTERN.test(name) || isCatchBinding(scope, name)) {\n context.report({\n node,\n messageId: \"noJsonStringifyError\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `catch` clauses that only log (via `console.*`) or do\n * nothing and then swallow the error. A catch that logs and falls through —\n * with no `throw`, no `return`, and no real recovery — hides failures: the\n * program keeps running in a broken state while the only signal is a log line\n * that is easy to miss. Either rethrow the error or handle it for real.\n *\n * This rule is deliberately conservative: it flags ONLY catches whose body is\n * empty or consists exclusively of `console.log/error/warn/info/debug` call\n * statements. Any other statement (a `throw`, a `return`, a fallback\n * assignment, a non-console call, etc.) means the catch is doing something and\n * is left alone — we prefer a false negative over a false positive.\n *\n * Test files opt out by default (filenames containing `.test.`, `.spec.`, or a\n * `__tests__/` path segment) since swallow-and-log is common and acceptable in\n * test scaffolding.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noLogOnlyCatch\";\ntype Options = readonly [];\n\nconst DEFAULT_IGNORE_PATTERNS: readonly RegExp[] = [\n /\\.test\\./,\n /\\.spec\\./,\n /[\\\\/]__tests__[\\\\/]/,\n];\n\nconst CONSOLE_METHODS: ReadonlySet<string> = new Set([\n \"log\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n]);\n\n/**\n * True when a statement is exactly a bare `console.<method>(...)` call, e.g.\n * `console.error(err);`. Anything else (other objects, optional chaining on a\n * non-`console` base, awaited/returned calls, etc.) returns false so the catch\n * is treated as doing real work.\n */\nfunction isConsoleCallStatement(statement: TSESTree.Statement): boolean {\n if (statement.type !== \"ExpressionStatement\") {\n return false;\n }\n const expr = statement.expression;\n if (expr.type !== \"CallExpression\") {\n return false;\n }\n const callee = expr.callee;\n if (callee.type !== \"MemberExpression\") {\n return false;\n }\n const { object, property } = callee;\n if (object.type !== \"Identifier\" || object.name !== \"console\") {\n return false;\n }\n if (callee.computed) {\n // console[\"log\"](...) — not a plain identifier method; be conservative.\n return false;\n }\n if (property.type !== \"Identifier\") {\n return false;\n }\n return CONSOLE_METHODS.has(property.name);\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-log-only-catch\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `catch` clauses that only log (or do nothing) and then swallow the error; rethrow or handle it instead.\",\n },\n schema: [],\n messages: {\n noLogOnlyCatch:\n \"Logging then swallowing the error hides failures. Rethrow the error or handle it for real.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n\n const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS.some((re) =>\n re.test(filename),\n );\n\n if (isIgnoredByDefault) {\n return {};\n }\n\n return {\n CatchClause(node: TSESTree.CatchClause): void {\n const statements = node.body.body;\n\n // Empty catch: swallows the error silently.\n if (statements.length === 0) {\n context.report({ node, messageId: \"noLogOnlyCatch\" });\n return;\n }\n\n // Flag only if EVERY statement is a bare console.* call. Any other\n // statement (throw, return, fallback, real handler, etc.) means the\n // catch is doing something — leave it alone.\n const everyStatementIsConsoleLog = statements.every((statement) =>\n isConsoleCallStatement(statement),\n );\n\n if (everyStatementIsConsoleLog) {\n context.report({ node, messageId: \"noLogOnlyCatch\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow direct `process.env` access. Force all env reads\n * through a Zod-validated env module so configuration is typed and validated\n * at startup.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noRawEnv\";\ntype Options = readonly [];\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-raw-env\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow direct `process.env` access; use a Zod-validated env module instead.\",\n },\n schema: [],\n messages: {\n noRawEnv:\n \"Do not read from `process.env` directly. Import the Zod-validated env module instead so values are typed and validated at startup.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n MemberExpression(node: TSESTree.MemberExpression): void {\n if (node.computed) {\n // Skip dynamic accesses like process[\"env\"] — extremely rare and out of scope.\n return;\n }\n if (\n node.object.type === \"Identifier\" &&\n node.object.name === \"process\" &&\n node.property.type === \"Identifier\" &&\n node.property.name === \"env\"\n ) {\n context.report({\n node,\n messageId: \"noRawEnv\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow silently swallowing an error in a `catch` clause by\n * returning a \"sentinel\" empty value as the final/only statement.\n *\n * A `catch` block whose last statement is `return null` / `return undefined` /\n * `return false` / `return []` / `return {}` (and which never `throw`s) discards\n * the caught error entirely. Downstream callers can't distinguish a genuine\n * empty result from a failure, which is a frequent source of silent data loss\n * and broken idempotency decisions.\n *\n * This rule is deliberately conservative — it prefers false negatives over\n * false positives. It does NOT flag:\n * - catch blocks that `throw`/rethrow anywhere in their body,\n * - returns of a computed/meaningful value (calls, identifiers, member\n * expressions, non-empty literals),\n * - `return 0` / `return \"\"`, which are often legitimate results.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSentinelReturn\";\ntype Options = readonly [];\n\n/** Whether a returned expression is one of the swallowing sentinels. */\nfunction isSentinelArgument(arg: TSESTree.Expression | null): boolean {\n if (arg === null) {\n // `return;` — bare return is not in scope (no value-shaped sentinel).\n return false;\n }\n\n // `return null`\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === null) {\n return true;\n }\n\n // `return false`\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === false) {\n return true;\n }\n\n // `return undefined`\n if (arg.type === AST_NODE_TYPES.Identifier && arg.name === \"undefined\") {\n return true;\n }\n\n // `return []` — empty array literal only.\n if (arg.type === AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {\n return true;\n }\n\n // `return {}` — empty object literal only.\n if (\n arg.type === AST_NODE_TYPES.ObjectExpression &&\n arg.properties.length === 0\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Does this subtree contain a `throw` statement, ignoring nested functions\n * (a throw inside a nested function/arrow doesn't rethrow for *this* catch)?\n */\nfunction containsThrow(node: TSESTree.Node): boolean {\n let found = false;\n\n const visit = (current: TSESTree.Node): void => {\n if (found) {\n return;\n }\n\n if (current.type === AST_NODE_TYPES.ThrowStatement) {\n found = true;\n return;\n }\n\n // Do not descend into nested function scopes — a throw there does not\n // propagate out of the current catch synchronously.\n if (\n current.type === AST_NODE_TYPES.FunctionDeclaration ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return;\n }\n\n for (const key of Object.keys(current)) {\n if (key === \"parent\") {\n continue;\n }\n const value = (current as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child)) {\n visit(child);\n }\n }\n } else if (isNode(value)) {\n visit(value);\n }\n }\n };\n\n visit(node);\n return found;\n}\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-sentinel-return-on-catch\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow swallowing a caught error by returning an empty sentinel (`null`, `undefined`, `false`, `[]`, `{}`) as the final statement of a `catch` block.\",\n },\n schema: [],\n messages: {\n noSentinelReturn:\n \"This `catch` block swallows the error by returning an empty sentinel. Rethrow it, return a typed Result, or handle the error explicitly.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CatchClause(node: TSESTree.CatchClause): void {\n const body = node.body.body;\n if (body.length === 0) {\n return;\n }\n\n const last = body[body.length - 1];\n if (last === undefined || last.type !== AST_NODE_TYPES.ReturnStatement) {\n return;\n }\n\n if (!isSentinelArgument(last.argument)) {\n return;\n }\n\n // Conservative: if the catch body throws/rethrows anywhere, it's not\n // silently swallowing the error.\n if (containsThrow(node.body)) {\n return;\n }\n\n context.report({\n node: last,\n messageId: \"noSentinelReturn\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `await` expressions located directly inside the body\n * of a `for` / `for-of` / `for-in` / `while` loop within the same function\n * scope. Awaiting serially inside a loop serializes I/O that is often better\n * expressed as `await Promise.all(xs.map(async (x) => ...))`, letting the\n * operations run concurrently.\n *\n * This rule is intentionally conservative — it prefers a false negative over a\n * false positive:\n * - `for await...of` is NOT flagged (async iteration is the correct tool).\n * - awaits inside a function/arrow defined within the loop are NOT flagged\n * (they belong to a different function scope).\n * - awaits not inside any loop are NOT flagged.\n * At most one report is emitted per offending loop.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSequentialAwait\";\ntype Options = readonly [];\n\n/**\n * Node types that introduce a new function scope. We never descend across one\n * of these when looking for awaits belonging to a loop, because an `await`\n * inside a nested function/arrow is awaited by *that* function, not by the loop.\n */\nfunction isFunctionLike(node: TSESTree.Node): boolean {\n return (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n );\n}\n\n/**\n * Loop node types whose bodies we scan. `ForOfStatement` is handled specially\n * by the caller so that `for await...of` is excluded.\n */\ntype LoopNode =\n | TSESTree.ForStatement\n | TSESTree.ForOfStatement\n | TSESTree.ForInStatement\n | TSESTree.WhileStatement\n | TSESTree.DoWhileStatement;\n\n/**\n * Statement node types that introduce a nested loop. When scanning a loop's\n * body we must NOT descend into another loop — that inner loop's awaits belong\n * to it and are reported when the inner loop is visited. This keeps reporting\n * at one-per-loop and avoids double-flagging an outer loop for an await that\n * only appears inside a nested loop.\n */\nfunction isLoop(node: TSESTree.Node): boolean {\n return (\n node.type === \"ForStatement\" ||\n node.type === \"ForOfStatement\" ||\n node.type === \"ForInStatement\" ||\n node.type === \"WhileStatement\" ||\n node.type === \"DoWhileStatement\"\n );\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-sequential-await\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow serial `await` inside a loop; use `await Promise.all(...)` to run the operations concurrently.\",\n },\n schema: [],\n messages: {\n noSequentialAwait:\n \"Avoid `await` inside a loop — it serializes I/O. Collect the promises and `await Promise.all(xs.map(async (x) => ...))` instead.\",\n },\n },\n defaultOptions: [],\n create(context) {\n /**\n * Walks the subtree rooted at `node`, returning the first `AwaitExpression`\n * that belongs to *this* loop's scope — i.e. reachable without crossing a\n * nested function/arrow boundary or descending into a nested loop. Returns\n * `null` if none.\n *\n * Stopping at function boundaries excludes awaits in nested functions\n * (awaited by that function, not the loop). Stopping at nested-loop\n * boundaries means each loop only \"owns\" its own direct awaits, so an outer\n * loop isn't flagged for an await that lives solely in an inner loop, and\n * every report stays one-per-loop.\n */\n function findAwaitInScope(\n node: TSESTree.Node,\n ): TSESTree.AwaitExpression | null {\n if (node.type === \"AwaitExpression\") {\n return node;\n }\n if (isFunctionLike(node)) {\n // Crossing into a different function scope — its awaits aren't ours.\n return null;\n }\n\n for (const key of Object.keys(node) as (keyof TSESTree.Node)[]) {\n if (key === \"parent\") {\n continue;\n }\n const value = node[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child) && !isLoop(child)) {\n const found = findAwaitInScope(child);\n if (found) {\n return found;\n }\n }\n }\n } else if (isNode(value) && !isLoop(value)) {\n const found = findAwaitInScope(value);\n if (found) {\n return found;\n }\n }\n }\n\n return null;\n }\n\n function isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n }\n\n /**\n * Reports the loop if its body contains an `await` belonging to the same\n * function scope. The loop's `body` (and, for the C-style `for`, its init /\n * test / update expressions) are the only places an \"await in this loop\"\n * can live; awaits in a *nested* loop are caught when that nested loop is\n * itself visited, keeping reports at one-per-loop.\n */\n function checkLoop(node: LoopNode): void {\n const parts: (TSESTree.Node | null)[] = [node.body];\n\n if (node.type === \"ForStatement\") {\n parts.push(node.init, node.test, node.update);\n } else if (\n node.type === \"ForOfStatement\" ||\n node.type === \"ForInStatement\"\n ) {\n parts.push(node.right);\n } else {\n // While / DoWhile.\n parts.push(node.test);\n }\n\n for (const part of parts) {\n // A part that is itself a loop (e.g. `for (...) for (...) await f()`)\n // is owned by that inner loop and checked when it is visited.\n if (part && !isLoop(part) && findAwaitInScope(part)) {\n context.report({ node, messageId: \"noSequentialAwait\" });\n return;\n }\n }\n }\n\n return {\n ForStatement: checkLoop,\n ForInStatement: checkLoop,\n WhileStatement: checkLoop,\n DoWhileStatement: checkLoop,\n ForOfStatement(node: TSESTree.ForOfStatement): void {\n // `for await...of` is correct async iteration — never flag it.\n if (node.await) {\n return;\n }\n checkLoop(node);\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow string accumulation via `+=` inside a loop, which is\n * the classic O(n^2) string-building antipattern: each `+=` rebuilds the whole\n * string. Push the parts onto an array and `arr.join(\"\")` after the loop\n * instead.\n *\n * This is a purely SYNTACTIC rule — it uses scope analysis (not the type\n * service) to confirm the left-hand side was declared with a string-literal\n * initializer (`let s = \"\"`, `= \"...\"`, or a template literal). It is\n * deliberately conservative: when the initializer type cannot be determined\n * (no initializer, a non-literal expression, a parameter, etc.) the `+=` is\n * NOT flagged. This mirrors the Python rule SARJ002.\n *\n * KNOWN GAP (false-negative): only the compound `+=` operator is detected. The\n * equivalent longhand `s = s + x` (a plain `=` assignment whose RHS is a\n * `BinaryExpression` referencing the LHS) has the same O(n^2) behavior but is\n * NOT flagged. Left as a deliberate scope limit to keep the rule conservative.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"noStringConcatInLoop\";\ntype Options = readonly [];\n\nconst LOOP_NODE_TYPES = new Set<string>([\n \"ForStatement\",\n \"ForOfStatement\",\n \"ForInStatement\",\n \"WhileStatement\",\n \"DoWhileStatement\",\n]);\n\n/**\n * Returns true if the given expression node is a string-producing literal:\n * a string `Literal` (`\"\"`, `\"...\"`, `'...'`) or a `TemplateLiteral`.\n */\nfunction isStringLiteralInit(node: TSESTree.Expression | null): boolean {\n if (node === null) {\n return false;\n }\n if (node.type === \"TemplateLiteral\") {\n return true;\n }\n if (node.type === \"Literal\") {\n return typeof node.value === \"string\";\n }\n return false;\n}\n\n/**\n * Walk the chain of enclosing scopes to find the variable definition for the\n * given identifier name. Returns the resolved `Variable`, or `undefined` if it\n * cannot be found (e.g. an undeclared global or an out-of-scope reference).\n */\nfunction findVariable(\n scope: Scope.Scope,\n name: string,\n): Scope.Variable | undefined {\n let current: Scope.Scope | null = scope;\n while (current !== null) {\n const variable = current.variables.find((v) => v.name === name);\n if (variable !== undefined) {\n return variable;\n }\n current = current.upper;\n }\n return undefined;\n}\n\n/**\n * Returns true if the variable was declared with a string-literal initializer.\n * Conservative: if the variable has no single string-initialized declarator\n * (no init, non-literal init, multiple conflicting declarators), returns false.\n */\nfunction isStringInitializedVariable(variable: Scope.Variable): boolean {\n // A variable can technically have multiple declarators (e.g. via `var`\n // hoisting / redeclaration). Only treat it as string-initialized when there\n // is exactly one declarator and it has a string-literal initializer.\n if (variable.defs.length !== 1) {\n return false;\n }\n const def = variable.defs[0];\n if (def === undefined || def.type !== \"Variable\") {\n // Parameters, function names, imports, etc. — type unknown, don't flag.\n return false;\n }\n const declarator = def.node;\n if (declarator.type !== \"VariableDeclarator\") {\n return false;\n }\n return isStringLiteralInit(declarator.init);\n}\n\n/**\n * Returns true if `node` is contained within the body of a loop statement.\n * Walks ancestors and, for each loop, ensures the node is inside the loop's\n * BODY (not its test/init/update clauses, which run a bounded number of times\n * relative to the body and aren't the antipattern we target).\n */\nfunction isInsideLoopBody(node: TSESTree.Node): boolean {\n let child: TSESTree.Node = node;\n let parent = node.parent;\n while (parent !== undefined && parent !== null) {\n if (LOOP_NODE_TYPES.has(parent.type)) {\n // `body` is the property that holds the looped statements for every\n // loop variant we care about.\n const loop = parent as\n | TSESTree.ForStatement\n | TSESTree.ForOfStatement\n | TSESTree.ForInStatement\n | TSESTree.WhileStatement\n | TSESTree.DoWhileStatement;\n if (loop.body === child) {\n return true;\n }\n }\n child = parent;\n parent = parent.parent;\n }\n return false;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-string-concat-in-loop\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Disallow O(n^2) string building via `+=` on a string variable inside a loop; push parts to an array and `join` instead.\",\n },\n schema: [],\n messages: {\n noStringConcatInLoop:\n \"Avoid building a string with `+=` inside a loop — this is O(n^2). Push the parts onto an array and use `arr.join(\\\"\\\")` after the loop.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n AssignmentExpression(node: TSESTree.AssignmentExpression): void {\n // Only the compound `+=` operator builds up a value.\n if (node.operator !== \"+=\") {\n return;\n }\n // The LHS must be a plain variable reference.\n if (node.left.type !== \"Identifier\") {\n return;\n }\n // Must occur inside a loop body, else it's a one-shot append.\n if (!isInsideLoopBody(node)) {\n return;\n }\n\n const scope = context.sourceCode.getScope(node);\n const variable = findVariable(scope, node.left.name);\n // Conservative: can't resolve the declaration -> don't flag.\n if (variable === undefined) {\n return;\n }\n // Only flag when we can confirm the LHS was string-initialized; a\n // numeric initializer (or anything non-string) is intentionally\n // excluded to avoid false positives.\n if (!isStringInitializedVariable(variable)) {\n return;\n }\n\n context.report({\n node,\n messageId: \"noStringConcatInLoop\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Flag `'use client'` files with no hooks or event handlers.\n *\n * If a file is marked `'use client'` but contains no hook calls\n * (`useState`/`useEffect`/etc.), no JSX event handlers (`onClick`,\n * `onChange`, etc.), no browser globals, no client-only imports, and no\n * other client-side indicators (classes, re-exports), the directive is\n * likely unnecessary and the file could be a React Server Component —\n * improving cold-start, bundle size, and SEO.\n *\n * False-positive watch: components that only use client-side context\n * (e.g. theme providers) without hooks or events still need `'use client'`.\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/rendering/client-components\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"unnecessaryUseClient\";\ntype Options = readonly [];\n\nconst HOOK_REGEX = /^use([A-Z]|$)/;\nconst EVENT_PROP_REGEX = /^on[A-Z]/;\nconst ERROR_FILE_REGEX = /\\b(?:global-)?error\\.[jt]sx?$/;\n\nconst BROWSER_GLOBALS: ReadonlySet<string> = new Set([\n \"window\",\n \"document\",\n \"navigator\",\n \"localStorage\",\n \"sessionStorage\",\n \"location\",\n \"history\",\n \"screen\",\n \"requestAnimationFrame\",\n \"cancelAnimationFrame\",\n \"CustomEvent\",\n \"Event\",\n \"MouseEvent\",\n \"KeyboardEvent\",\n \"TouchEvent\",\n]);\n\nconst CLIENT_ONLY_PACKAGES_REGEX =\n /^(?:@radix-ui\\/|framer-motion|react-dom|react-day-picker|@floating-ui\\/|react-select|react-toastify|react-hook-form|recharts|react-dropzone|react-slick|react-swipeable|react-resizable|react-draggable|react-beautiful-dnd|@hello-pangea\\/dnd|react-virtualized|react-window|@tanstack\\/react-table|@tanstack\\/react-query|react-redux|recoil|jotai|zustand|@tippyjs\\/react|react-color|react-datepicker|next-themes|react-helmet|react-helmet-async|styled-components|@emotion\\/)/;\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\nconst isUseClientDirective = (\n node: TSESTree.Statement,\n): node is TSESTree.ExpressionStatement => {\n return (\n node.type === AST_NODE_TYPES.ExpressionStatement &&\n node.expression.type === AST_NODE_TYPES.Literal &&\n node.expression.value === \"use client\"\n );\n};\n\nconst isGlobalReference = (\n node: TSESTree.Identifier,\n context: Ctx,\n): boolean => {\n if (!BROWSER_GLOBALS.has(node.name)) return false;\n\n const parent = node.parent;\n if (parent !== undefined) {\n // `obj.window` — `window` is a property name, not a global reference.\n if (\n parent.type === AST_NODE_TYPES.MemberExpression &&\n parent.property === node &&\n !parent.computed\n ) {\n return false;\n }\n // `{ window: ... }` — property key, not a global reference.\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === node &&\n !parent.computed\n ) {\n return false;\n }\n // Type annotations / type-only positions are not runtime references.\n if (parent.type.startsWith(\"TS\")) {\n return false;\n }\n }\n\n // If there's a local binding for this name anywhere up the chain, it's not\n // a reference to the browser global.\n let scope: Scope.Scope | null = context.sourceCode.getScope(node);\n while (scope !== null) {\n const variable = scope.set.get(node.name);\n if (variable !== undefined && variable.defs.length > 0) {\n return false;\n }\n scope = scope.upper;\n }\n\n return true;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-unnecessary-use-client\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag `'use client'` files with no hooks or event handlers — they could be RSC.\",\n },\n schema: [],\n messages: {\n unnecessaryUseClient:\n \"'use client' directive but no hooks (use*), JSX event handlers (on*), browser globals, or client-only imports found. Consider removing the directive and serving as a React Server Component.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n if (ERROR_FILE_REGEX.test(filename)) {\n return {};\n }\n\n let directiveNode: TSESTree.ExpressionStatement | null = null;\n let hasClientIndicator = false;\n\n const markIfHookOrContext = (\n callee: TSESTree.CallExpression[\"callee\"],\n ): void => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n if (HOOK_REGEX.test(callee.name) || callee.name === \"createContext\") {\n hasClientIndicator = true;\n }\n return;\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n const name = callee.property.name;\n if (HOOK_REGEX.test(name) || name === \"createContext\") {\n hasClientIndicator = true;\n }\n }\n };\n\n return {\n Program(node): void {\n for (const stmt of node.body) {\n // Directives must be the first statements; once we see a non-\n // ExpressionStatement, stop scanning.\n if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) break;\n if (isUseClientDirective(stmt)) {\n directiveNode = stmt;\n break;\n }\n }\n },\n CallExpression(node): void {\n // The `Program` visitor (entered first) has already determined whether\n // this file has a `'use client'` directive. If it doesn't, the result\n // can't change — skip all of the per-node indicator work, including the\n // hot scope-resolution in the `Identifier` visitor below.\n if (directiveNode === null) return;\n markIfHookOrContext(node.callee);\n },\n JSXAttribute(node): void {\n if (directiveNode === null) return;\n if (\n node.name.type === AST_NODE_TYPES.JSXIdentifier &&\n EVENT_PROP_REGEX.test(node.name.name)\n ) {\n hasClientIndicator = true;\n }\n },\n ImportDeclaration(node): void {\n if (directiveNode === null) return;\n if (\n typeof node.source.value === \"string\" &&\n CLIENT_ONLY_PACKAGES_REGEX.test(node.source.value)\n ) {\n hasClientIndicator = true;\n }\n },\n ExportNamedDeclaration(node): void {\n if (directiveNode === null) return;\n if (node.source !== null) {\n hasClientIndicator = true;\n }\n },\n ExportAllDeclaration(node): void {\n if (directiveNode === null) return;\n if (node.source !== null) {\n hasClientIndicator = true;\n }\n },\n ClassDeclaration(): void {\n if (directiveNode === null) return;\n hasClientIndicator = true;\n },\n ClassExpression(): void {\n if (directiveNode === null) return;\n hasClientIndicator = true;\n },\n Identifier(node): void {\n if (directiveNode === null) return;\n if (isGlobalReference(node, context)) {\n hasClientIndicator = true;\n }\n },\n \"Program:exit\"(): void {\n if (directiveNode !== null && !hasClientIndicator) {\n context.report({\n node: directiveNode,\n messageId: \"unnecessaryUseClient\",\n });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag object types that model mutually-exclusive states with a\n * boolean status flag plus many optional members. A shape like\n * `{ success: boolean; data?: T; error?: E; code?: number }` encodes \"success\n * vs. error\" implicitly and lets illegal states (e.g. `success: true` with an\n * `error`) be representable.\n *\n * Such shapes should be modelled as a discriminated union, e.g.\n * `{ ok: true; data: T } | { ok: false; error: E }`, so the compiler enforces\n * that exactly one branch's fields are present.\n *\n * This is the TypeScript mirror of the Python rule SARJ005.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport { AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"preferDiscriminatedUnion\";\ntype Options = readonly [];\n\n/**\n * Boolean-typed member names that read as a success/error status discriminant.\n */\nconst STATUS_MEMBER_NAMES: ReadonlySet<string> = new Set([\n \"success\",\n \"ok\",\n \"error\",\n \"failed\",\n \"isError\",\n]);\n\nconst MIN_OPTIONAL_MEMBERS = 2;\n\n/**\n * Returns the property key name for a member if it is a plain identifier or\n * string-literal property signature, otherwise `null`.\n */\nfunction getMemberName(member: TSESTree.TypeElement): string | null {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return null;\n }\n const { key } = member;\n if (key.type === AST_NODE_TYPES.Identifier) {\n return key.name;\n }\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") {\n return key.value;\n }\n return null;\n}\n\n/**\n * Whether a property signature is annotated with `boolean`.\n */\nfunction isBooleanTyped(member: TSESTree.TSPropertySignature): boolean {\n return (\n member.typeAnnotation?.typeAnnotation.type ===\n AST_NODE_TYPES.TSBooleanKeyword\n );\n}\n\n/**\n * Returns true when the object type literal has BOTH a boolean-typed status\n * member AND at least `MIN_OPTIONAL_MEMBERS` optional members.\n */\nfunction looksLikeMutuallyExclusiveState(\n typeLiteral: TSESTree.TSTypeLiteral,\n): boolean {\n let hasStatusBoolean = false;\n let optionalCount = 0;\n\n for (const member of typeLiteral.members) {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n continue;\n }\n\n if (member.optional) {\n optionalCount += 1;\n }\n\n const name = getMemberName(member);\n if (\n name !== null &&\n STATUS_MEMBER_NAMES.has(name) &&\n isBooleanTyped(member)\n ) {\n hasStatusBoolean = true;\n }\n }\n\n return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-discriminated-union\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag object types with a boolean status flag and many optionals; model them as a discriminated union instead.\",\n },\n schema: [],\n messages: {\n preferDiscriminatedUnion:\n \"This object type uses a boolean status flag alongside several optional fields, which lets illegal states be representable. Model it as a `z.discriminatedUnion` / discriminated union (e.g. `{ ok: true; data: T } | { ok: false; error: E }`) to make illegal states unrepresentable.\",\n },\n },\n defaultOptions: [],\n create(context) {\n function checkTypeLiteral(\n typeLiteral: TSESTree.TSTypeLiteral,\n reportNode: TSESTree.Node,\n ): void {\n if (looksLikeMutuallyExclusiveState(typeLiteral)) {\n context.report({\n node: reportNode,\n messageId: \"preferDiscriminatedUnion\",\n });\n }\n }\n\n return {\n TSInterfaceDeclaration(\n node: TSESTree.TSInterfaceDeclaration,\n ): void {\n // An interface body is structurally an object type literal; reuse the\n // same membership analysis by treating its `body.body` as members.\n const synthetic: TSESTree.TSTypeLiteral = {\n ...node.body,\n type: AST_NODE_TYPES.TSTypeLiteral,\n members: node.body.body,\n } as TSESTree.TSTypeLiteral;\n checkTypeLiteral(synthetic, node);\n },\n \"TSTypeAliasDeclaration > TSTypeLiteral\"(\n node: TSESTree.TSTypeLiteral,\n ): void {\n checkTypeLiteral(node, node.parent);\n },\n };\n },\n});\n","/**\n * @fileoverview Don't access `response.json()` fields without a Zod parse first.\n *\n * Pattern flagged:\n * const data = await response.json();\n * doSomething(data.foo); // <-- unvalidated property access\n *\n * Encouraged:\n * const data = MySchema.parse(await response.json());\n * doSomething(data.foo); // typed + validated\n *\n * Heuristic:\n * - Track variables initialized to `await someCall.json()` using ESLint's scope manager.\n * - Untrack if reassigned to anything other than another raw `json()` call.\n * - Flag MemberExpression reads and destructuring off tracked variables.\n * - `.parse()` / `.safeParse()` chained directly on the json call are legit\n * and never produce a tracked binding in the first place.\n *\n * References:\n * - https://zod.dev/?id=parse\n * - https://www.totaltypescript.com/parse-don-t-validate\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"unparsedJsonAccess\";\ntype Options = readonly [];\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\n/**\n * Peel TypeScript wrapper nodes that don't affect the underlying value\n * (`as Foo`, `<Foo>x`, `x!`, `x satisfies Foo`, parentheses, optional chain\n * wrappers). Returns the inner expression we actually care about.\n */\nconst unwrap = (\n node: TSESTree.Node | null | undefined,\n): TSESTree.Node | null => {\n let current: TSESTree.Node | null | undefined = node;\n while (current !== null && current !== undefined) {\n if (\n current.type === AST_NODE_TYPES.TSAsExpression ||\n current.type === AST_NODE_TYPES.TSTypeAssertion ||\n current.type === AST_NODE_TYPES.TSNonNullExpression ||\n current.type === AST_NODE_TYPES.TSSatisfiesExpression\n ) {\n current = current.expression;\n } else if (current.type === AST_NODE_TYPES.ChainExpression) {\n current = current.expression;\n } else {\n break;\n }\n }\n return current ?? null;\n};\n\n/**\n * Returns true if the expression is (optionally awaited) `<x>.json()`.\n */\nconst isJsonCall = (\n node: TSESTree.Node | null | undefined,\n): boolean => {\n let current = unwrap(node);\n if (current === null) return false;\n if (current.type === AST_NODE_TYPES.AwaitExpression) {\n current = unwrap(current.argument);\n }\n if (current === null || current.type !== AST_NODE_TYPES.CallExpression) {\n return false;\n }\n const callee = unwrap(current.callee);\n if (callee === null || callee.type !== AST_NODE_TYPES.MemberExpression) {\n return false;\n }\n const property = unwrap(callee.property);\n return (\n property !== null &&\n property.type === AST_NODE_TYPES.Identifier &&\n property.name === \"json\"\n );\n};\n\nconst findVariable = (\n scope: Scope.Scope | null,\n name: string,\n): Scope.Variable | null => {\n let current: Scope.Scope | null = scope;\n while (current !== null) {\n const variable = current.set.get(name);\n if (variable !== undefined) return variable;\n current = current.upper;\n }\n return null;\n};\n\nconst isUnvalidatedVariableRef = (\n node: TSESTree.Node | null | undefined,\n scope: Scope.Scope,\n tracked: ReadonlySet<Scope.Variable>,\n): boolean => {\n const unwrapped = unwrap(node);\n if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES.Identifier) {\n return false;\n }\n const variable = findVariable(scope, unwrapped.name);\n return variable !== null && tracked.has(variable);\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-schema-for-api-payload\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require Zod (or similar) schema validation on `response.json()` before property access.\",\n },\n schema: [],\n messages: {\n unparsedJsonAccess:\n \"Property access on the result of `response.json()` without a schema parse. Pipe through `XSchema.parse(...)` (Zod) before reading fields.\",\n },\n },\n defaultOptions: [],\n create(context: Ctx) {\n const unvalidatedVariables = new Set<Scope.Variable>();\n\n const trackInitializer = (\n declarator: TSESTree.VariableDeclarator,\n ): void => {\n if (!isJsonCall(declarator.init)) return;\n const declaredVars = context.sourceCode.getDeclaredVariables(declarator);\n const variable = declaredVars[0];\n if (variable !== undefined) {\n unvalidatedVariables.add(variable);\n }\n };\n\n return {\n VariableDeclarator(node): void {\n const scope = context.sourceCode.getScope(node);\n\n if (node.id.type === AST_NODE_TYPES.Identifier) {\n trackInitializer(node);\n return;\n }\n\n if (\n node.id.type === AST_NODE_TYPES.ObjectPattern ||\n node.id.type === AST_NODE_TYPES.ArrayPattern\n ) {\n if (isJsonCall(node.init)) {\n context.report({ node: node.id, messageId: \"unparsedJsonAccess\" });\n return;\n }\n if (\n isUnvalidatedVariableRef(node.init, scope, unvalidatedVariables)\n ) {\n context.report({ node: node.id, messageId: \"unparsedJsonAccess\" });\n }\n }\n },\n AssignmentExpression(node): void {\n const scope = context.sourceCode.getScope(node);\n\n if (node.left.type === AST_NODE_TYPES.Identifier) {\n const variable = findVariable(scope, node.left.name);\n if (variable === null) return;\n if (isJsonCall(node.right)) {\n unvalidatedVariables.add(variable);\n } else {\n // Reassigned to a parse call or something else: drop tracking.\n unvalidatedVariables.delete(variable);\n }\n return;\n }\n\n if (\n node.left.type === AST_NODE_TYPES.ObjectPattern ||\n node.left.type === AST_NODE_TYPES.ArrayPattern\n ) {\n if (isJsonCall(node.right)) {\n context.report({\n node: node.left,\n messageId: \"unparsedJsonAccess\",\n });\n return;\n }\n if (\n isUnvalidatedVariableRef(node.right, scope, unvalidatedVariables)\n ) {\n context.report({\n node: node.left,\n messageId: \"unparsedJsonAccess\",\n });\n }\n }\n },\n MemberExpression(node): void {\n const scope = context.sourceCode.getScope(node);\n const obj = unwrap(node.object);\n\n if (isJsonCall(obj)) {\n // Direct `.foo` access on `(await r.json()).foo` is always bad,\n // unless the parent call is a `.parse()`/`.safeParse()` — in which\n // case it's a validation, not an unvalidated read.\n const parent = node.parent;\n if (\n parent.type === AST_NODE_TYPES.CallExpression &&\n parent.callee === node &&\n node.property.type === AST_NODE_TYPES.Identifier &&\n (node.property.name === \"parse\" ||\n node.property.name === \"safeParse\")\n ) {\n return;\n }\n context.report({ node, messageId: \"unparsedJsonAccess\" });\n return;\n }\n\n if (\n obj !== null &&\n obj.type === AST_NODE_TYPES.Identifier &&\n isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)\n ) {\n context.report({ node, messageId: \"unparsedJsonAccess\" });\n const variable = findVariable(scope, obj.name);\n if (variable !== null) {\n unvalidatedVariables.delete(variable);\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Enforce design-system semantic color tokens over raw Tailwind\n * palette classes and hardcoded color values.\n *\n * Scoped to genuine className positions to avoid false positives on non-class\n * strings (Tailwind `safelist`, `toHaveClass(...)` test assertions, prose, color\n * maps): JSX `className`, the args of `cn()`/`clsx()`/`cva()`/`tv()`/`cx()`/\n * `twMerge()` (recursing into cva variant objects), and `*class*`-named\n * variables/object properties. Plus inline color literals on JSX `style`/`fill`/\n * `stroke`.\n *\n * Flags:\n * - raw palette classes: `text-red-500`, `bg-slate-200/50`\n * - arbitrary color values: `bg-[#fff]`, `text-[rgb(...)]`, `ring-[oklch(...)]`\n * - inline color literals: `style={{ color: \"#111827\" }}`, `fill=\"#000\"`\n *\n * Allowed: semantic tokens (`bg-primary`, `text-muted-foreground`, `bg-chart-1`),\n * `white`/`black` (the `bg-black/50` overlay idiom rarely has a token), `var(--…)`,\n * `currentColor`, and non-color arbitraries (`w-[437px]`, `grid-cols-[auto_1fr]`).\n * No autofix — use a semantic token, or for charts / standalone pages / 3rd-party\n * config add `// eslint-disable-next-line @sarj/prefer-semantic-colors -- <reason>`.\n */\n\nimport { AST_NODE_TYPES, ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\nimport { classTokens, tailwindBase } from \"./_tailwind.js\";\n\ntype MessageIds = \"rawPalette\" | \"arbitraryColor\" | \"inlineColor\";\ntype Options = readonly [];\n\nconst COLOR_PREFIXES =\n \"text|bg|border(?:-[trblxyse])?|ring(?:-offset)?|fill|stroke|from|via|to|divide|decoration|placeholder|accent|caret|shadow|outline\";\nconst PALETTE =\n \"red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|slate|gray|zinc|neutral|stone\";\nconst COLOR_FN = \"rgba?|hsla?|hwb|oklch|oklab|lab|lch|color\";\n\nconst RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-\\\\d{2,3}(?:/\\\\d{1,3})?$`);\nconst ARBITRARY_COLOR_RE = new RegExp(\n `^(?:${COLOR_PREFIXES})-\\\\[(?:#[0-9a-fA-F]{3,8}|(?:${COLOR_FN})\\\\([^\\\\]]*\\\\))\\\\]$`,\n \"i\",\n);\n\n/** Call expressions whose string args are className fragments. */\nconst CLASS_FNS = new Set<string>([\"cn\", \"clsx\", \"cva\", \"tv\", \"cx\", \"twMerge\", \"classnames\", \"classNames\"]);\nconst CLASS_NAME_RE = /class/i;\n\n/** CSS color-bearing properties, in their JSX (camelCase) and SVG-attribute forms. */\nconst STYLE_COLOR_PROPS = new Set<string>([\n \"color\",\n \"background\",\n \"backgroundColor\",\n \"borderColor\",\n \"borderTopColor\",\n \"borderRightColor\",\n \"borderBottomColor\",\n \"borderLeftColor\",\n \"outlineColor\",\n \"caretColor\",\n \"textDecorationColor\",\n \"columnRuleColor\",\n \"fill\",\n \"stroke\",\n \"stopColor\",\n \"floodColor\",\n \"lightingColor\",\n]);\nconst RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\\\b|\\\\b(?:${COLOR_FN})\\\\s*\\\\(`, \"i\");\n\nconst propName = (key: TSESTree.Property[\"key\"]): string | null => {\n if (key.type === AST_NODE_TYPES.Identifier) return key.name;\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") return key.value;\n return null;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-semantic-colors\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce design-system semantic color tokens (bg-primary, text-destructive, …) over raw Tailwind palette classes (text-red-500), arbitrary color values (bg-[#fff]), and inline color literals.\",\n },\n schema: [],\n messages: {\n rawPalette:\n \"Raw palette class '{{class}}' — use a semantic token (e.g. text-foreground, bg-primary, text-destructive, bg-muted).\",\n arbitraryColor:\n \"Hardcoded color '{{class}}' — use a semantic token, or var(--…). For charts/brand add an eslint-disable with a reason.\",\n inlineColor:\n \"Hardcoded color '{{value}}' — use a semantic token / CSS variable. For charts/standalone pages add an eslint-disable with a reason.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const reportClasses = (value: string, node: TSESTree.Node): void => {\n for (const token of classTokens(value)) {\n const base = tailwindBase(token);\n if (RAW_PALETTE_RE.test(base)) {\n context.report({ node, messageId: \"rawPalette\", data: { class: token } });\n } else if (ARBITRARY_COLOR_RE.test(base)) {\n context.report({ node, messageId: \"arbitraryColor\", data: { class: token } });\n }\n }\n };\n\n // Walk a node that holds className fragments: strings, templates, arrays, cva\n // variant objects, and conditionals. CallExpressions are handled separately, so\n // they're not recursed here (avoids double-reporting cn()/cva() args).\n const checkClassNode = (node: TSESTree.Node | null): void => {\n if (node === null) return;\n switch (node.type) {\n case AST_NODE_TYPES.Literal:\n if (typeof node.value === \"string\") reportClasses(node.value, node);\n break;\n case AST_NODE_TYPES.TemplateLiteral:\n for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? \"\", quasi);\n break;\n case AST_NODE_TYPES.ArrayExpression:\n for (const element of node.elements) {\n if (element !== null && element.type !== AST_NODE_TYPES.SpreadElement) checkClassNode(element);\n }\n break;\n case AST_NODE_TYPES.ObjectExpression:\n for (const property of node.properties) {\n if (property.type === AST_NODE_TYPES.Property) checkClassNode(property.value);\n }\n break;\n case AST_NODE_TYPES.ConditionalExpression:\n checkClassNode(node.consequent);\n checkClassNode(node.alternate);\n break;\n case AST_NODE_TYPES.LogicalExpression:\n checkClassNode(node.right);\n break;\n default:\n break;\n }\n };\n\n const checkColorValueNode = (node: TSESTree.Node): void => {\n if (\n node.type === AST_NODE_TYPES.Literal &&\n typeof node.value === \"string\" &&\n RAW_COLOR_VALUE_RE.test(node.value)\n ) {\n context.report({ node, messageId: \"inlineColor\", data: { value: node.value } });\n }\n };\n\n return {\n \"JSXAttribute[name.name='className']\"(node: TSESTree.JSXAttribute): void {\n if (node.value === null) return;\n if (node.value.type === AST_NODE_TYPES.Literal) checkClassNode(node.value);\n else if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer) {\n if (node.value.expression.type !== AST_NODE_TYPES.JSXEmptyExpression) {\n checkClassNode(node.value.expression);\n }\n }\n },\n CallExpression(node: TSESTree.CallExpression): void {\n if (node.callee.type === AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {\n for (const arg of node.arguments) {\n if (arg.type !== AST_NODE_TYPES.SpreadElement) checkClassNode(arg);\n }\n }\n },\n VariableDeclarator(node: TSESTree.VariableDeclarator): void {\n if (node.id.type === AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {\n checkClassNode(node.init);\n }\n },\n Property(node: TSESTree.Property): void {\n const name = propName(node.key);\n if (name !== null && CLASS_NAME_RE.test(name)) checkClassNode(node.value);\n },\n // SVG presentation attributes: <path fill=\"#000\" stroke=\"#fff\" />\n \"JSXAttribute[name.name=/^(fill|stroke|color)$/]\"(node: TSESTree.JSXAttribute): void {\n if (node.value?.type === AST_NODE_TYPES.Literal) checkColorValueNode(node.value);\n },\n // Inline style objects: style={{ color: \"#111827\", backgroundColor: \"#fff\" }}\n \"JSXAttribute[name.name='style'] ObjectExpression > Property\"(node: TSESTree.Property): void {\n const name = propName(node.key);\n if (name !== null && STYLE_COLOR_PROPS.has(name)) checkColorValueNode(node.value);\n },\n };\n },\n});\n","/**\n * @fileoverview Shared helpers for the Tailwind-className rules. className values\n * are reachable as plain string `Literal`s (attribute values, `cn()`/`clsx()`/\n * `cva()`/`tv()` args, and className-holding constants) and as the static quasis of\n * `TemplateLiteral`s — so the rules visit both node types and run these helpers.\n */\n\n/**\n * Strip Tailwind variant prefixes (`hover:`, `dark:`, `focus-visible:`, …) and a\n * leading `!` important marker, leaving the bare utility (`bg-red-500`). Variants are\n * `[a-z0-9-]+:` runs at the start; bracketed arbitrary values never start a token, so\n * a `:` inside `[url(http://…)]` is not mistaken for a variant separator.\n */\nexport const tailwindBase = (token: string): string =>\n token.replace(/^(?:[a-z0-9-]+:)+/i, \"\").replace(/^!/, \"\");\n\n/** Split a className string into its non-empty class tokens. */\nexport const classTokens = (value: string): readonly string[] =>\n value.split(/\\s+/).filter(Boolean);\n","/**\n * @fileoverview Prefer Next.js Server Actions over /api/* mutations.\n *\n * Flags mutations against internal `/api/*` URLs (POST/PUT/DELETE/PATCH) via\n * `fetch`, axios-style helpers, or direct axios/request calls. GET requests\n * and external URLs are ignored. Tests, scripts, and Next.js route handlers\n * are skipped because Server Actions don't apply there.\n *\n * The member branch (`api.post('/api/x')`) intentionally skips calls that pass\n * a function argument (e.g. `router.post('/api/x', handler)`) so Express-style\n * route *definitions* aren't mistaken for client-side mutations.\n *\n * References:\n * - https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"preferServerAction\";\ntype Options = readonly [];\n\nconst MUTATION_METHODS = new Set([\"POST\", \"PUT\", \"DELETE\", \"PATCH\"]);\nconst AXIOS_MUTATION_METHODS = new Set([\"post\", \"put\", \"delete\", \"patch\"]);\n\nconst SKIP_FILE_REGEX =\n /(?:\\.test\\.[jt]sx?$|\\.spec\\.[jt]sx?$|\\/tests?\\/|\\/__tests__\\/|\\/scripts?\\/|\\/app\\/api\\/.*\\/route\\.[jt]sx?$|\\/pages\\/api\\/)/;\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\nfunction getScope(\n context: Ctx,\n node: TSESTree.Node,\n): Scope.Scope {\n return context.sourceCode.getScope(node);\n}\n\n/**\n * Walk up the scope chain looking for a variable declared with a single\n * initializer; if found, return the initializer expression so we can analyze\n * it. Falls back to the original node when resolution is not possible.\n */\nfunction resolveNode(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): TSESTree.Node | null {\n if (!node) return null;\n if (node.type !== \"Identifier\") return node;\n\n let scope: Scope.Scope | null = getScope(context, node);\n while (scope) {\n const variable = scope.set.get(node.name);\n if (variable && variable.defs.length === 1) {\n const def = variable.defs[0];\n if (def && def.type === \"Variable\") {\n const declarator = def.node;\n if (\n declarator.type === \"VariableDeclarator\" &&\n declarator.init\n ) {\n return declarator.init;\n }\n }\n }\n scope = scope.upper;\n }\n return node;\n}\n\nfunction isApiUrl(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): boolean {\n const resolved = resolveNode(node, context);\n if (!resolved) return false;\n\n if (resolved.type === \"Literal\" && typeof resolved.value === \"string\") {\n return resolved.value.startsWith(\"/api/\");\n }\n if (resolved.type === \"TemplateLiteral\") {\n const firstQuasi = resolved.quasis[0];\n const cooked = firstQuasi?.value.cooked;\n return typeof cooked === \"string\" && cooked.startsWith(\"/api/\");\n }\n if (resolved.type === \"BinaryExpression\" && resolved.operator === \"+\") {\n return isApiUrl(resolved.left, context);\n }\n return false;\n}\n\nfunction isMutationMethod(\n node: TSESTree.Node | null | undefined,\n context: Ctx,\n): boolean {\n const resolved = resolveNode(node, context);\n if (!resolved) return false;\n\n if (resolved.type === \"Literal\" && typeof resolved.value === \"string\") {\n return MUTATION_METHODS.has(resolved.value.toUpperCase());\n }\n\n if (\n resolved.type === \"TemplateLiteral\" &&\n resolved.expressions.length === 0\n ) {\n const val = resolved.quasis.map((q) => q.value.cooked).join(\"\");\n return MUTATION_METHODS.has(val.toUpperCase());\n }\n\n if (resolved.type === \"ConditionalExpression\") {\n return (\n isMutationMethod(resolved.consequent, context) ||\n isMutationMethod(resolved.alternate, context)\n );\n }\n\n if (resolved.type === \"LogicalExpression\" && resolved.operator === \"||\") {\n return (\n isMutationMethod(resolved.left, context) ||\n isMutationMethod(resolved.right, context)\n );\n }\n\n return false;\n}\n\nfunction getPropertyNode(\n objNode: TSESTree.Node | null | undefined,\n propName: string,\n): TSESTree.Node | null {\n if (!objNode || objNode.type !== \"ObjectExpression\") return null;\n for (const prop of objNode.properties) {\n if (prop.type !== \"Property\") continue;\n let keyName: string | null = null;\n if (prop.key.type === \"Identifier\" && !prop.computed) {\n keyName = prop.key.name;\n } else if (\n prop.key.type === \"Literal\" &&\n typeof prop.key.value === \"string\"\n ) {\n keyName = prop.key.value;\n }\n if (keyName === propName) {\n // Skip destructuring patterns — they're not valid as config values.\n if (\n prop.value.type === \"AssignmentPattern\" ||\n prop.value.type === \"ArrayPattern\" ||\n prop.value.type === \"ObjectPattern\"\n ) {\n return null;\n }\n return prop.value;\n }\n }\n return null;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-server-actions\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Prefer Next.js Server Actions over /api/* mutations.\",\n },\n schema: [],\n messages: {\n preferServerAction:\n \"Mutation against /api/* — prefer a Next.js Server Action for type-safety and to avoid the JSON round-trip.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n if (SKIP_FILE_REGEX.test(filename)) {\n return {};\n }\n\n return {\n CallExpression(node) {\n let isMutation = false;\n\n // 1. Standard fetch('/api/orders', { method: 'POST' })\n if (\n node.callee.type === \"Identifier\" &&\n node.callee.name === \"fetch\"\n ) {\n const urlArg = node.arguments[0];\n if (urlArg && urlArg.type !== \"SpreadElement\" && isApiUrl(urlArg, context)) {\n const initArg = node.arguments[1];\n if (initArg && initArg.type !== \"SpreadElement\") {\n const resolvedInit = resolveNode(initArg, context);\n const methodNode = getPropertyNode(resolvedInit, \"method\");\n if (methodNode && isMutationMethod(methodNode, context)) {\n isMutation = true;\n }\n }\n }\n }\n // 2. Custom wrappers or Axios: api.post('/api/orders') or axios.put('/api/orders')\n else if (\n node.callee.type === \"MemberExpression\" &&\n node.callee.property.type === \"Identifier\" &&\n !node.callee.computed\n ) {\n const methodName = node.callee.property.name.toLowerCase();\n if (AXIOS_MUTATION_METHODS.has(methodName)) {\n const urlArg = node.arguments[0];\n // Skip Express-style route definitions like\n // `router.post('/api/x', handler)`: a function argument means this\n // is registering a handler, not issuing a client mutation.\n const hasHandlerArg = node.arguments.some(\n (arg) =>\n arg.type === \"ArrowFunctionExpression\" ||\n arg.type === \"FunctionExpression\",\n );\n if (\n urlArg &&\n urlArg.type !== \"SpreadElement\" &&\n !hasHandlerArg &&\n isApiUrl(urlArg, context)\n ) {\n isMutation = true;\n }\n }\n }\n // 3. Direct axios/request call: axios({ method: 'post', url: '/api/orders' })\n else if (\n node.callee.type === \"Identifier\" &&\n (node.callee.name === \"axios\" || node.callee.name === \"request\")\n ) {\n const firstArg = node.arguments[0];\n if (firstArg && firstArg.type !== \"SpreadElement\") {\n const configArg = resolveNode(firstArg, context);\n if (configArg && configArg.type === \"ObjectExpression\") {\n const urlNode = getPropertyNode(configArg, \"url\");\n const methodNode = getPropertyNode(configArg, \"method\");\n if (\n urlNode &&\n isApiUrl(urlNode, context) &&\n methodNode &&\n isMutationMethod(methodNode, context)\n ) {\n isMutation = true;\n }\n }\n }\n }\n\n if (isMutation) {\n context.report({ node, messageId: \"preferServerAction\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Prefer shadcn/ui form primitives over their native HTML\n * counterparts. Limited to form/dialog elements — `<button>` and `<table>`\n * have been removed from the forbid list because they produced 100% false\n * positives during bulbul validation (icon buttons, layout tables).\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"preferShadcn\";\ntype Options = readonly [];\n\nconst REPLACEMENTS: Readonly<Record<string, string>> = {\n input: \"Input\",\n select: \"Select\",\n textarea: \"Textarea\",\n dialog: \"Dialog\",\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-shadcn\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Prefer shadcn/ui form primitives over native `<input>`, `<select>`, `<textarea>`, and `<dialog>` elements.\",\n },\n schema: [],\n messages: {\n preferShadcn:\n \"Use the shadcn <{{replacement}}> component from @/components/ui/{{lowercase}} instead of native <{{element}}>.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n JSXOpeningElement(node: TSESTree.JSXOpeningElement): void {\n // Only lowercase JSXIdentifier names represent native HTML elements.\n // Member expressions (`Foo.Bar`) and namespaces (`svg:path`) are skipped.\n if (node.name.type !== \"JSXIdentifier\") {\n return;\n }\n\n const elementName = node.name.name;\n const replacement = REPLACEMENTS[elementName];\n\n if (replacement === undefined) {\n return;\n }\n\n context.report({\n node,\n messageId: \"preferShadcn\",\n data: {\n element: elementName,\n replacement,\n lowercase: elementName,\n },\n });\n },\n };\n },\n});\n","import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"missingAssertNever\";\ntype Options = readonly [];\n\n/**\n * Matches a call to `assertNever(...)` — either the bare identifier form\n * (`assertNever(x)`) or a namespaced member form (`utils.assertNever(x)`).\n */\nconst isAssertNeverCall = (expression: TSESTree.Expression): boolean => {\n if (expression.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = expression.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name === \"assertNever\";\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name === \"assertNever\";\n }\n return false;\n};\n\nconst statementContainsAssertNever = (\n statement: TSESTree.Statement,\n): boolean => {\n if (statement.type === AST_NODE_TYPES.ExpressionStatement) {\n return isAssertNeverCall(statement.expression);\n }\n if (statement.type === AST_NODE_TYPES.ThrowStatement) {\n return isAssertNeverCall(statement.argument);\n }\n if (statement.type === AST_NODE_TYPES.ReturnStatement) {\n return (\n statement.argument !== null && isAssertNeverCall(statement.argument)\n );\n }\n // Recurse into block-scoped default bodies like `default: { ... }`\n if (statement.type === AST_NODE_TYPES.BlockStatement) {\n return statement.body.some(statementContainsAssertNever);\n }\n return false;\n};\n\n/**\n * Returns true if the statement performs some runtime work. An empty statement\n * or an empty block does nothing; everything else (`return`, `throw`, `break`,\n * a function call, an `if`, ...) is treated as legitimate runtime handling of\n * the default case.\n */\nconst isRuntimeHandlingStatement = (statement: TSESTree.Statement): boolean => {\n if (statement.type === AST_NODE_TYPES.EmptyStatement) return false;\n if (statement.type === AST_NODE_TYPES.BlockStatement) {\n return statement.body.some(isRuntimeHandlingStatement);\n }\n return true;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"require-assert-never\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require an exhaustive-style switch whose `default` case does no runtime work to call `assertNever(_)` so that discriminated unions are exhaustively checked at compile time. Switches with a legitimate runtime default (a reducer's `return state`, an HTTP-status `return fallback()`, a `break`, a `throw`, etc.) are left alone.\",\n },\n schema: [],\n messages: {\n missingAssertNever:\n \"Empty switch `default` case — add runtime handling or call `assertNever()` so the discriminated union is exhaustively checked at compile time.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n SwitchStatement(node: TSESTree.SwitchStatement): void {\n const defaultCase = node.cases.find(\n (caseNode): caseNode is TSESTree.SwitchCase => caseNode.test === null,\n );\n // No `default` at all is fine — we don't demand exhaustiveness of every\n // switch, only of those that opted into a (no-op) default.\n if (!defaultCase) return;\n\n // An explicit `assertNever(...)` is the canonical exhaustiveness check.\n if (defaultCase.consequent.some(statementContainsAssertNever)) return;\n\n // A default that does real runtime work (return a fallback, break,\n // throw, log, ...) is legitimate — don't demand assertNever there.\n if (defaultCase.consequent.some(isRuntimeHandlingStatement)) return;\n\n // Otherwise the default is empty / a pure no-op: flag it.\n context.report({\n node: defaultCase,\n messageId: \"missingAssertNever\",\n });\n },\n };\n },\n});\n","import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\nimport type { RuleContext, Scope } from \"@typescript-eslint/utils/ts-eslint\";\n\ntype MessageIds = \"missingZodValidation\";\ntype Options = readonly [];\n\ntype Ctx = Readonly<RuleContext<MessageIds, Options>>;\n\n// A receiver name that looks like a Zod schema: ends in `Schema`, or uses the\n// `Z<Capital>` house convention (e.g. `ZUser`), or the bare `z` builder.\nconst ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;\n\n/**\n * Walk down a (possibly chained) receiver expression and decide whether it\n * originates from something that looks like a Zod schema — the bare `z` builder\n * (`z.object({...}).parse(...)`), a `Schema`-suffixed identifier\n * (`userSchema.parse(...)`), or a `Z`-prefixed identifier (`ZUser.parse(...)`).\n * Non-Zod receivers like `JSON` / `Date` are intentionally rejected.\n */\nconst looksLikeZodSchema = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n while (true) {\n if (current.type === AST_NODE_TYPES.Identifier) {\n return current.name === \"z\" || ZOD_SCHEMA_NAME_RE.test(current.name);\n }\n if (current.type === AST_NODE_TYPES.CallExpression) {\n current = current.callee;\n continue;\n }\n if (current.type === AST_NODE_TYPES.MemberExpression) {\n current = current.object;\n continue;\n }\n return false;\n }\n};\n\n/**\n * Matches a Zod validation call: `<ZodSchema>.parse(...)` or\n * `<ZodSchema>.safeParse(...)`. Keys off the *receiver* looking like a Zod\n * schema rather than the method name alone, so `JSON.parse(...)` /\n * `Date.parse(...)` are NOT treated as validation.\n */\nconst isZodParseCall = (node: TSESTree.Node): boolean => {\n if (node.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;\n if (callee.computed) return false;\n if (callee.property.type !== AST_NODE_TYPES.Identifier) return false;\n const method = callee.property.name;\n if (method !== \"parse\" && method !== \"safeParse\") return false;\n return looksLikeZodSchema(callee.object);\n};\n\n/**\n * Matches an (optionally awaited) `<x>.formData()` call — the canonical way a\n * `FormData` object is obtained from a `Request` / `Response`.\n */\nconst isFormDataMethodCall = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n if (current.type === AST_NODE_TYPES.AwaitExpression) {\n current = current.argument;\n }\n if (current.type !== AST_NODE_TYPES.CallExpression) return false;\n const callee = current.callee;\n return (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier &&\n callee.property.name === \"formData\"\n );\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"require-zod-form-validation\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.\",\n },\n schema: [],\n messages: {\n missingZodValidation:\n \"FormData parsing must use Zod schema validation (e.g., Schema.parse() / Schema.safeParse())\",\n },\n },\n defaultOptions: [],\n create(context: Ctx) {\n // A receiver is a FormData source if its name reads like form data, or if\n // it is a binding initialized from a `.formData()` call.\n const isFormSourceIdentifier = (node: TSESTree.Node): boolean => {\n if (node.type !== AST_NODE_TYPES.Identifier) return false;\n if (/formdata/i.test(node.name)) return true;\n\n let scope: Scope.Scope | null = context.sourceCode.getScope(node);\n while (scope !== null) {\n const variable = scope.set.get(node.name);\n if (variable !== undefined && variable.defs.length === 1) {\n const def = variable.defs[0];\n if (\n def !== undefined &&\n def.type === \"Variable\" &&\n def.node.type === AST_NODE_TYPES.VariableDeclarator &&\n def.node.init !== null\n ) {\n return isFormDataMethodCall(def.node.init);\n }\n return false;\n }\n scope = scope.upper;\n }\n return false;\n };\n\n const isFormDataGetCall = (node: TSESTree.CallExpression): boolean => {\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return false;\n if (\n callee.property.type !== AST_NODE_TYPES.Identifier ||\n callee.property.name !== \"get\"\n ) {\n return false;\n }\n return isFormSourceIdentifier(callee.object);\n };\n\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n if (!isFormDataGetCall(node)) return;\n\n // Walk up the parent chain to find a surrounding Zod `.parse(...)` /\n // `.safeParse(...)` call. `.parent` is `null` at the Program root, so we\n // must guard for both null and undefined.\n let parent: TSESTree.Node | null | undefined = node.parent;\n while (parent !== null && parent !== undefined) {\n if (isZodParseCall(parent)) return;\n parent = parent.parent;\n }\n\n context.report({\n node,\n messageId: \"missingZodValidation\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Enforce the `Z`-prefix naming convention for Zod schemas\n * (`ZUser = z.object({...})`).\n *\n * NOTE on audit backing: this is an intentional org-wide convention, not a\n * direct mapping of `readability-and-naming.md` (which governs property-name\n * casing, not schema-variable prefixes). The `Z` prefix lets schemas and their\n * inferred types share a base name (`ZUser` / `type User = z.infer<typeof\n * ZUser>`) without collision. Kept as-is by design.\n */\n\nimport { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"zPrefix\";\ntype Options = readonly [];\n\n/**\n * Walks down a (possibly chained) callee like `z.object().extend().refine()` and\n * returns `true` if the chain originates from a bare `z` identifier — i.e. the\n * outermost MemberExpression on the chain has `z` as its receiver.\n */\nconst calleeChainStartsWithZ = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n\n while (current.type === AST_NODE_TYPES.MemberExpression) {\n const receiver: TSESTree.Node = current.object;\n if (receiver.type === AST_NODE_TYPES.Identifier && receiver.name === \"z\") {\n return true;\n }\n if (receiver.type === AST_NODE_TYPES.CallExpression) {\n current = receiver.callee;\n continue;\n }\n return false;\n }\n\n return false;\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"zod-naming-convention\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Enforce Zod schemas to be named with a Z prefix (e.g. `ZUser = z.object({...})`).\",\n },\n schema: [],\n messages: {\n zPrefix: \"Zod schema names should start with Z\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n VariableDeclarator(node: TSESTree.VariableDeclarator): void {\n const init = node.init;\n if (init === null || init === undefined) return;\n if (init.type !== AST_NODE_TYPES.CallExpression) return;\n\n const callee = init.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) return;\n\n if (!calleeChainStartsWithZ(callee)) return;\n\n if (node.id.type !== AST_NODE_TYPES.Identifier) return;\n const variableName = node.id.name;\n if (variableName.startsWith(\"Z\")) return;\n\n context.report({\n node: node.id,\n messageId: \"zPrefix\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview TS port of Python SARJ028\n * (`no-cors-wildcard-with-credentials`). Flags CORS configuration that reflects\n * ANY origin (`\"*\"`) while ALSO allowing credentials. The browser treats\n * `Access-Control-Allow-Origin: *` together with\n * `Access-Control-Allow-Credentials: true` as a directive to reflect the\n * request's Origin and expose authenticated (cookie/session) responses — which\n * lets any website read them cross-origin. That is a credential-theft surface.\n *\n * Two shapes are detected, and BOTH the wildcard origin and credentials=true\n * must co-occur before the rule fires (a `\"*\"` origin without credentials, or\n * credentials with a specific origin, is safe and is NOT reported):\n *\n * 1. A `cors(...)` / `new Cors(...)` call whose options `ObjectExpression`\n * has `credentials: true` AND an `origin` property whose value subtree\n * contains a `\"*\"` string literal anywhere — the bare `\"*\"`, the `[\"*\"]`\n * array, or a `flag ? origins : \"*\"` conditional branch. Reported at the\n * call.\n *\n * 2. Manual header setting where, within the SAME function (or module) scope,\n * `Access-Control-Allow-Origin` is set to `\"*\"` AND\n * `Access-Control-Allow-Credentials` is set to `\"true\"` — via\n * `res.setHeader(...)`, `headers.set(...)` / `.append(...)` (covers\n * `NextResponse` header objects), or a single object literal\n * `{ \"Access-Control-Allow-Origin\": \"*\", \"Access-Control-Allow-Credentials\": \"true\" }`.\n * Header-name matching is case-insensitive. The object-literal form is\n * reported at the object; the split `setHeader`/`set` form is reported at\n * the wildcard-origin call.\n *\n * References:\n * - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"corsWildcardWithCredentials\";\ntype Options = readonly [];\n\nconst ACAO_HEADER = \"access-control-allow-origin\";\nconst ACAC_HEADER = \"access-control-allow-credentials\";\nconst HEADER_SET_METHODS = new Set([\"setheader\", \"set\", \"append\"]);\n\n/**\n * True only for the boolean literal `true` (not `1`, not a truthy expression).\n */\nfunction isTrueLiteral(node: TSESTree.Node): boolean {\n return node.type === \"Literal\" && node.value === true;\n}\n\n/**\n * True if `node` is a string literal whose value equals `\"true\"`\n * (case-insensitive), or the boolean literal `true`. Header values are strings,\n * but some frameworks coerce a boolean, so both are accepted.\n */\nfunction isCredentialsTrueValue(node: TSESTree.Node): boolean {\n if (node.type === \"Literal\") {\n if (node.value === true) {\n return true;\n }\n if (typeof node.value === \"string\") {\n return node.value.trim().toLowerCase() === \"true\";\n }\n }\n return false;\n}\n\n/**\n * True if `node` is the string literal `\"*\"`.\n */\nfunction isStarLiteral(node: TSESTree.Node): boolean {\n return node.type === \"Literal\" && node.value === \"*\";\n}\n\n/**\n * True if a `\"*\"` string literal appears anywhere in `node`'s subtree. Walking\n * the whole subtree catches `\"*\"`, `[\"*\"]`, and the `flag ? origins : \"*\"`\n * conditional branch. A dynamic `origin: someVar` has no `\"*\"` literal, so it\n * does not fire.\n */\nfunction subtreeContainsStarLiteral(node: TSESTree.Node): boolean {\n if (isStarLiteral(node)) {\n return true;\n }\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") {\n continue;\n }\n const value = (node as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child) && subtreeContainsStarLiteral(child)) {\n return true;\n }\n }\n } else if (isNode(value) && subtreeContainsStarLiteral(value)) {\n return true;\n }\n }\n return false;\n}\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\n/**\n * Returns the (non-computed) string name of a property key, or `undefined`.\n */\nfunction propertyKeyName(prop: TSESTree.Property): string | undefined {\n if (prop.computed) {\n return undefined;\n }\n const key = prop.key;\n if (key.type === \"Identifier\") {\n return key.name;\n }\n if (key.type === \"Literal\" && typeof key.value === \"string\") {\n return key.value;\n }\n return undefined;\n}\n\n/**\n * Extracts the callee's terminal identifier name for a call/new expression\n * (`cors` for `cors(...)` and `app.cors(...)`, `Cors` for `new Cors(...)`).\n */\nfunction calleeName(\n node: TSESTree.CallExpression | TSESTree.NewExpression,\n): string | undefined {\n const callee = node.callee;\n if (callee.type === \"Identifier\") {\n return callee.name;\n }\n if (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.property.type === \"Identifier\"\n ) {\n return callee.property.name;\n }\n return undefined;\n}\n\n/**\n * Detects the `cors({ origin: \"*\", credentials: true })` shape. Returns true\n * when the callee is `cors` / `Cors` and the first ObjectExpression argument\n * has `credentials: true` AND an `origin` whose subtree contains `\"*\"`.\n */\nfunction isCorsWildcardCredentialsCall(\n node: TSESTree.CallExpression | TSESTree.NewExpression,\n): boolean {\n const name = calleeName(node);\n if (name === undefined || name.toLowerCase() !== \"cors\") {\n return false;\n }\n const options = node.arguments.find(\n (arg): arg is TSESTree.ObjectExpression => arg.type === \"ObjectExpression\",\n );\n if (options === undefined) {\n return false;\n }\n let hasCredentials = false;\n let hasWildcardOrigin = false;\n for (const prop of options.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const key = propertyKeyName(prop);\n if (key === \"credentials\" && isTrueLiteral(prop.value)) {\n hasCredentials = true;\n } else if (key === \"origin\" && subtreeContainsStarLiteral(prop.value)) {\n hasWildcardOrigin = true;\n }\n }\n return hasCredentials && hasWildcardOrigin;\n}\n\n/**\n * True if the ObjectExpression is a header map setting BOTH\n * `Access-Control-Allow-Origin: \"*\"` and\n * `Access-Control-Allow-Credentials: \"true\"` (case-insensitive keys).\n */\nfunction isWildcardCredentialsHeaderObject(\n node: TSESTree.ObjectExpression,\n): boolean {\n let wildcardOrigin = false;\n let credentialsTrue = false;\n for (const prop of node.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const key = propertyKeyName(prop);\n if (key === undefined) {\n continue;\n }\n const header = key.toLowerCase();\n if (header === ACAO_HEADER && isStarLiteral(prop.value)) {\n wildcardOrigin = true;\n } else if (header === ACAC_HEADER && isCredentialsTrueValue(prop.value)) {\n credentialsTrue = true;\n }\n }\n return wildcardOrigin && credentialsTrue;\n}\n\ntype HeaderSetKind = \"origin\" | \"credentials\";\n\n/**\n * Classifies a `x.setHeader(name, value)` / `x.set(name, value)` /\n * `x.append(name, value)` call as an ACAO-wildcard set, an ACAC-true set, or\n * neither.\n */\nfunction classifyHeaderSetCall(\n node: TSESTree.CallExpression,\n): HeaderSetKind | undefined {\n const callee = node.callee;\n if (\n callee.type !== \"MemberExpression\" ||\n callee.computed ||\n callee.property.type !== \"Identifier\" ||\n !HEADER_SET_METHODS.has(callee.property.name.toLowerCase())\n ) {\n return undefined;\n }\n const [nameArg, valueArg] = node.arguments;\n if (\n nameArg === undefined ||\n valueArg === undefined ||\n nameArg.type !== \"Literal\" ||\n typeof nameArg.value !== \"string\"\n ) {\n return undefined;\n }\n const header = nameArg.value.toLowerCase();\n if (header === ACAO_HEADER && isStarLiteral(valueArg)) {\n return \"origin\";\n }\n if (header === ACAC_HEADER && isCredentialsTrueValue(valueArg)) {\n return \"credentials\";\n }\n return undefined;\n}\n\n/**\n * Nearest enclosing function node, or `undefined` for module scope. Used to\n * group split `setHeader`/`set` header assignments so a wildcard origin and a\n * credentials=true set only pair up when they live in the same scope.\n */\nfunction enclosingScope(node: TSESTree.Node): TSESTree.Node | undefined {\n let current: TSESTree.Node | undefined = node.parent;\n while (current) {\n if (\n current.type === \"FunctionDeclaration\" ||\n current.type === \"FunctionExpression\" ||\n current.type === \"ArrowFunctionExpression\"\n ) {\n return current;\n }\n current = current.parent;\n }\n return undefined;\n}\n\ninterface ScopeHeaderSets {\n originNodes: TSESTree.CallExpression[];\n credentialsNodes: TSESTree.CallExpression[];\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-cors-wildcard-with-credentials\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n 'Disallow CORS that reflects any Origin (`\"*\"`) while allowing credentials; any site could then read authenticated responses. Enumerate explicit trusted origins instead.',\n },\n schema: [],\n messages: {\n corsWildcardWithCredentials:\n 'CORS reflects any Origin (`\"*\"`) while allowing credentials — any site can read authenticated responses. Enumerate explicit trusted origins instead of using `\"*\"` with credentials.',\n },\n },\n defaultOptions: [],\n create(context) {\n const scopeHeaderSets = new Map<TSESTree.Node | \"module\", ScopeHeaderSets>();\n\n function recordHeaderSet(\n node: TSESTree.CallExpression,\n kind: HeaderSetKind,\n ): void {\n const key = enclosingScope(node) ?? \"module\";\n let entry = scopeHeaderSets.get(key);\n if (entry === undefined) {\n entry = { originNodes: [], credentialsNodes: [] };\n scopeHeaderSets.set(key, entry);\n }\n if (kind === \"origin\") {\n entry.originNodes.push(node);\n } else {\n entry.credentialsNodes.push(node);\n }\n }\n\n return {\n NewExpression(node: TSESTree.NewExpression): void {\n if (isCorsWildcardCredentialsCall(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n }\n },\n CallExpression(node: TSESTree.CallExpression): void {\n if (isCorsWildcardCredentialsCall(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n return;\n }\n const kind = classifyHeaderSetCall(node);\n if (kind !== undefined) {\n recordHeaderSet(node, kind);\n }\n },\n ObjectExpression(node: TSESTree.ObjectExpression): void {\n if (isWildcardCredentialsHeaderObject(node)) {\n context.report({ node, messageId: \"corsWildcardWithCredentials\" });\n }\n },\n \"Program:exit\"(): void {\n for (const { originNodes, credentialsNodes } of scopeHeaderSets.values()) {\n if (originNodes.length > 0 && credentialsNodes.length > 0) {\n for (const node of originNodes) {\n context.report({\n node,\n messageId: \"corsWildcardWithCredentials\",\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `try` blocks whose body contains more than three\n * top-level statements that can throw (TS port of Python's SARJ007).\n *\n * A fat `try` body obscures which statement is actually expected to throw and\n * widens the blast radius of the `catch` handler: unrelated failures get caught\n * (and often swallowed or mis-reported) by a handler written for a different\n * operation. Keep the `try` skinny — isolate the throwing statement(s) and move\n * the non-throwing setup and follow-up work outside.\n *\n * Only top-level statements that can *throw* are counted. What counts, and the\n * guards that keep the count aligned with intent (tuned against ~5.6k real TS\n * files to drive false positives to ~zero):\n *\n * - An `await` always counts — awaiting a promise is the canonical throwing\n * operation in async TS. A statement with an `await` in its same-scope\n * subtree counts.\n * - A synchronous call / `new` whose value is *used* (assigned, returned,\n * branched on, or passed as an argument) counts — e.g. `const x = parse(s)`,\n * `return build(x)`, `if (!validate(x))`.\n * - A bare fire-and-forget call statement with no `await` does NOT count. In\n * idiomatic TS these are side effects — React state setters (`setOpen(false)`),\n * toasts (`toast.error(...)`), `router.refresh()`, logging, optional\n * callbacks (`onSuccess?.()`). They are the post-success UI work that\n * naturally trails the one awaited action; counting them flagged nearly\n * every event handler.\n * - Pure, non-throwing array / string / `Map` / `Object` / `Math` / `JSON`\n * helpers (`.map`, `.filter`, `.push`, `.get`, `.join`, `Object.keys`, ...)\n * do NOT count — they are data plumbing, not the operation being guarded.\n * - Calls inside a nested function / arrow body do not run when the `try`\n * executes, so they are not counted (same-scope walk).\n *\n * Two structural exemptions match the Python rule:\n *\n * - A `finally` clause is a deliberate cleanup contract that couples the body\n * to the handler — exempt.\n * - A `catch` handler guaranteed to re-throw (its body's last statement is a\n * `throw`) makes the wide body uniform error-context wrapping, not an\n * over-broad swallow — exempt.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"fatTryBlock\";\ntype Options = readonly [];\n\nconst MAX_TRY_BODY_STATEMENTS = 3;\n\nconst NESTED_FUNCTION_TYPES = new Set<AST_NODE_TYPES>([\n AST_NODE_TYPES.FunctionDeclaration,\n AST_NODE_TYPES.FunctionExpression,\n AST_NODE_TYPES.ArrowFunctionExpression,\n]);\n\n/** Non-throwing member methods — array / string / Map / Set data plumbing. */\nconst PURE_METHODS = new Set<string>([\n \"map\", \"filter\", \"forEach\", \"reduce\", \"reduceRight\", \"find\", \"findIndex\",\n \"findLast\", \"findLastIndex\", \"some\", \"every\", \"push\", \"pop\", \"shift\",\n \"unshift\", \"slice\", \"splice\", \"concat\", \"flat\", \"flatMap\", \"join\", \"reverse\",\n \"sort\", \"fill\", \"includes\", \"indexOf\", \"lastIndexOf\", \"at\", \"keys\", \"values\",\n \"entries\", \"has\", \"get\", \"set\", \"add\", \"delete\", \"clear\", \"toString\",\n \"toLocaleString\", \"valueOf\", \"charAt\", \"charCodeAt\", \"codePointAt\", \"split\",\n \"padStart\", \"padEnd\", \"repeat\", \"trim\", \"trimStart\", \"trimEnd\", \"toUpperCase\",\n \"toLowerCase\", \"toFixed\", \"toPrecision\", \"startsWith\", \"endsWith\",\n]);\n\n/** Non-throwing global namespaces called as `X.method(...)`. */\nconst PURE_NAMESPACES = new Set<string>([\n \"Object\", \"Array\", \"Math\", \"JSON\", \"Number\", \"String\", \"Boolean\", \"console\",\n]);\n\n/** Constructors that do not throw on construction. */\nconst PURE_CONSTRUCTORS = new Set<string>([\n \"Map\", \"Set\", \"WeakMap\", \"WeakSet\", \"Date\", \"Error\", \"TypeError\",\n \"RangeError\", \"Array\", \"Object\", \"Headers\", \"URLSearchParams\", \"FormData\",\n \"TextEncoder\", \"TextDecoder\", \"Blob\", \"ReadableStream\", \"WritableStream\",\n \"TransformStream\", \"Response\", \"AbortController\",\n]);\n\nfunction isNode(value: unknown): value is TSESTree.Node {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\n/** A call whose value is a known pure, non-throwing helper. */\nfunction isPureCall(node: TSESTree.CallExpression): boolean {\n const callee = node.callee;\n if (callee.type !== AST_NODE_TYPES.MemberExpression) {\n return false;\n }\n const property = callee.property;\n if (property.type !== AST_NODE_TYPES.Identifier) {\n return false;\n }\n if (\n callee.object.type === AST_NODE_TYPES.Identifier &&\n PURE_NAMESPACES.has(callee.object.name)\n ) {\n return true;\n }\n return PURE_METHODS.has(property.name);\n}\n\nfunction isPureNew(node: TSESTree.NewExpression): boolean {\n return (\n node.callee.type === AST_NODE_TYPES.Identifier &&\n PURE_CONSTRUCTORS.has(node.callee.name)\n );\n}\n\n/**\n * Walk `stmt`'s same-scope subtree (not descending into nested function/arrow\n * bodies) until `predicate` matches a node.\n */\nfunction subtreeMatches(\n stmt: TSESTree.Node,\n predicate: (node: TSESTree.Node) => boolean,\n): boolean {\n let found = false;\n\n const visit = (current: TSESTree.Node): void => {\n if (found) {\n return;\n }\n if (predicate(current)) {\n found = true;\n return;\n }\n for (const key of Object.keys(current)) {\n if (key === \"parent\") {\n continue;\n }\n if (NESTED_FUNCTION_TYPES.has(current.type) && key === \"body\") {\n continue;\n }\n const value = (current as unknown as Record<string, unknown>)[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (isNode(child)) {\n visit(child);\n }\n }\n } else if (isNode(value)) {\n visit(value);\n }\n if (found) {\n return;\n }\n }\n };\n\n visit(stmt);\n return found;\n}\n\nconst hasAwait = (stmt: TSESTree.Statement): boolean =>\n subtreeMatches(stmt, (n) => n.type === AST_NODE_TYPES.AwaitExpression);\n\nconst hasThrowingCallOrNew = (stmt: TSESTree.Statement): boolean =>\n subtreeMatches(\n stmt,\n (n) =>\n (n.type === AST_NODE_TYPES.CallExpression && !isPureCall(n)) ||\n (n.type === AST_NODE_TYPES.NewExpression && !isPureNew(n)),\n );\n\n/** Unwrap `await` / optional-chain / non-null wrappers to the core expression. */\nfunction unwrap(expr: TSESTree.Expression): TSESTree.Expression {\n let current = expr;\n while (\n current.type === AST_NODE_TYPES.ChainExpression ||\n current.type === AST_NODE_TYPES.TSNonNullExpression\n ) {\n current = current.expression;\n }\n return current;\n}\n\n/**\n * Whether a top-level try-body statement can plausibly throw when the `try`\n * runs. See the file overview for the guards; the key ones are: `await` always\n * counts, and a bare fire-and-forget call statement (no `await`) does not.\n */\nfunction canThrow(stmt: TSESTree.Statement): boolean {\n if (hasAwait(stmt)) {\n return true;\n }\n if (\n stmt.type === AST_NODE_TYPES.ExpressionStatement &&\n unwrap(stmt.expression).type === AST_NODE_TYPES.CallExpression\n ) {\n return false;\n }\n return hasThrowingCallOrNew(stmt);\n}\n\n/**\n * Conservative: is the `catch` handler guaranteed to re-throw? True when a\n * handler is present and its body's last statement is a `throw`.\n */\nfunction handlerRethrows(handler: TSESTree.CatchClause | null): boolean {\n if (handler === null) {\n return false;\n }\n const body = handler.body.body;\n const last = body[body.length - 1];\n return last !== undefined && last.type === AST_NODE_TYPES.ThrowStatement;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-fat-try-blocks\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow `try` blocks with more than three top-level statements that can throw — isolate the throwing statement and move non-throwing work outside.\",\n },\n schema: [],\n messages: {\n fatTryBlock:\n \"This `try` block has {{count}} statements that can throw (max {{max}}). Isolate the throwing statement(s); move non-throwing work outside the `try`.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const sourceCode = context.sourceCode;\n\n return {\n TryStatement(node: TSESTree.TryStatement): void {\n if (node.finalizer !== null) {\n return;\n }\n if (handlerRethrows(node.handler)) {\n return;\n }\n\n const count = node.block.body.filter(canThrow).length;\n if (count <= MAX_TRY_BODY_STATEMENTS) {\n return;\n }\n\n const tryKeyword = sourceCode.getFirstToken(node);\n context.report({\n node: tryKeyword ?? node,\n messageId: \"fatTryBlock\",\n data: { count, max: MAX_TRY_BODY_STATEMENTS },\n });\n },\n };\n },\n});\n","/**\n * @fileoverview TS port of SARJ012 (`no-secret-in-log`). Passing a secret value\n * (token, password, api key, jwt, credential, signature, ...) to a logging call\n * leaks it into log sinks — files, stdout, log aggregators — where it persists\n * far beyond its intended lifetime and is readable by anyone with log access.\n * Prefer redaction (`tokenPrefix: token.slice(0, 6)`) or omission.\n *\n * We fire on a logging call (`logger.info(...)`, `log.error(...)`, loguru/bind\n * builder chains, etc.) that passes a secret-named value either as a property of\n * an object argument (`logger.error(\"msg\", { token, apiKey })`) or as a bare\n * secret-named positional identifier (`logger.info(\"x\", password)`).\n *\n * The secret-name predicate matches a secret word only as a WHOLE token (after\n * snake_case / camelCase splitting) and disqualifies identifiers whose trailing\n * token is a counter / row-id / flag marker (`tokenCount`, `apiKeyId`,\n * `passwordEnabled`), so metadata *about* a secret is not mistaken for the\n * secret itself. Redaction markers (prefix/mask/hash/redact/tag) are exempt.\n *\n * References:\n * - https://owasp.org/www-community/vulnerabilities/Information_exposure_through_log_files\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSecretInLog\";\ntype Options = readonly [];\n\nconst LOG_METHODS: ReadonlySet<string> = new Set([\n \"debug\",\n \"info\",\n \"warn\",\n \"warning\",\n \"error\",\n \"exception\",\n \"critical\",\n \"trace\",\n \"log\",\n \"fatal\",\n \"success\",\n]);\n\nconst LOGGER_NAMES: ReadonlySet<string> = new Set([\n \"logger\",\n \"log\",\n \"logging\",\n \"loguru\",\n \"console\",\n \"_logger\",\n \"_log\",\n]);\n\nconst LOGGER_FACTORIES: ReadonlySet<string> = new Set([\"getlogger\", \"get_logger\"]);\n\nconst SECRET_WORDS: ReadonlySet<string> = new Set([\n \"token\",\n \"secret\",\n \"password\",\n \"passwd\",\n \"jwt\",\n \"secrets\",\n \"passwords\",\n \"credential\",\n \"credentials\",\n \"authorization\",\n \"signature\",\n \"hmac\",\n \"digest\",\n \"hash\",\n \"apikey\",\n]);\n\nconst INNOCUOUS_WORDS: ReadonlySet<string> = new Set([\n \"count\",\n \"counts\",\n \"budget\",\n \"limit\",\n \"limits\",\n \"id\",\n \"ids\",\n \"enabled\",\n \"disabled\",\n \"flag\",\n \"flags\",\n \"present\",\n \"set\",\n \"unset\",\n \"configured\",\n \"missing\",\n \"required\",\n \"valid\",\n \"invalid\",\n \"exists\",\n \"type\",\n \"types\",\n \"name\",\n \"names\",\n \"label\",\n \"labels\",\n \"title\",\n \"expiry\",\n \"expiration\",\n \"expires\",\n \"ttl\",\n \"version\",\n \"versions\",\n \"policy\",\n \"rotation\",\n \"arn\",\n \"path\",\n \"paths\",\n \"issuer\",\n \"audience\",\n \"strength\",\n \"manager\",\n \"service\",\n \"services\",\n \"repository\",\n \"provider\",\n \"providers\",\n \"store\",\n \"factory\",\n \"handler\",\n \"controller\",\n \"bucket\",\n \"url\",\n \"uri\",\n \"endpoint\",\n \"endpoints\",\n \"scope\",\n \"scopes\",\n \"event\",\n \"events\",\n \"format\",\n \"at\",\n \"len\",\n \"length\",\n]);\n\nconst REDACTION_RE = /prefix|suffix|redact|mask|hash|hint|_len|length/i;\nconst WHOLE_TOKEN_REDACTION_MARKERS: ReadonlySet<string> = new Set([\"tag\"]);\n\nconst CAMEL_RE = /[A-Z]+(?=[A-Z][a-z])|[A-Z]?[a-z]+|[A-Z]+|\\d+/g;\nconst SEGMENT_RE = /[^A-Za-z0-9]+/;\n\n/**\n * Ordered lowercase tokens from snake_case + camelCase decomposition. Also\n * yields each whole snake/kebab segment lowercased, so a pathological mixed-case\n * word still surfaces its intended form.\n */\nfunction tokenize(identifier: string): string[] {\n const tokens: string[] = [];\n for (const segment of identifier.split(SEGMENT_RE)) {\n if (!segment) {\n continue;\n }\n tokens.push(segment.toLowerCase());\n for (const part of segment.match(CAMEL_RE) ?? []) {\n tokens.push(part.toLowerCase());\n }\n }\n return tokens;\n}\n\n/** True if `api` is immediately followed by `key` (the split form of `api_key`). */\nfunction hasApiKey(tokens: readonly string[]): boolean {\n for (let i = 0; i + 1 < tokens.length; i++) {\n if (tokens[i] === \"api\" && tokens[i + 1] === \"key\") {\n return true;\n }\n }\n return false;\n}\n\n/** True if `identifier` names raw secret material (a credential, not metadata). */\nfunction isSecretName(identifier: string): boolean {\n const tokens = tokenize(identifier);\n const last = tokens.at(-1);\n if (last !== undefined && INNOCUOUS_WORDS.has(last)) {\n return false;\n }\n if (tokens.some((tok) => SECRET_WORDS.has(tok))) {\n return true;\n }\n return hasApiKey(tokens);\n}\n\n/** True if the name names a raw secret and is not a redacted derivative. */\nfunction isSecretKeyword(name: string): boolean {\n if (REDACTION_RE.test(name)) {\n return false;\n }\n if (tokenize(name).some((tok) => WHOLE_TOKEN_REDACTION_MARKERS.has(tok))) {\n return false;\n }\n return isSecretName(name);\n}\n\n/**\n * True if `expr` evaluates to a logger. Resolves the whole receiver chain so\n * adapter/builder/factory calls are caught: `logger.bind(...).info(...)`,\n * `logging.getLogger(name).info(...)`, `this.logger.error(...)`.\n */\nfunction isLoggerExpr(expr: TSESTree.Expression | TSESTree.PrivateIdentifier): boolean {\n switch (expr.type) {\n case \"Identifier\":\n return LOGGER_NAMES.has(expr.name.toLowerCase());\n case \"MemberExpression\": {\n const { property, object } = expr;\n if (!expr.computed && property.type === \"Identifier\") {\n const lowered = property.name.toLowerCase();\n if (LOGGER_NAMES.has(lowered) || LOGGER_FACTORIES.has(lowered)) {\n return true;\n }\n }\n return isLoggerExpr(object);\n }\n case \"CallExpression\": {\n const callee = expr.callee;\n if (\n callee.type === \"MemberExpression\" &&\n !callee.computed &&\n callee.property.type === \"Identifier\" &&\n LOGGER_FACTORIES.has(callee.property.name.toLowerCase())\n ) {\n return true;\n }\n if (callee.type !== \"Super\") {\n return isLoggerExpr(callee);\n }\n return false;\n }\n default:\n return false;\n }\n}\n\n/**\n * True if `prop`'s value is the raw secret rather than a redacted/derived form.\n * Shorthand (`{ token }`), a bare identifier (`{ apiKey: theKey }`), or a plain\n * member access (`{ apiKey: config.apiKey }`) all carry the secret verbatim. A\n * call (`token.slice(0, 6)`, `mask(token)`), template literal, ternary, concat,\n * or literal placeholder (`\"***\"`) is already redacted — logging it is safe.\n */\nfunction isRawSecretValue(prop: TSESTree.Property): boolean {\n if (prop.shorthand) {\n return true;\n }\n return prop.value.type === \"Identifier\" || prop.value.type === \"MemberExpression\";\n}\n\n/** The static string name of an object-property key, or null when not statically named. */\nfunction propertyKeyName(prop: TSESTree.Property): string | null {\n if (prop.computed) {\n return null;\n }\n if (prop.key.type === \"Identifier\") {\n return prop.key.name;\n }\n if (prop.key.type === \"Literal\" && typeof prop.key.value === \"string\") {\n return prop.key.value;\n }\n return null;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"no-secret-in-log\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Disallow passing a secret-named value to a logging call; it leaks to log sinks. Redact or omit it.\",\n },\n schema: [],\n messages: {\n noSecretInLog:\n \"Secret `{{name}}` passed to a logging call leaks it to log sinks. Redact (e.g. `{{name}}Prefix: {{name}}.slice(0, 6)`) or omit it.\",\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression): void {\n const callee = node.callee;\n if (\n callee.type !== \"MemberExpression\" ||\n callee.computed ||\n callee.property.type !== \"Identifier\" ||\n !LOG_METHODS.has(callee.property.name)\n ) {\n return;\n }\n if (!isLoggerExpr(callee.object)) {\n return;\n }\n\n for (const arg of node.arguments) {\n if (arg.type === \"Identifier\") {\n if (isSecretKeyword(arg.name)) {\n context.report({\n node: arg,\n messageId: \"noSecretInLog\",\n data: { name: arg.name },\n });\n }\n continue;\n }\n if (arg.type === \"ObjectExpression\") {\n for (const prop of arg.properties) {\n if (prop.type !== \"Property\") {\n continue;\n }\n const keyName = propertyKeyName(prop);\n if (keyName !== null && isSecretKeyword(keyName) && isRawSecretValue(prop)) {\n context.report({\n node: prop,\n messageId: \"noSecretInLog\",\n data: { name: keyName },\n });\n }\n }\n }\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Flag raw `string` used where a closed enumeration is clearly\n * intended, and comparison clusters against a fixed set of string literals.\n * The prescribed replacement is a string-literal union type\n * (`type Status = \"active\" | \"inactive\"`) — NOT a `StrEnum`/`enum`, since the\n * companion `no-enum` rule bans TypeScript enums.\n *\n * This is the TypeScript analog of the Python rule SARJ006 (prefer-str-enum).\n * It fires on two shapes:\n *\n * 1. **Choice-like field** — a `TSPropertySignature` (interface / type literal)\n * or class `PropertyDefinition` whose key's last word is one of the\n * high-precision CHOICE tokens (`status`, `state`, `kind`, `role`,\n * `priority`, `severity`, `direction`, `tier`, `stage`, `type`, `mode`,\n * `level`) and whose type annotation is the bare `string` keyword. Because\n * open-set API DTO fields (`status: string` from an untyped backend) are the\n * dominant false positive, a bare field fires ONLY when CORROBORATED by a\n * sibling string-literal-union member in the SAME interface / class / object\n * type. A file-wide comparison cluster on the field's name is deliberately\n * NOT used to corroborate: it flags unrelated same-named fields (DB-row casts\n * like `as Array<{ status: string }>`, passthrough DTOs). The closed-set fact\n * is still surfaced — as a `comparisonCluster` diagnostic at the comparison\n * site, which is the actionable location.\n *\n * 2. **Comparison cluster** — within one function scope, the same identifier or\n * member expression compared (`===` / `!==` / `==` / `!=`, or a `switch`)\n * against 2+ distinct short lowercase string literals (each matching\n * `^[a-z][a-z0-9_-]{0,30}$`). One diagnostic per cluster. This shape is\n * type-aware: it fires ONLY when the compared operand's resolved type is the\n * general `string` type. An operand already typed as a string-literal union\n * (`CallStatus = \"a\" | \"b\"`, a discriminated-union tag) is the target state\n * and is suppressed — a syntactic rule can't see through a named/imported\n * union, so without type information this shape is inert (the choice-field\n * shape still runs).\n *\n * `Literal`-union types (`type X = \"a\" | \"b\"`) are the target state and never\n * fire. Generated files (`*.gen.ts`, `**\\/generated/**`, `*.d.ts`, or a\n * `@generated` marker) opt out.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n type ParserServicesWithTypeInformation,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\nimport * as ts from \"typescript\";\n\ntype MessageIds = \"bareChoiceField\" | \"comparisonCluster\";\ntype Options = readonly [];\n\nconst CHOICE_TOKENS: ReadonlySet<string> = new Set([\n \"status\",\n \"state\",\n \"kind\",\n \"role\",\n \"priority\",\n \"severity\",\n \"direction\",\n \"tier\",\n \"stage\",\n \"type\",\n \"mode\",\n \"level\",\n]);\n\nconst LOWER_TOKEN_RE = /^[a-z][a-z0-9_-]{0,30}$/;\nconst MIN_CLUSTER_SIZE = 2;\n\nconst BOOLEANISH: ReadonlySet<string> = new Set([\"true\", \"false\"]);\n\n/**\n * An enum-shaped token worth a string-literal union: a short lowercase word of\n * 2+ chars that isn't a boolean-string. Single characters (`'a'`), file\n * paths/URLs/i18n keys (contain `/`, `:`, `.`), and `'true'`/`'false'` are NOT\n * closed-enum members — comparing against them is a flag/path/boolean guard.\n */\nfunction isEnumToken(lit: string): boolean {\n return LOWER_TOKEN_RE.test(lit) && lit.length >= 2 && !BOOLEANISH.has(lit);\n}\n\nconst IGNORE_PATTERNS: readonly RegExp[] = [\n /[\\\\/]generated[\\\\/]/,\n /\\.gen\\.tsx?$/,\n /\\.generated\\.tsx?$/,\n /\\.d\\.ts$/,\n];\n\nfunction isIgnoredFile(filename: string, sourceText: string): boolean {\n if (IGNORE_PATTERNS.some((re) => re.test(filename))) {\n return true;\n }\n return /@generated\\b/.test(sourceText.slice(0, 1024));\n}\n\n/**\n * The trailing word of a camelCase / snake_case identifier, lowercased.\n * `callStatus` -> `status`, `user_role` -> `role`, `estate` -> `estate`.\n */\nfunction lastWord(name: string): string {\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/[_\\s]+/)\n .filter((w) => w.length > 0);\n const last = words[words.length - 1] ?? name;\n return last.toLowerCase();\n}\n\nfunction isChoiceLikeName(name: string): boolean {\n return CHOICE_TOKENS.has(lastWord(name));\n}\n\nfunction keyName(\n key: TSESTree.PropertyDefinition[\"key\"] | TSESTree.PropertyName,\n): string | null {\n if (key.type === AST_NODE_TYPES.Identifier) {\n return key.name;\n }\n if (key.type === AST_NODE_TYPES.Literal && typeof key.value === \"string\") {\n return key.value;\n }\n return null;\n}\n\nfunction isStringLiteralMember(t: TSESTree.TypeNode): boolean {\n return (\n t.type === AST_NODE_TYPES.TSLiteralType &&\n t.literal.type === AST_NODE_TYPES.Literal &&\n typeof t.literal.value === \"string\"\n );\n}\n\n/** Whether a type node is a union of 2+ string-literal types. */\nfunction isStringLiteralUnion(node: TSESTree.TypeNode | undefined): boolean {\n if (node?.type !== AST_NODE_TYPES.TSUnionType) {\n return false;\n }\n return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;\n}\n\n/**\n * Whether a resolved TS type includes the general `string` type — as opposed to\n * being (a union of) string-literal types. `CallStatus = \"a\" | \"b\"` has no\n * general-string member and is already the target state; a raw `string` (or\n * `string | undefined`) does, and a comparison cluster on it should become a\n * union. Requires type information; the comparison-cluster path is inert\n * without it.\n */\nfunction typeHasRawString(type: ts.Type): boolean {\n const parts = type.isUnion() ? type.types : [type];\n return parts.some((t) => (t.flags & ts.TypeFlags.String) !== 0);\n}\n\n/** A stable key for a plain identifier or non-computed member chain, else null. */\nfunction refKey(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Identifier) {\n return node.name;\n }\n if (node.type === AST_NODE_TYPES.MemberExpression && !node.computed) {\n const inner = refKey(node.object);\n if (inner === null || node.property.type !== AST_NODE_TYPES.Identifier) {\n return null;\n }\n return `${inner}.${node.property.name}`;\n }\n return null;\n}\n\nfunction strLiteral(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Literal && typeof node.value === \"string\") {\n return node.value;\n }\n return null;\n}\n\ninterface ClusterEntry {\n node: TSESTree.Node;\n literals: Set<string>;\n allTokens: boolean;\n}\n\ninterface Scope {\n clusters: Map<string, ClusterEntry>;\n}\n\ninterface CollectedProperty {\n name: string;\n container: TSESTree.Node;\n node: TSESTree.Node;\n}\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"prefer-string-literal-union\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Flag raw `string` choice fields and string-literal comparison clusters; prefer a string-literal union type.\",\n },\n schema: [],\n messages: {\n bareChoiceField:\n '`{{name}}: string` looks like a choice field — prefer a string-literal union type (e.g. `type X = \"a\" | \"b\"`). Enums are banned by `no-enum`; use a union.',\n comparisonCluster:\n '`{{key}}` is compared against a closed set of string literals — define a string-literal union type (e.g. `type X = \"a\" | \"b\"`).',\n },\n },\n defaultOptions: [],\n create(context) {\n const filename = context.filename;\n const sourceText = context.sourceCode.getText();\n if (isIgnoredFile(filename, sourceText)) {\n return {};\n }\n\n let services: ParserServicesWithTypeInformation | null;\n try {\n services = ESLintUtils.getParserServices(context);\n } catch {\n services = null;\n }\n\n const scopeStack: Scope[] = [];\n const validClusters: TSESTree.Node[] = [];\n const bareChoiceProps: CollectedProperty[] = [];\n const containersWithUnion = new Set<TSESTree.Node>();\n\n function operandIsRawString(node: TSESTree.Node): boolean {\n if (services === null) {\n return false;\n }\n return typeHasRawString(services.getTypeAtLocation(node));\n }\n\n function pushScope(): void {\n scopeStack.push({ clusters: new Map() });\n }\n\n function popScope(): void {\n const scope = scopeStack.pop();\n if (scope === undefined) {\n return;\n }\n for (const entry of scope.clusters.values()) {\n if (entry.allTokens && entry.literals.size >= MIN_CLUSTER_SIZE) {\n validClusters.push(entry.node);\n }\n }\n }\n\n function accumulate(\n key: string,\n literals: string[],\n node: TSESTree.Node,\n ): void {\n const scope = scopeStack[scopeStack.length - 1];\n if (scope === undefined) {\n return;\n }\n const allTokens = literals.every((lit) => isEnumToken(lit));\n const existing = scope.clusters.get(key);\n if (existing === undefined) {\n scope.clusters.set(key, {\n node,\n literals: new Set(literals),\n allTokens,\n });\n return;\n }\n for (const lit of literals) {\n existing.literals.add(lit);\n }\n existing.allTokens = existing.allTokens && allTokens;\n }\n\n function collectProperty(\n key: TSESTree.PropertyDefinition[\"key\"] | TSESTree.PropertyName,\n typeNode: TSESTree.TypeNode | undefined,\n container: TSESTree.Node,\n node: TSESTree.Node,\n ): void {\n if (isStringLiteralUnion(typeNode)) {\n containersWithUnion.add(container);\n return;\n }\n if (typeNode?.type !== AST_NODE_TYPES.TSStringKeyword) {\n return;\n }\n const name = keyName(key);\n if (name === null || !isChoiceLikeName(name)) {\n return;\n }\n bareChoiceProps.push({ name, container, node });\n }\n\n return {\n FunctionDeclaration: pushScope,\n \"FunctionDeclaration:exit\": popScope,\n FunctionExpression: pushScope,\n \"FunctionExpression:exit\": popScope,\n ArrowFunctionExpression: pushScope,\n \"ArrowFunctionExpression:exit\": popScope,\n\n BinaryExpression(node: TSESTree.BinaryExpression): void {\n if (\n node.operator !== \"===\" &&\n node.operator !== \"!==\" &&\n node.operator !== \"==\" &&\n node.operator !== \"!=\"\n ) {\n return;\n }\n const leftKey = refKey(node.left);\n const rightLit = strLiteral(node.right);\n const rightKey = refKey(node.right);\n const leftLit = strLiteral(node.left);\n if (leftKey !== null && rightLit !== null) {\n if (operandIsRawString(node.left)) {\n accumulate(leftKey, [rightLit], node);\n }\n } else if (rightKey !== null && leftLit !== null) {\n if (operandIsRawString(node.right)) {\n accumulate(rightKey, [leftLit], node);\n }\n }\n },\n\n SwitchStatement(node: TSESTree.SwitchStatement): void {\n const key = refKey(node.discriminant);\n if (key === null || !operandIsRawString(node.discriminant)) {\n return;\n }\n const literals: string[] = [];\n for (const c of node.cases) {\n if (c.test !== null) {\n const lit = strLiteral(c.test);\n if (lit !== null) {\n literals.push(lit);\n }\n }\n }\n if (literals.length > 0) {\n accumulate(key, literals, node);\n }\n },\n\n TSPropertySignature(node: TSESTree.TSPropertySignature): void {\n collectProperty(\n node.key,\n node.typeAnnotation?.typeAnnotation,\n node.parent,\n node,\n );\n },\n\n PropertyDefinition(node: TSESTree.PropertyDefinition): void {\n collectProperty(\n node.key,\n node.typeAnnotation?.typeAnnotation,\n node.parent,\n node,\n );\n },\n\n \"Program:exit\"(): void {\n for (const clusterNode of validClusters) {\n context.report({\n node: clusterNode,\n messageId: \"comparisonCluster\",\n data: { key: refKeyText(clusterNode) },\n });\n }\n for (const prop of bareChoiceProps) {\n if (containersWithUnion.has(prop.container)) {\n context.report({\n node: prop.node,\n messageId: \"bareChoiceField\",\n data: { name: prop.name },\n });\n }\n }\n },\n };\n\n function refKeyText(node: TSESTree.Node): string {\n if (node.type === AST_NODE_TYPES.BinaryExpression) {\n return refKey(node.left) ?? refKey(node.right) ?? \"value\";\n }\n if (node.type === AST_NODE_TYPES.SwitchStatement) {\n return refKey(node.discriminant) ?? \"value\";\n }\n return \"value\";\n }\n },\n});\n","/**\n * @fileoverview Flag a junk-drawer module stem that has a single public export.\n * TS port of Python SARJ022. Fires ONLY when BOTH hold:\n *\n * (a) the file's basename stem is a generic \"junk-drawer\" name that describes\n * no responsibility (`utils`, `helpers`, `types`, `models`, ...), AND\n * (b) the module has exactly one public export, and that export is a named\n * function / class / function-const, so the rename target is unambiguous.\n *\n * When both hold, the sole export's name is the information-rich replacement for\n * the meaningless stem (`utils.ts` exporting `snakeCaseText` -> `snake-case-text.ts`).\n *\n * A junk-drawer stem carries no domain to lose, so replacing it with the export\n * name is strictly an improvement; an informative stem (`pagination.ts`) names a\n * domain broader than its one current export and is deliberately never flagged.\n */\n\nimport { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"renameJunkDrawer\";\ntype Options = readonly [];\n\n// Generic module stems that describe no responsibility. `index` is deliberately\n// excluded: barrel files legitimately re-export many symbols under that name.\nconst JUNK_DRAWER_STEMS = new Set([\n \"util\",\n \"utils\",\n \"helper\",\n \"helpers\",\n \"common\",\n \"constant\",\n \"constants\",\n \"type\",\n \"types\",\n \"model\",\n \"models\",\n \"shared\",\n \"misc\",\n]);\n\n// Exports whose name is an idiomatic ecosystem convention that lives in a\n// junk-drawer bucket by design — flagging them fights the convention and the\n// bucket is expected to grow. `cn` is the shadcn/ui tailwind-merge className\n// helper that scaffolds into `lib/utils.ts`; renaming to `cn.ts` breaks every\n// `import { cn } from \"@/lib/utils\"`.\nconst CONVENTIONAL_BUCKET_EXPORTS = new Set([\"cn\"]);\n\n// Multi-word acronyms whose accepted kebab-case is a single token rather than a\n// letter-by-letter split (`OAuth` -> `oauth`, not `o-auth`).\nconst ACRONYM_OVERRIDES: ReadonlyArray<readonly [RegExp, string]> = [\n [/OAuth/g, \"Oauth\"],\n [/GraphQL/g, \"Graphql\"],\n [/gRPC/g, \"Grpc\"],\n];\n\n// Split on camelCase boundaries while keeping runs of capitals (acronyms)\n// together: `HTTPServer` -> `HTTP` + `Server`, `JWTHandler` -> `JWT` + `Handler`.\nconst CAMEL_BOUNDARY_RE = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;\n\nconst TEST_FILE_RE = /\\.(test|spec)\\.[cm]?[jt]sx?$/i;\nconst SCRIPT_EXT_RE = /\\.[cm]?[jt]sx?$/i;\n\ninterface ExportSummary {\n readonly names: number;\n readonly hasReExport: boolean;\n readonly candidate: { name: string; node: TSESTree.Node } | null;\n}\n\nconst basename = (filename: string): string =>\n filename.split(/[/\\\\]/).pop() ?? filename;\n\nconst stemOf = (base: string): string => base.replace(SCRIPT_EXT_RE, \"\");\n\nconst kebabCase = (name: string): string => {\n let normalized = name;\n for (const [pattern, replacement] of ACRONYM_OVERRIDES) {\n normalized = normalized.replace(pattern, replacement);\n }\n return normalized.replace(CAMEL_BOUNDARY_RE, \"-\").toLowerCase();\n};\n\nconst isFunctionExpression = (node: TSESTree.Expression | null): boolean =>\n node !== null &&\n (node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.FunctionExpression);\n\n// A `const foo = () => {}` is a rename candidate; a value const (`const MAX = 5`)\n// is not — renaming a file after a bare constant loses more than it gains.\nconst functionConstName = (\n decl: TSESTree.VariableDeclaration,\n): string | null => {\n if (decl.declarations.length !== 1) return null;\n const [declarator] = decl.declarations;\n if (declarator === undefined) return null;\n if (declarator.id.type !== AST_NODE_TYPES.Identifier) return null;\n if (!isFunctionExpression(declarator.init)) return null;\n return declarator.id.name;\n};\n\nconst summarizeExports = (body: readonly TSESTree.ProgramStatement[]): ExportSummary => {\n let names = 0;\n let hasReExport = false;\n let candidate: { name: string; node: TSESTree.Node } | null = null;\n\n const addCandidate = (name: string, node: TSESTree.Node): void => {\n names += 1;\n candidate = { name, node };\n };\n\n for (const statement of body) {\n switch (statement.type) {\n case AST_NODE_TYPES.ExportAllDeclaration:\n hasReExport = true;\n break;\n case AST_NODE_TYPES.ExportDefaultDeclaration: {\n names += 1;\n const decl = statement.declaration;\n if (\n decl.type === AST_NODE_TYPES.FunctionDeclaration &&\n decl.id !== null\n ) {\n candidate = { name: decl.id.name, node: statement };\n } else if (\n decl.type === AST_NODE_TYPES.ClassDeclaration &&\n decl.id !== null\n ) {\n candidate = { name: decl.id.name, node: statement };\n }\n break;\n }\n case AST_NODE_TYPES.ExportNamedDeclaration: {\n if (statement.source !== null) {\n hasReExport = true;\n break;\n }\n const decl = statement.declaration;\n if (decl === null) {\n names += statement.specifiers.length;\n break;\n }\n switch (decl.type) {\n case AST_NODE_TYPES.FunctionDeclaration:\n if (decl.id !== null) addCandidate(decl.id.name, statement);\n else names += 1;\n break;\n case AST_NODE_TYPES.ClassDeclaration:\n if (decl.id !== null) addCandidate(decl.id.name, statement);\n else names += 1;\n break;\n case AST_NODE_TYPES.VariableDeclaration: {\n const fnName = functionConstName(decl);\n if (fnName !== null && decl.declarations.length === 1) {\n addCandidate(fnName, statement);\n } else {\n names += decl.declarations.length;\n }\n break;\n }\n default:\n names += 1;\n }\n break;\n }\n default:\n break;\n }\n }\n\n return { names, hasReExport, candidate };\n};\n\nexport default ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`,\n)<Options, MessageIds>({\n name: \"single-public-export\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"A junk-drawer module stem (`utils`, `helpers`, `types`, ...) with a single public function/class/const export should be renamed after that export.\",\n },\n schema: [],\n messages: {\n renameJunkDrawer:\n \"Module stem `{{stem}}` is a generic junk-drawer name; its sole public export is `{{name}}` — rename the file to `{{expected}}.ts` to describe its responsibility.\",\n },\n },\n defaultOptions: [],\n create(context) {\n const base = basename(context.filename);\n\n if (base.endsWith(\".d.ts\")) return {};\n if (TEST_FILE_RE.test(base)) return {};\n\n const stem = stemOf(base);\n if (!JUNK_DRAWER_STEMS.has(stem.toLowerCase())) return {};\n\n return {\n Program(node: TSESTree.Program): void {\n const { names, hasReExport, candidate } = summarizeExports(node.body);\n if (hasReExport) return;\n if (names !== 1 || candidate === null) return;\n if (CONVENTIONAL_BUCKET_EXPORTS.has(candidate.name)) return;\n\n const expected = kebabCase(candidate.name);\n if (stem === expected) return;\n\n context.report({\n node: candidate.node,\n messageId: \"renameJunkDrawer\",\n data: { stem, name: candidate.name, expected },\n });\n },\n };\n },\n});\n","import enforceFileStructure from \"./rules/enforce-file-structure.js\";\nimport noClientSideDataFetching from \"./rules/no-client-side-data-fetching.js\";\nimport noCommentCruft from \"./rules/no-comment-cruft.js\";\nimport noEnum from \"./rules/no-enum.js\";\nimport noInsecureRandomId from \"./rules/no-insecure-random-id.js\";\nimport noJsonStringifyError from \"./rules/no-json-stringify-error.js\";\nimport noLogOnlyCatch from \"./rules/no-log-only-catch.js\";\nimport noRawEnv from \"./rules/no-raw-env.js\";\nimport noSentinelReturnOnCatch from \"./rules/no-sentinel-return-on-catch.js\";\nimport noSequentialAwait from \"./rules/no-sequential-await.js\";\nimport noStringConcatInLoop from \"./rules/no-string-concat-in-loop.js\";\nimport noUnnecessaryUseClient from \"./rules/no-unnecessary-use-client.js\";\nimport preferDiscriminatedUnion from \"./rules/prefer-discriminated-union.js\";\nimport preferSchemaForApiPayload from \"./rules/prefer-schema-for-api-payload.js\";\nimport preferSemanticColors from \"./rules/prefer-semantic-colors.js\";\nimport preferServerActions from \"./rules/prefer-server-actions.js\";\nimport preferShadcn from \"./rules/prefer-shadcn.js\";\nimport requireAssertNever from \"./rules/require-assert-never.js\";\nimport requireZodFormValidation from \"./rules/require-zod-form-validation.js\";\nimport zodNamingConvention from \"./rules/zod-naming-convention.js\";\nimport noCorsWildcardWithCredentials from \"./rules/no-cors-wildcard-with-credentials.js\";\nimport noFatTryBlocks from \"./rules/no-fat-try-blocks.js\";\nimport noSecretInLog from \"./rules/no-secret-in-log.js\";\nimport preferStringLiteralUnion from \"./rules/prefer-string-literal-union.js\";\nimport singlePublicExport from \"./rules/single-public-export.js\";\n\nconst rules = {\n \"enforce-file-structure\": enforceFileStructure,\n \"no-client-side-data-fetching\": noClientSideDataFetching,\n \"no-comment-cruft\": noCommentCruft,\n \"no-enum\": noEnum,\n \"no-insecure-random-id\": noInsecureRandomId,\n \"no-json-stringify-error\": noJsonStringifyError,\n \"no-log-only-catch\": noLogOnlyCatch,\n \"no-raw-env\": noRawEnv,\n \"no-sentinel-return-on-catch\": noSentinelReturnOnCatch,\n \"no-sequential-await\": noSequentialAwait,\n \"no-string-concat-in-loop\": noStringConcatInLoop,\n \"no-unnecessary-use-client\": noUnnecessaryUseClient,\n \"prefer-discriminated-union\": preferDiscriminatedUnion,\n \"prefer-schema-for-api-payload\": preferSchemaForApiPayload,\n \"prefer-semantic-colors\": preferSemanticColors,\n \"prefer-server-actions\": preferServerActions,\n \"prefer-shadcn\": preferShadcn,\n \"require-assert-never\": requireAssertNever,\n \"require-zod-form-validation\": requireZodFormValidation,\n \"zod-naming-convention\": zodNamingConvention,\n \"no-cors-wildcard-with-credentials\": noCorsWildcardWithCredentials,\n \"no-fat-try-blocks\": noFatTryBlocks,\n \"no-secret-in-log\": noSecretInLog,\n \"prefer-string-literal-union\": preferStringLiteralUnion,\n \"single-public-export\": singlePublicExport,\n};\n\nconst plugin = {\n meta: {\n name: \"@sarj/eslint-plugin\",\n version: \"2.3.3\",\n },\n rules,\n configs: {\n recommended: {\n plugins: [\"@sarj\"],\n rules: {\n \"@sarj/zod-naming-convention\": \"warn\",\n \"@sarj/require-assert-never\": \"error\",\n \"@sarj/require-zod-form-validation\": \"error\",\n \"@sarj/enforce-file-structure\": \"warn\",\n \"@sarj/no-client-side-data-fetching\": \"warn\",\n \"@sarj/prefer-server-actions\": \"warn\",\n \"@sarj/no-unnecessary-use-client\": \"warn\",\n \"@sarj/prefer-schema-for-api-payload\": \"warn\",\n // Distilled from sarj-audit skills — warn in recommended, error in strict.\n \"@sarj/no-sequential-await\": \"warn\",\n \"@sarj/no-sentinel-return-on-catch\": \"warn\",\n \"@sarj/no-log-only-catch\": \"warn\",\n \"@sarj/no-insecure-random-id\": \"warn\",\n \"@sarj/no-json-stringify-error\": \"warn\",\n \"@sarj/no-string-concat-in-loop\": \"warn\",\n \"@sarj/prefer-discriminated-union\": \"warn\",\n \"@sarj/no-comment-cruft\": \"warn\",\n // Frontend / styling — distilled from frontend PR-review mining.\n \"@sarj/prefer-semantic-colors\": \"warn\",\n // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.\n \"@sarj/no-fat-try-blocks\": \"warn\",\n \"@sarj/no-cors-wildcard-with-credentials\": \"warn\",\n \"@sarj/no-secret-in-log\": \"warn\",\n \"@sarj/single-public-export\": \"warn\",\n \"@sarj/prefer-string-literal-union\": \"warn\",\n },\n },\n strict: {\n plugins: [\"@sarj\"],\n rules: {\n \"@sarj/zod-naming-convention\": \"error\",\n \"@sarj/require-assert-never\": \"error\",\n \"@sarj/require-zod-form-validation\": \"error\",\n \"@sarj/enforce-file-structure\": \"error\",\n \"@sarj/no-raw-env\": \"error\",\n \"@sarj/prefer-shadcn\": \"error\",\n \"@sarj/no-enum\": \"error\",\n \"@sarj/no-client-side-data-fetching\": \"error\",\n \"@sarj/prefer-server-actions\": \"error\",\n \"@sarj/no-unnecessary-use-client\": \"error\",\n \"@sarj/prefer-schema-for-api-payload\": \"error\",\n // Distilled from sarj-audit skills.\n \"@sarj/no-sequential-await\": \"error\",\n \"@sarj/no-sentinel-return-on-catch\": \"error\",\n \"@sarj/no-log-only-catch\": \"error\",\n \"@sarj/no-insecure-random-id\": \"error\",\n \"@sarj/no-json-stringify-error\": \"error\",\n \"@sarj/no-string-concat-in-loop\": \"error\",\n \"@sarj/prefer-discriminated-union\": \"error\",\n \"@sarj/no-comment-cruft\": \"error\",\n // Frontend / styling — distilled from frontend PR-review mining. Stylistic,\n // no autofix → warn (rollout should prove the FP rate before raising it).\n \"@sarj/prefer-semantic-colors\": \"warn\",\n // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.\n \"@sarj/no-fat-try-blocks\": \"error\",\n \"@sarj/no-cors-wildcard-with-credentials\": \"error\",\n \"@sarj/no-secret-in-log\": \"error\",\n \"@sarj/single-public-export\": \"error\",\n // High-volume/stylistic — warn until rollout proves FP rate.\n \"@sarj/prefer-string-literal-union\": \"warn\",\n },\n },\n },\n};\n\nexport default plugin;\nexport { rules };\n"],"mappings":"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","names":["AST_NODE_TYPES","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","ESLintUtils","DEFAULT_IGNORE_PATTERNS","ESLintUtils","ESLintUtils","AST_NODE_TYPES","ESLintUtils","isNode","ESLintUtils","AST_NODE_TYPES","ESLintUtils","ESLintUtils","AST_NODE_TYPES","AST_NODE_TYPES","ESLintUtils","findVariable","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","ESLintUtils","propName","keyName","ESLintUtils","ESLintUtils","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","ESLintUtils","isNode","ESLintUtils","AST_NODE_TYPES","isNode","unwrap","ESLintUtils","propertyKeyName","keyName","ESLintUtils","AST_NODE_TYPES","ESLintUtils","AST_NODE_TYPES","isFunctionExpression"]}