@sarj/eslint-plugin 2.3.4 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +870 -327
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +796 -247
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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"],"sourcesContent":["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.4\",\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","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\nfunction isExternalSourceFile(sf: ts.SourceFile | undefined): boolean {\n if (sf === undefined) {\n return false;\n }\n return sf.isDeclarationFile || sf.fileName.includes(\"/node_modules/\");\n}\n\nfunction symbolIsExternallyDeclared(sym: ts.Symbol | undefined): boolean {\n return (\n sym?.declarations?.some((d) => isExternalSourceFile(d.getSourceFile())) ??\n false\n );\n}\n\n/**\n * The iterable expression a destructuring binding element draws its value from,\n * e.g. `Object.entries(x)` for `key` in `for (const [key] of Object.entries(x))`\n * or the RHS of `const { a } = rhs`.\n */\nfunction bindingSourceExpression(\n decl: ts.BindingElement,\n): ts.Expression | undefined {\n let node: ts.Node = decl.parent;\n while (\n !ts.isForOfStatement(node) &&\n !(ts.isVariableDeclaration(node) && node.initializer !== undefined)\n ) {\n if (node.parent === undefined) {\n return undefined;\n }\n node = node.parent;\n }\n return ts.isForOfStatement(node) ? node.expression : node.initializer;\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 /**\n * Whether the compared value provably originates from a type we don't own —\n * a property of a `.d.ts` / node_modules type (DOM `getComputedStyle().overflowY`,\n * `Task.status` from another package), the return of such a method\n * (`URLSearchParams.get()`, `str.toLowerCase()`), or a destructuring of one\n * (`Object.entries()` keys). A string-literal union is not an available fix\n * for these, so the cluster shape must not flag them.\n */\n function originIsExternal(node: ts.Node | undefined, depth: number): boolean {\n if (node === undefined || services === null || depth > 6) {\n return false;\n }\n const checker = services.program.getTypeChecker();\n if (\n ts.isParenthesizedExpression(node) ||\n ts.isNonNullExpression(node) ||\n ts.isAsExpression(node)\n ) {\n return originIsExternal(node.expression, depth + 1);\n }\n if (ts.isPropertyAccessExpression(node)) {\n return symbolIsExternallyDeclared(checker.getSymbolAtLocation(node.name));\n }\n if (ts.isCallExpression(node)) {\n return originIsExternal(node.expression, depth + 1);\n }\n if (ts.isIdentifier(node)) {\n const decl = checker.getSymbolAtLocation(node)?.valueDeclaration;\n if (decl === undefined) {\n return false;\n }\n if (ts.isVariableDeclaration(decl) && decl.initializer !== undefined) {\n return originIsExternal(decl.initializer, depth + 1);\n }\n if (ts.isBindingElement(decl)) {\n return originIsExternal(bindingSourceExpression(decl), depth + 1);\n }\n }\n return false;\n }\n\n function operandIsFlaggable(node: TSESTree.Node): boolean {\n return (\n operandIsRawString(node) &&\n !originIsExternal(services?.esTreeNodeToTSNodeMap.get(node), 0)\n );\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 (operandIsFlaggable(node.left)) {\n accumulate(leftKey, [rightLit], node);\n }\n } else if (rightKey !== null && leftLit !== null) {\n if (operandIsFlaggable(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 || !operandIsFlaggable(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"],"mappings":"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","names":["import_utils","import_utils","import_utils","import_utils","import_utils","import_utils","DEFAULT_IGNORE_PATTERNS","import_utils","import_utils","import_utils","isNode","import_utils","import_utils","import_utils","import_utils","findVariable","import_utils","import_utils","propName","keyName","import_utils","import_utils","import_utils","import_utils","import_utils","isNode","import_utils","isNode","unwrap","import_utils","propertyKeyName","keyName","import_utils","import_utils","isFunctionExpression"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../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/_logging.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"],"sourcesContent":["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.4.0\",\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","import { ESLintUtils, type TSESTree, AST_NODE_TYPES } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"importsFirst\" | \"useServerDirective\";\ntype Options = readonly [];\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\ntype StatementKind = \"import\" | \"reexport\" | \"body\";\n\n/**\n * Classify a top-level statement by WHAT it introduces, not by the presence of\n * the `export` keyword.\n *\n * - `import ...` → \"import\"\n * - `export ... from`, `export * from`, → \"reexport\"\n * `export { a, b }` (local names)\n * - everything else, INCLUDING every → \"body\"\n * exported declaration/function\n *\n * Bucketing exported statements as \"body\" is the whole point: an exported\n * `interface`/`type`/`enum`/`class`/value-`const` is a declaration and an\n * exported `function` (or `export default <fn>`) is a function — both live in\n * the same body as their non-exported equivalents. That lets the dominant\n * step-down layout (public API first, private helpers below) pass instead of\n * forcing every `export`-prefixed statement into a terminal \"exports\" section.\n *\n * Re-exports are their own neutral group: a generated `_namespaces` barrel that\n * interleaves `import * as X` / `export { X }` must not be flagged, so\n * re-exports never trigger and are allowed anywhere in the file.\n */\nconst classifyStatement = (\n statement: TSESTree.ProgramStatement,\n): StatementKind => {\n switch (statement.type) {\n case AST_NODE_TYPES.ImportDeclaration:\n return \"import\";\n case AST_NODE_TYPES.ExportAllDeclaration:\n return \"reexport\";\n case AST_NODE_TYPES.ExportNamedDeclaration:\n // `export { a } from './x'` / `export { a, b }` re-export names without\n // declaring anything; only `export <decl>` introduces a body statement.\n return statement.declaration === null ? \"reexport\" : \"body\";\n default:\n return \"body\";\n }\n};\n\nconst isStringDirective = (statement: TSESTree.ProgramStatement): boolean =>\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\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 \"Require `import` statements to come first, then allow step-down ordering (public API first, private helpers below) for the rest of the file. Exported statements are classified by WHAT they export — an exported interface is a declaration, an exported function is a function — so a public exported function followed by a private helper, or an exported interface among declarations, is allowed. Re-exports (`export { … } from`, `export *`, `export { … }`) are a neutral group, so generated namespace barrels pass. 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 importsFirst:\n \"File structure violation: import statements must come before other declarations\",\n useServerDirective:\n \"Server action files must start with 'use server' directive\",\n },\n },\n defaultOptions: [],\n create(context) {\n const isServerAction = SERVER_ACTION_FILE_RE.test(context.filename);\n\n return {\n Program(node: TSESTree.Program): void {\n const body = node.body;\n\n if (isServerAction && !isUseServerDirective(body[0])) {\n context.report({\n node,\n messageId: \"useServerDirective\",\n });\n }\n\n let seenBody = false;\n\n for (const statement of body) {\n if (isStringDirective(statement)) continue;\n\n switch (classifyStatement(statement)) {\n case \"reexport\":\n continue;\n case \"body\":\n seenBody = true;\n continue;\n case \"import\":\n if (seenBody) {\n context.report({\n node: statement,\n messageId: \"importsFirst\",\n });\n }\n continue;\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|<amd|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\n// Placeholders that only appear in grammar productions / desugaring examples,\n// never in real code: `%sent%`, `[opt]`, a standalone `<FunctionBody>`, `…` / `...`.\nconst PSEUDOCODE_RE = /%\\w+%|\\[opt\\]|(?:^|\\s)<[A-Za-z]\\w*>|…|\\.\\.\\./;\n\n// A triple-slash `///` directive keeps its third `/` after ESLint strips the\n// leading `//`, so strip 1–2 leading slashes (not exactly two) for `<reference`.\nfunction stripCommentMarker(line: string): string {\n return line.replace(/^\\s*\\/{1,2}/, \"\").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\nfunction hasPseudocode(text: string): boolean {\n return PSEUDOCODE_RE.test(text);\n}\n\n// A prose lead-in preceding a code-shaped line marks that line as an\n// illustration (`// For example:`, a grammar production `FunctionExpression:`),\n// not commented-out code.\nfunction isProse(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n if (t.endsWith(\":\")) return true;\n if (\n /[.!?]$/.test(t) &&\n /\\s/.test(t) &&\n /[a-z]/.test(t) &&\n !looksLikeCode(t) &&\n t.split(/\\s+/).length >= 3\n ) {\n return true;\n }\n return false;\n}\n\nfunction hasCommentedOutCode(\n texts: readonly string[],\n precedingProse: boolean,\n): boolean {\n for (let i = 0; i < texts.length; i++) {\n const line = texts[i];\n if (line === undefined || !looksLikeCode(line) || hasPseudocode(line)) {\n continue;\n }\n const prev = i > 0 ? texts[i - 1] : undefined;\n if (prev !== undefined ? isProse(prev) : precedingProse) continue;\n return true;\n }\n return false;\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 (let i = 0; i < comments.length; i++) {\n const comment = comments[i];\n if (comment === undefined) continue;\n if (isJsDoc(comment) || !isStandalone(comment)) continue;\n if (LICENSE_RE.test(comment.value)) 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 continue;\n }\n const prev = comments[i - 1];\n const precedingProse =\n prev !== undefined &&\n prev.type === \"Line\" &&\n prev.loc.end.line === comment.loc.start.line - 1 &&\n isProse(stripCommentMarker(prev.value));\n if (hasCommentedOutCode(texts, precedingProse)) {\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 tokens/secrets\n * can lead to collisions and trivially guessable values. Prefer\n * `crypto.randomUUID()` or `crypto.getRandomValues(...)` instead.\n *\n * Precision matters here: the rule runs at `error` in the `strict` config, so a\n * false positive blocks a real PR. Large open-source sweeps (VS Code, NestJS,\n * Next.js) showed the bare `id`/`key`/`session` substring heuristic firing on a\n * flood of NON-security correlation/ephemeral ids — temp-file suffixes, HMR\n * session numbers, dev request/execution/trace ids, in-process RPC handles.\n * None of those are security tokens. So the rule now requires a STRONG security\n * signal, and actively exempts names that read as ephemeral/correlation ids or\n * random values concatenated into a filename/path/DOM id.\n *\n * The rule flags a `Math.random()` call when, and only when:\n * 1. Its enclosing binding/property NAME carries a strong security signal\n * (`token`, `secret`, `apiKey`, `csrf`, `password`, `nonce`, `salt`,\n * `uuid`, `authId`) — even a `sessionToken` counts because of `token`; or\n * 2. Its result is fed into a `.toString(36)` chain (the classic insecure\n * random-id idiom, e.g. `Math.random().toString(36).slice(2)`) AND the\n * value is not an exempt ephemeral/correlation id or path fragment.\n *\n * It does NOT flag when the enclosing name signals a non-security\n * correlation/ephemeral id (`temp`, `tmp`, `cache`, `correlation`, `request`,\n * `req`, `trace`, `execution`, `dev`, `hmr`, `mock`, `test`, `perf`, `marker`),\n * nor when the random value is concatenated into a filename/path/DOM id. A\n * strong security name still wins over these exemptions.\n *\n * Bare `Math.random()` used for non-identifier purposes (jitter, sampling,\n * rolls, etc.) is NOT flagged, and neither is the bare `id`/`key`/`session`\n * substring on its own — we err toward suppressing ambiguous correlation ids.\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 2 does not fire. Such code is only caught if its binding/property\n * name looks security-like (trigger 1). See the documented test case.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"insecureRandomId\";\ntype Options = readonly [];\n\nconst STRONG_SECURITY_PATTERN =\n /token|secret|csrf|password|passwd|apikey|api[-_]?key|nonce|salt|uuid|authid/i;\n\nconst NON_SECURITY_ID_PATTERN =\n /temp|tmp|cache|correlation|request|req|trace|execution|dev|hmr|mock|test|perf|marker/i;\n\n/** Matches a static string fragment that reads as a path or DOM-id context. */\nconst PATH_OR_DOM_MARKER = /[\\\\/#]|\\.[A-Za-z0-9]/;\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 * Climbs the member/call chain in which `node` is the object/callee end, and\n * returns the outermost value node of that chain. For\n * `Math.random().toString(36).slice(2)` this returns the `.slice(2)` call —\n * i.e. the value that actually gets assigned/concatenated.\n */\nfunction climbValueChain(node: TSESTree.Node): TSESTree.Node {\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 ) {\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 current;\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 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 (firstArg && firstArg.type === \"Literal\" && firstArg.value === 36) {\n return true;\n }\n }\n }\n\n if (parent.type === \"MemberExpression\" && parent.object === current) {\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. Passes through string concatenation and template literals so\n * that `const tempPath = base + Math.random()...` resolves to `tempPath`.\n * Returns `undefined` if no such name is found before leaving the enclosing\n * 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 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 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 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 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\n/**\n * Collects the static string fragments of a `+` concatenation / template\n * literal subtree into `out`.\n */\nfunction collectStaticStringParts(\n node: TSESTree.Node,\n out: string[],\n): void {\n if (node.type === \"Literal\" && typeof node.value === \"string\") {\n out.push(node.value);\n return;\n }\n if (node.type === \"TemplateLiteral\") {\n for (const quasi of node.quasis) {\n out.push(quasi.value.cooked ?? quasi.value.raw);\n }\n return;\n }\n if (node.type === \"BinaryExpression\" && node.operator === \"+\") {\n collectStaticStringParts(node.left, out);\n collectStaticStringParts(node.right, out);\n }\n}\n\n/**\n * Returns true if the random value is concatenated into a string whose static\n * parts read as a filename/path/DOM id (contain a slash, backslash, `#`, or a\n * `.ext`-style fragment).\n */\nfunction isConcatenatedIntoPathOrDomId(node: TSESTree.Node): boolean {\n const valueNode = climbValueChain(node);\n\n let current: TSESTree.Node = valueNode;\n let parent = current.parent;\n let top: TSESTree.Node | undefined;\n\n while (parent) {\n if (\n parent.type === \"BinaryExpression\" &&\n parent.operator === \"+\" &&\n (parent.left === current || parent.right === current)\n ) {\n top = parent;\n current = parent;\n parent = current.parent;\n continue;\n }\n if (parent.type === \"TemplateLiteral\") {\n top = parent;\n current = parent;\n parent = current.parent;\n continue;\n }\n break;\n }\n\n if (!top) {\n return false;\n }\n\n const parts: string[] = [];\n collectStaticStringParts(top, parts);\n return parts.some((part) => PATH_OR_DOM_MARKER.test(part));\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 const name = findEnclosingName(node);\n\n // A strong security name always fires — even a `sessionToken` or a name\n // that also happens to contain a correlation-id word.\n if (name !== undefined && STRONG_SECURITY_PATTERN.test(name)) {\n context.report({ node, messageId: \"insecureRandomId\" });\n return;\n }\n\n // Ephemeral / correlation ids (temp files, HMR sessions, dev request\n // ids, ...) are not security-sensitive — suppress, including the\n // `.toString(36)` idiom used to shape them.\n if (name !== undefined && NON_SECURITY_ID_PATTERN.test(name)) {\n return;\n }\n\n // A random value concatenated into a filename/path/DOM id is not a\n // security token.\n if (isConcatenatedIntoPathOrDomId(node)) {\n return;\n }\n\n // The classic insecure random-id idiom.\n if (isPartOfToString36Chain(node)) {\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)` when the first argument is either:\n * 1. an Identifier that is the binding of an enclosing `catch (x)` clause, or\n * matches the conventional error-name pattern /^(e|err|error|ex|exc)$/i, OR\n * 2. a member expression denoting an error value (`err.cause`, `this.lastError`) —\n * an error-suggesting property name, or an error-named base whose property is\n * not a plain string accessor (`.message` / `.stack` / `.name`).\n *\n * It suppresses the report inside the non-error branch of an `x instanceof Error`\n * guard (`x instanceof Error ? x : JSON.stringify(x)`), where stringifying the\n * non-Error fallback is exactly correct.\n *\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, SourceCode } 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/** Property names whose value is itself an error object (unsafe to stringify). */\nconst ERROR_PROP_PATTERN = /^(cause|lastError|error|err|exception|originalError|innerError)$/i;\n\n/** Property names whose value is a plain string — the recommended escape hatch. */\nconst SAFE_STRING_PROPS: ReadonlySet<string> = new Set([\"message\", \"stack\", \"name\"]);\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\n/**\n * True if a member-expression argument (`err.cause`, `this.lastError`) denotes an\n * Error value: an error-suggesting property name, or an error-suggesting base whose\n * property is not a known string accessor (`.message` / `.stack` / `.name`).\n */\nfunction memberSuggestsError(\n member: TSESTree.MemberExpression,\n scope: Scope.Scope,\n): boolean {\n const propName =\n !member.computed && member.property.type === \"Identifier\" ? member.property.name : null;\n\n if (propName !== null && ERROR_PROP_PATTERN.test(propName)) {\n return true;\n }\n\n const base = member.object;\n const baseSuggestsError =\n base.type === \"Identifier\" &&\n (ERROR_NAME_PATTERN.test(base.name) || isCatchBinding(scope, base.name));\n if (baseSuggestsError) {\n return propName === null || !SAFE_STRING_PROPS.has(propName.toLowerCase());\n }\n\n return false;\n}\n\n/** The subject `x` of an `x instanceof Error` test, or null. */\nfunction instanceofErrorSubject(\n test: TSESTree.Expression,\n): TSESTree.Expression | null {\n if (\n test.type === \"BinaryExpression\" &&\n test.operator === \"instanceof\" &&\n test.right.type === \"Identifier\" &&\n test.right.name === \"Error\"\n ) {\n return test.left;\n }\n return null;\n}\n\n/** The subject `x` of a negated `!(x instanceof Error)` test, or null. */\nfunction negatedInstanceofErrorSubject(\n test: TSESTree.Expression,\n): TSESTree.Expression | null {\n if (test.type === \"UnaryExpression\" && test.operator === \"!\") {\n return instanceofErrorSubject(test.argument);\n }\n return null;\n}\n\nfunction nodeWithin(node: TSESTree.Node, container: TSESTree.Node | null): boolean {\n return (\n container !== null &&\n node.range[0] >= container.range[0] &&\n node.range[1] <= container.range[1]\n );\n}\n\n/**\n * True if `node` sits in the NON-error branch of an `argExpr instanceof Error`\n * guard — the branch where `argExpr` is provably not an Error, so stringifying it\n * is the correct fallback. Handles both the ternary and `if`/`else` shapes,\n * including the negated `!(x instanceof Error)` form.\n */\nfunction isGuardedByInstanceofError(\n node: TSESTree.Node,\n argExpr: TSESTree.Expression,\n sourceCode: Readonly<SourceCode>,\n): boolean {\n const argText = sourceCode.getText(argExpr);\n const sameSubject = (subject: TSESTree.Expression): boolean =>\n sourceCode.getText(subject) === argText;\n\n let current: TSESTree.Node | undefined = node.parent;\n while (current) {\n if (current.type === \"ConditionalExpression\") {\n const subject = instanceofErrorSubject(current.test);\n if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {\n return true;\n }\n const negated = negatedInstanceofErrorSubject(current.test);\n if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {\n return true;\n }\n } else if (current.type === \"IfStatement\") {\n const subject = instanceofErrorSubject(current.test);\n if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {\n return true;\n }\n const negated = negatedInstanceofErrorSubject(current.test);\n if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {\n return true;\n }\n }\n current = current.parent;\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) {\n return;\n }\n\n const scope = context.sourceCode.getScope(firstArg);\n\n let suggestsError: boolean;\n if (firstArg.type === \"Identifier\") {\n suggestsError =\n ERROR_NAME_PATTERN.test(firstArg.name) || isCatchBinding(scope, firstArg.name);\n } else if (firstArg.type === \"MemberExpression\") {\n suggestsError = memberSuggestsError(firstArg, scope);\n } else {\n return;\n }\n\n if (!suggestsError) {\n return;\n }\n\n if (isGuardedByInstanceofError(node, firstArg, context.sourceCode)) {\n return;\n }\n\n context.report({\n node,\n messageId: \"noJsonStringifyError\",\n });\n },\n };\n },\n});\n","/**\n * @fileoverview Disallow `catch` clauses that only log (via `console.*` or a\n * logger receiver such as `logger.warn(...)` / `Log.error(...)`) and then\n * swallow the error. A catch that logs and falls through — with no `throw`, no\n * `return`, and no real recovery — hides failures: the program keeps running in\n * a broken state while the only signal is a log line that is easy to miss.\n * Either rethrow the error or handle it for real.\n *\n * This rule is deliberately conservative and fires in exactly two shapes:\n * - `noLogOnlyCatch`: the catch body is non-empty and *every* statement is a\n * logging call (`console.*` or a call on a logger-named receiver). Any other\n * statement (a `throw`, a `return`, a fallback assignment, a non-logging\n * call, etc.) means the catch is doing something and is left alone.\n * - `emptyCatch`: the catch body is genuinely empty AND carries no comment.\n * A comment-only catch (`catch { /* ignore, safe because … *\\/ }`) is treated\n * as an intentional, documented ignore and is exempt.\n *\n * A previous version fired the \"logging then swallowing\" message on empty and\n * comment-only catches that contained no logging call at all — the vast majority\n * of real-world hits — which was factually wrong. The two distinct message ids\n * keep each diagnostic accurate.\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\nimport { isLoggingCall } from \"./_logging.js\";\n\ntype MessageIds = \"noLogOnlyCatch\" | \"emptyCatch\";\ntype Options = readonly [];\n\nconst DEFAULT_IGNORE_PATTERNS: readonly RegExp[] = [\n /\\.test\\./,\n /\\.spec\\./,\n /[\\\\/]__tests__[\\\\/]/,\n];\n\n/** True when a statement is exactly a bare logging call, e.g. `console.error(err);` or `logger.warn(err);`. */\nfunction isLoggingCallStatement(statement: TSESTree.Statement): boolean {\n if (statement.type !== \"ExpressionStatement\") {\n return false;\n }\n return isLoggingCall(statement.expression);\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 silently 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 emptyCatch:\n \"Empty catch silently swallows the error. Rethrow it, handle it, or add a comment explaining why it is safe to ignore.\",\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 if (statements.length === 0) {\n // A comment inside the block documents an intentional ignore; only a\n // truly empty catch is an unexplained silent swallow.\n if (context.sourceCode.getCommentsInside(node.body).length > 0) {\n return;\n }\n context.report({ node, messageId: \"emptyCatch\" });\n return;\n }\n\n const everyStatementIsLogging = statements.every((statement) =>\n isLoggingCallStatement(statement),\n );\n\n if (everyStatementIsLogging) {\n context.report({ node, messageId: \"noLogOnlyCatch\" });\n }\n },\n };\n },\n});\n","/**\n * @fileoverview Shared helpers for recognising logging / error-reporting calls.\n * Used by `no-log-only-catch` and `no-sentinel-return-on-catch` so both rules\n * agree on what counts as \"the error was logged/reported\" before deciding a\n * catch silently swallows it. The logger-name and log-method sets mirror\n * `no-secret-in-log.ts`.\n */\n\nimport { type TSESTree } from \"@typescript-eslint/utils\";\n\nexport const 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\nexport const LOGGER_NAMES: ReadonlySet<string> = new Set([\n \"logger\",\n \"log\",\n \"logging\",\n \"loguru\",\n \"console\",\n \"_logger\",\n \"_log\",\n]);\n\n/**\n * Names of free functions / methods that report an error to a handler or sink,\n * e.g. `onUnexpectedError`, `reportError`, `captureException`, `logError`. Kept\n * broad on purpose: pairing this with \"takes the caught binding\" is what makes\n * it precise.\n */\nexport const REPORT_NAME_RE = /error|report|capture|log|trace|warn/i;\n\n/**\n * True when `expr` resolves to a logger receiver — a bare logger identifier\n * (`logger`, `log`, `console`, `Log`) or a member chain ending in one\n * (`this.logger`, `svc.log`).\n */\nexport function isLoggerReceiver(\n expr: TSESTree.Expression | TSESTree.PrivateIdentifier,\n): 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 (\n !expr.computed &&\n property.type === \"Identifier\" &&\n LOGGER_NAMES.has(property.name.toLowerCase())\n ) {\n return true;\n }\n return isLoggerReceiver(object);\n }\n default:\n return false;\n }\n}\n\n/**\n * True when `expr` is a logging call: `console.error(...)`, `logger.warn(...)`,\n * `Log.error(...)`, `this.logger.info(...)`, etc. Requires a non-computed log\n * method on a logger receiver.\n */\nexport function isLoggingCall(expr: TSESTree.Expression): boolean {\n if (expr.type !== \"CallExpression\") {\n return false;\n }\n const callee = expr.callee;\n if (\n callee.type !== \"MemberExpression\" ||\n callee.computed ||\n callee.property.type !== \"Identifier\"\n ) {\n return false;\n }\n if (!LOG_METHODS.has(callee.property.name.toLowerCase())) {\n return false;\n }\n return isLoggerReceiver(callee.object);\n}\n\n/** The static callee name of a call (free function or method), or null. */\nexport function calleeName(callee: TSESTree.Node): string | null {\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 null;\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\n/** True for the `process.env` member node (dotted or as the base of `process.env[key]`). */\nfunction isProcessEnv(node: TSESTree.MemberExpression): boolean {\n return (\n !node.computed &&\n node.object.type === \"Identifier\" &&\n node.object.name === \"process\" &&\n node.property.type === \"Identifier\" &&\n node.property.name === \"env\"\n );\n}\n\n/** True for the `import.meta.env` member node (dotted or as the base of `import.meta.env[key]`). */\nfunction isImportMetaEnv(node: TSESTree.MemberExpression): boolean {\n return (\n !node.computed &&\n node.property.type === \"Identifier\" &&\n node.property.name === \"env\" &&\n node.object.type === \"MetaProperty\" &&\n node.object.meta.name === \"import\" &&\n node.object.property.name === \"meta\"\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-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 (isProcessEnv(node) || isImportMetaEnv(node)) {\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 * - catches that LOG or REPORT the caught error before the sentinel return —\n * a `console.*`/logger call, or an error-reporting call that takes the\n * caught binding (`onUnexpectedError(err)`). Here the sentinel is a\n * deliberate degraded return, not a silent swallow.\n * - the typed-optional / safe-parse / predicate shape: the try body returns a\n * parse-style call that throws on bad input (`JSON.parse(x)`, `new RegExp`),\n * or the enclosing function returns the same sentinel kind on a normal path\n * (a boolean predicate, a `T | undefined` accessor). Here the sentinel is\n * the declared contract.\n */\n\nimport {\n ESLintUtils,\n type TSESTree,\n AST_NODE_TYPES,\n} from \"@typescript-eslint/utils\";\n\nimport {\n isLoggingCall,\n calleeName,\n REPORT_NAME_RE,\n} from \"./_logging.js\";\n\ntype MessageIds = \"noSentinelReturn\";\ntype Options = readonly [];\n\ntype SentinelKind = \"nullish\" | \"boolean\" | \"array\" | \"object\" | \"string\";\n\n/** The sentinel \"kind\" of a returned expression, or null if not a sentinel. */\nfunction sentinelKind(arg: TSESTree.Expression | null): SentinelKind | null {\n if (arg === null) {\n return null;\n }\n if (arg.type === AST_NODE_TYPES.Literal) {\n if (arg.value === null) {\n return \"nullish\";\n }\n if (typeof arg.value === \"boolean\") {\n return \"boolean\";\n }\n if (typeof arg.value === \"string\") {\n return \"string\";\n }\n return null;\n }\n if (arg.type === AST_NODE_TYPES.Identifier && arg.name === \"undefined\") {\n return \"nullish\";\n }\n if (arg.type === AST_NODE_TYPES.ArrayExpression) {\n return \"array\";\n }\n if (arg.type === AST_NODE_TYPES.ObjectExpression) {\n return \"object\";\n }\n return null;\n}\n\n/** Whether a returned expression is one of the swallowing sentinels we flag. */\nfunction isSentinelArgument(arg: TSESTree.Expression | null): boolean {\n if (arg === null) {\n return false;\n }\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === null) {\n return true;\n }\n if (arg.type === AST_NODE_TYPES.Literal && arg.value === false) {\n return true;\n }\n if (arg.type === AST_NODE_TYPES.Identifier && arg.name === \"undefined\") {\n return true;\n }\n if (arg.type === AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {\n return true;\n }\n if (\n arg.type === AST_NODE_TYPES.ObjectExpression &&\n arg.properties.length === 0\n ) {\n return true;\n }\n return false;\n}\n\nfunction isFunctionNode(node: TSESTree.Node): boolean {\n return (\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression\n );\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 * Walk `node`'s subtree applying `visit`, but do not descend into nested\n * function scopes — their statements don't run synchronously for the current\n * catch. Stops early once `visit` returns true.\n */\nfunction walkWithinScope(\n node: TSESTree.Node,\n visit: (current: TSESTree.Node) => boolean,\n): boolean {\n let found = false;\n\n const recurse = (current: TSESTree.Node): void => {\n if (found) {\n return;\n }\n if (visit(current)) {\n found = true;\n return;\n }\n if (isFunctionNode(current)) {\n return;\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 recurse(child);\n }\n }\n } else if (isNode(value)) {\n recurse(value);\n }\n }\n };\n\n recurse(node);\n return found;\n}\n\n/** Does this subtree throw (ignoring nested function scopes)? */\nfunction containsThrow(node: TSESTree.Node): boolean {\n return walkWithinScope(\n node,\n (current) => current.type === AST_NODE_TYPES.ThrowStatement,\n );\n}\n\n/** Are any of a call's arguments exactly the caught-error binding identifier? */\nfunction argsIncludeBinding(\n args: readonly TSESTree.CallExpressionArgument[],\n caughtName: string | null,\n): boolean {\n if (caughtName === null) {\n return false;\n }\n return args.some(\n (arg) => arg.type === AST_NODE_TYPES.Identifier && arg.name === caughtName,\n );\n}\n\n/**\n * Does the catch body log or report the caught error before the sentinel\n * return? Either a logging call (`console.*` / logger receiver), or an\n * error-reporting call whose name matches `REPORT_NAME_RE` and that takes the\n * caught binding (`onUnexpectedError(err)`).\n */\nfunction logsOrReportsError(\n catchBody: TSESTree.BlockStatement,\n caughtName: string | null,\n): boolean {\n return walkWithinScope(catchBody, (current) => {\n if (current.type !== AST_NODE_TYPES.CallExpression) {\n return false;\n }\n if (isLoggingCall(current)) {\n return true;\n }\n const name = calleeName(current.callee);\n return (\n name !== null &&\n REPORT_NAME_RE.test(name) &&\n argsIncludeBinding(current.arguments, caughtName)\n );\n });\n}\n\n/** The try block guarded by this catch. */\nfunction tryBlockOf(catchNode: TSESTree.CatchClause): TSESTree.BlockStatement {\n return catchNode.parent.block;\n}\n\n/**\n * True when a return argument is a parse-style call that throws on bad input,\n * so returning a sentinel on failure is the declared \"safe-parse\" contract:\n * `JSON.parse(x)`, `YAML.parse(x)`, `new RegExp(x)`, `new URL(x)`.\n */\nfunction isSafeParseExpression(arg: TSESTree.Expression | null): boolean {\n if (arg === null) {\n return false;\n }\n if (\n arg.type === AST_NODE_TYPES.CallExpression &&\n arg.callee.type === AST_NODE_TYPES.MemberExpression &&\n !arg.callee.computed &&\n arg.callee.property.type === AST_NODE_TYPES.Identifier &&\n arg.callee.property.name === \"parse\"\n ) {\n return true;\n }\n if (\n arg.type === AST_NODE_TYPES.NewExpression &&\n arg.callee.type === AST_NODE_TYPES.Identifier\n ) {\n return arg.callee.name === \"RegExp\" || arg.callee.name === \"URL\";\n }\n return false;\n}\n\n/** Does the try body return a safe-parse-style expression? */\nfunction tryReturnsSafeParse(catchNode: TSESTree.CatchClause): boolean {\n return walkWithinScope(\n tryBlockOf(catchNode),\n (current) =>\n current.type === AST_NODE_TYPES.ReturnStatement &&\n isSafeParseExpression(current.argument),\n );\n}\n\n/** The nearest enclosing function body, or null. */\nfunction enclosingFunctionBody(\n node: TSESTree.Node,\n): TSESTree.BlockStatement | null {\n let current: TSESTree.Node | undefined | null = node.parent;\n while (current !== undefined && current !== null) {\n if (\n isFunctionNode(current) &&\n \"body\" in current &&\n isNode(current.body) &&\n current.body.type === AST_NODE_TYPES.BlockStatement\n ) {\n return current.body;\n }\n current = current.parent;\n }\n return null;\n}\n\n/**\n * True when the enclosing function returns the same sentinel kind on a normal\n * (non-catch) path — a boolean predicate, a `T | undefined` accessor, etc. —\n * so the catch sentinel is the declared contract, not a swallow. Returns inside\n * the flagged catch itself are excluded.\n */\nfunction functionReturnsSameSentinelKindElsewhere(\n catchNode: TSESTree.CatchClause,\n kind: SentinelKind,\n): boolean {\n const functionBody = enclosingFunctionBody(catchNode);\n if (functionBody === null) {\n return false;\n }\n return walkWithinScope(functionBody, (current) => {\n if (current.type !== AST_NODE_TYPES.ReturnStatement) {\n return false;\n }\n if (isWithin(current, catchNode.body)) {\n return false;\n }\n return sentinelKind(current.argument) === kind;\n });\n}\n\n/** Is `node` inside `ancestor`'s subtree? */\nfunction isWithin(node: TSESTree.Node, ancestor: TSESTree.Node): boolean {\n let current: TSESTree.Node | undefined | null = node;\n while (current !== undefined && current !== null) {\n if (current === ancestor) {\n return true;\n }\n current = current.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-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, unless the error is logged/reported or the sentinel is the declared safe-parse/predicate contract.\",\n },\n schema: [],\n messages: {\n noSentinelReturn:\n \"This `catch` block swallows the error by returning an empty sentinel without logging it. Rethrow it, log/report it, or return a typed Result.\",\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 if (containsThrow(node.body)) {\n return;\n }\n\n const caughtName =\n node.param?.type === AST_NODE_TYPES.Identifier\n ? node.param.name\n : null;\n\n if (logsOrReportsError(node.body, caughtName)) {\n return;\n }\n\n if (tryReturnsSafeParse(node)) {\n return;\n }\n\n const kind = sentinelKind(last.argument);\n if (\n kind !== null &&\n functionReturnsSameSentinelKindElsewhere(node, kind)\n ) {\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 (or an async `.forEach` /\n * `.map` / `.filter` callback) within the same function scope. Awaiting serially\n * inside a loop serializes I/O that is often better expressed as\n * `await Promise.all(xs.map(async (x) => ...))`, letting the operations run\n * 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 *\n * Real-world sweeps (VS Code, NestJS, Next.js) surfaced whole classes of loops\n * where serial awaits are REQUIRED and `Promise.all` would change semantics.\n * Those are suppressed here:\n * (a) the loop short-circuits or retries — its body (this scope) contains a\n * `return` / `break` / `continue`;\n * (b) the awaited value threads through the iteration — `x = await f(x)`,\n * `content = await p(content)` (the assignment target is read inside the\n * awaited expression);\n * (c) the await is a timer yield — `await new Promise((r) => setTimeout(r))`;\n * (d) the iterable's name/derivation signals ordering — `*Sorted*`,\n * `.reverse()`, lifecycle `hooks`, pipeline `stages`, etc.\n * The genuinely parallelizable shape — independent awaits whose results are\n * collected or discarded without a cross-iteration dependency or early exit —\n * still fires.\n *\n * At most one report is emitted per offending loop / callback.\n */\n\nimport { ESLintUtils, type TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noSequentialAwait\";\ntype Options = readonly [];\n\n/**\n * Array iteration methods whose async callback with an `await` inside is the\n * classic serial-await footgun (`.forEach` ignores the returned promise\n * entirely; a discarded `.map` / `.filter` floats its promises).\n */\nconst ARRAY_ITERATION_METHODS = new Set<string>([\"forEach\", \"map\", \"filter\"]);\n\n/**\n * Text on the iterable (its identifier name or derivation) that signals an\n * ORDERED sequence whose elements must be processed one-after-another —\n * lifecycle hooks, sorted / reversed lists, pipeline stages. Awaiting serially\n * over such a sequence is the contract, so the report is suppressed. Broad by\n * design: the rule prefers a false negative to a false positive.\n */\nconst SEQUENTIAL_ITERABLE_HINT =\n /sort|reverse|ordered|sequence|hook|middleware|pipeline|\\bstage|\\bstep|\\bphase|migration|chain/i;\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\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\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 * Visits `root` and its descendants, calling `visit` on each, without crossing\n * into a nested function scope or descending into a nested loop — the same\n * ownership boundaries the rule uses to decide which awaits belong to a loop.\n */\nfunction visitScope(\n root: TSESTree.Node,\n visit: (node: TSESTree.Node) => void,\n): void {\n visit(root);\n for (const key of Object.keys(root) as (keyof TSESTree.Node)[]) {\n if (key === \"parent\") {\n continue;\n }\n const value = root[key];\n const children = Array.isArray(value) ? value : [value];\n for (const child of children) {\n if (isNode(child) && !isFunctionLike(child) && !isLoop(child)) {\n visitScope(child, visit);\n }\n }\n }\n}\n\nfunction collectAwaits(root: TSESTree.Node): TSESTree.AwaitExpression[] {\n const awaits: TSESTree.AwaitExpression[] = [];\n visitScope(root, (node) => {\n if (node.type === \"AwaitExpression\") {\n awaits.push(node);\n }\n });\n return awaits;\n}\n\n/**\n * Guard (a): the scope contains a `return` / `break` / `continue`, marking a\n * retry / short-circuit / early-exit loop whose serial awaits are intentional.\n */\nfunction hasEarlyExit(root: TSESTree.Node): boolean {\n let found = false;\n visitScope(root, (node) => {\n if (\n node.type === \"ReturnStatement\" ||\n node.type === \"BreakStatement\" ||\n node.type === \"ContinueStatement\"\n ) {\n found = true;\n }\n });\n return found;\n}\n\n/**\n * Guard (c): `await new Promise(...)` — a deliberate event-loop / timer yield,\n * not parallelizable I/O.\n */\nfunction isTimerYield(node: TSESTree.AwaitExpression): boolean {\n const arg = node.argument;\n return (\n arg.type === \"NewExpression\" &&\n arg.callee.type === \"Identifier\" &&\n arg.callee.name === \"Promise\"\n );\n}\n\nfunction referencesName(root: TSESTree.Node, name: string): boolean {\n let found = false;\n visitScope(root, (node) => {\n if (node.type === \"Identifier\" && node.name === name) {\n found = true;\n }\n });\n return found;\n}\n\n/**\n * Guard (b): the awaited value is threaded into the next iteration — the await\n * is the RHS of `target = await ...` / `const target = await ...` and `target`\n * is read inside the awaited expression (`x = await f(x)`,\n * `content = await p(content)`). Parallelizing would break the data dependency.\n */\nfunction isThreadedAccumulator(node: TSESTree.AwaitExpression): boolean {\n const parent = node.parent;\n let target: string | null = null;\n if (\n parent.type === \"AssignmentExpression\" &&\n parent.operator === \"=\" &&\n parent.right === node &&\n parent.left.type === \"Identifier\"\n ) {\n target = parent.left.name;\n } else if (\n parent.type === \"VariableDeclarator\" &&\n parent.init === node &&\n parent.id.type === \"Identifier\"\n ) {\n target = parent.id.name;\n }\n if (target === null) {\n return false;\n }\n return referencesName(node.argument, target);\n}\n\n/**\n * Decides whether a set of awaits owned by a loop/callback is worth reporting.\n * Suppressed when the loop short-circuits (a) or iterates an ordered sequence\n * (d); otherwise reported if AT LEAST ONE await is genuinely parallelizable —\n * i.e. not a timer yield (c) and not a threaded accumulator (b).\n */\nfunction shouldReport(\n awaits: readonly TSESTree.AwaitExpression[],\n earlyExit: boolean,\n iterableText: string | null,\n): boolean {\n if (awaits.length === 0) {\n return false;\n }\n if (earlyExit) {\n return false;\n }\n if (iterableText !== null && SEQUENTIAL_ITERABLE_HINT.test(iterableText)) {\n return false;\n }\n return awaits.some(\n (node) => !isTimerYield(node) && !isThreadedAccumulator(node),\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 * The parts of a loop where an await \"belonging to this loop\" can live: the\n * body, plus the C-style `for` init/test/update or the for-of/for-in\n * iterable or the while/do-while test. A part that is itself a nested loop\n * is owned by that loop and checked when it is visited.\n */\n function loopParts(node: LoopNode): (TSESTree.Node | null)[] {\n if (node.type === \"ForStatement\") {\n return [node.body, node.init, node.test, node.update];\n }\n if (node.type === \"ForOfStatement\" || node.type === \"ForInStatement\") {\n return [node.body, node.right];\n }\n return [node.body, node.test];\n }\n\n function iterableTextOf(node: LoopNode): string | null {\n if (node.type === \"ForOfStatement\" || node.type === \"ForInStatement\") {\n return context.sourceCode.getText(node.right);\n }\n return null;\n }\n\n function checkLoop(node: LoopNode): void {\n const awaits: TSESTree.AwaitExpression[] = [];\n let earlyExit = false;\n for (const part of loopParts(node)) {\n if (part === null || isLoop(part)) {\n continue;\n }\n awaits.push(...collectAwaits(part));\n if (!earlyExit && hasEarlyExit(part)) {\n earlyExit = true;\n }\n }\n if (shouldReport(awaits, earlyExit, iterableTextOf(node))) {\n context.report({ node, messageId: \"noSequentialAwait\" });\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 CallExpression(node: TSESTree.CallExpression): void {\n const callee = node.callee;\n if (callee.type !== \"MemberExpression\" || callee.computed) {\n return;\n }\n if (\n callee.property.type !== \"Identifier\" ||\n !ARRAY_ITERATION_METHODS.has(callee.property.name)\n ) {\n return;\n }\n const callback = node.arguments[0];\n if (\n callback === undefined ||\n !isFunctionLike(callback) ||\n !(\"async\" in callback && callback.async)\n ) {\n return;\n }\n // A discarded `.map` / `.filter` (statement position) floats its\n // promises just like `.forEach`; when its result is kept\n // (`Promise.all(...)`, an assignment, a `return`) the awaits are\n // consumed correctly, so only flag `.forEach` or a bare-statement call.\n if (\n callee.property.name !== \"forEach\" &&\n node.parent.type !== \"ExpressionStatement\"\n ) {\n return;\n }\n const awaits = collectAwaits(callback.body);\n const earlyExit = hasEarlyExit(callback.body);\n const iterableText = context.sourceCode.getText(callee.object);\n if (shouldReport(awaits, earlyExit, iterableText)) {\n context.report({ node, messageId: \"noSequentialAwait\" });\n }\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 * Both the compound `s += x` and the equivalent longhand `s = s + x` (a plain\n * `=` assignment whose RHS is a `+` `BinaryExpression` with the target as one\n * operand) are detected — they have identical O(n^2) behavior. A plain\n * `s = x + y` (target absent from the RHS) is NOT flagged.\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 `target` appears as a direct operand of a `+` expression\n * (following left-associative `+` chains, e.g. `s + a + b`). Used to recognize\n * the longhand `s = s + <...>` reassignment, which has the same O(n^2) cost as\n * `s += <...>`. A non-`+` operand (`foo.s`, `s.slice()`, `x + y`) does not match.\n */\nfunction isConcatOperand(\n node: TSESTree.Expression | TSESTree.PrivateIdentifier,\n target: string,\n): boolean {\n if (node.type === \"Identifier\") {\n return node.name === target;\n }\n if (node.type === \"BinaryExpression\" && node.operator === \"+\") {\n return (\n isConcatOperand(node.left, target) || isConcatOperand(node.right, target)\n );\n }\n return false;\n}\n\n/**\n * Returns true if `rhs` is a `+` `BinaryExpression` in which `target` appears as\n * an operand — the reassignment shape `s = s + x` / `s = x + s` / `s = s + a + b`.\n */\nfunction isConcatOntoTarget(\n rhs: TSESTree.Expression,\n target: string,\n): boolean {\n if (rhs.type !== \"BinaryExpression\" || rhs.operator !== \"+\") {\n return false;\n }\n return isConcatOperand(rhs.left, target) || isConcatOperand(rhs.right, target);\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 // The LHS must be a plain variable reference.\n if (node.left.type !== \"Identifier\") {\n return;\n }\n // Accept both the compound `s += x` and the longhand `s = s + x`; any\n // other operator/shape (`s = x + y`, `s -= x`, ...) is not accumulation.\n const isAccumulation =\n node.operator === \"+=\" ||\n (node.operator === \"=\" &&\n isConcatOntoTarget(node.right, node.left.name));\n if (!isAccumulation) {\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 * - Untrack when passed to a user-defined type-guard predicate — a call whose\n * callee name matches `/^is[A-Z]/`, or any call used in an `if`/`?:` test\n * position (`if (guard(body)) { … body.foo … }`). Hand-written guards validate\n * the payload just as a Zod `.parse()` does.\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\n/** User-defined type-guard predicate names, e.g. `isProtectedResourceMetadata`. */\nconst GUARD_NAME_RE = /^is[A-Z]/;\n\n/**\n * True when a call sits in a boolean-test position (`if`/`while`/`for`/`?:`),\n * seen through `!`, `&&`/`||`, and optional-chaining wrappers — i.e. it narrows.\n */\nconst isGuardTestPosition = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node = node;\n let parent: TSESTree.Node | null | undefined = current.parent;\n while (parent !== undefined && parent !== null) {\n switch (parent.type) {\n case AST_NODE_TYPES.UnaryExpression:\n case AST_NODE_TYPES.LogicalExpression:\n case AST_NODE_TYPES.ChainExpression:\n current = parent;\n parent = parent.parent;\n continue;\n case AST_NODE_TYPES.IfStatement:\n case AST_NODE_TYPES.ConditionalExpression:\n case AST_NODE_TYPES.WhileStatement:\n case AST_NODE_TYPES.DoWhileStatement:\n case AST_NODE_TYPES.ForStatement:\n return parent.test === current;\n default:\n return false;\n }\n }\n return false;\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 CallExpression(node): void {\n if (node.callee.type !== AST_NODE_TYPES.Identifier) return;\n if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {\n return;\n }\n const scope = context.sourceCode.getScope(node);\n for (const arg of node.arguments) {\n if (arg.type === AST_NODE_TYPES.SpreadElement) continue;\n const unwrapped = unwrap(arg);\n if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES.Identifier) {\n continue;\n }\n const variable = findVariable(scope, unwrapped.name);\n if (variable !== null) unvalidatedVariables.delete(variable);\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 *\n * SVG drawing data is exempt on `fill`/`stroke`/`color` attributes: any value inside\n * a `<mask>`/`<clipPath>`/`<defs>`/`<pattern>`/`<linearGradient>`/`<radialGradient>`\n * (masking breaks without literal `#fff`/`#000`), the neutral literals\n * (`#fff`/`#000`/`transparent`/`none`/`currentColor`/`inherit`), and `*.stories.*`\n * files (Storybook fixtures) never fire. Real component styling — `className` and\n * inline `style={{ … }}` objects — still fires on hardcoded colors.\n *\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 STORIES_FILE_RE = /\\.stories\\.[cm]?[jt]sx?$/i;\n\n/** SVG container elements whose children carry structural (not UI-token) colors. */\nconst SVG_DEFS_CONTAINERS = new Set<string>([\n \"mask\",\n \"clipPath\",\n \"defs\",\n \"pattern\",\n \"linearGradient\",\n \"radialGradient\",\n]);\n\n/** Neutral fill/stroke literals that are SVG drawing data, never a UI token. */\nconst SVG_EXEMPT_COLOR_VALUES = new Set<string>([\n \"#fff\",\n \"#ffffff\",\n \"#000\",\n \"#000000\",\n \"transparent\",\n \"none\",\n \"currentcolor\",\n \"inherit\",\n]);\n\nconst isInsideSvgDefsContainer = (node: TSESTree.Node): boolean => {\n let current: TSESTree.Node | null | undefined = node.parent;\n while (current !== undefined && current !== null) {\n if (\n current.type === AST_NODE_TYPES.JSXElement &&\n current.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier &&\n SVG_DEFS_CONTAINERS.has(current.openingElement.name.name)\n ) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\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 if (STORIES_FILE_RE.test(context.filename)) return {};\n\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=\"#7c3aed\" stroke=\"#7c3aed\" />.\n // Neutral drawing literals and anything inside an SVG defs container are\n // structural, not UI tokens, so they never fire.\n \"JSXAttribute[name.name=/^(fill|stroke|color)$/]\"(node: TSESTree.JSXAttribute): void {\n if (node.value?.type !== AST_NODE_TYPES.Literal) return;\n if (\n typeof node.value.value === \"string\" &&\n SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())\n ) {\n return;\n }\n if (isInsideSvgDefsContainer(node)) return;\n 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 * `<input>` is resolved by its `type`: a bare `<input type=\"checkbox\">` maps to\n * `<Checkbox>`, `radio` → `<RadioGroup>`, `range` → `<Slider>`, and the text-like\n * types (or no type) → `<Input>`. `type=\"hidden\"` is skipped (no shadcn primitive),\n * and a dynamic `type={…}` falls back to the generic `<Input>` rather than asserting\n * a wrong primitive.\n */\n\nimport {\n AST_NODE_TYPES,\n ESLintUtils,\n type TSESTree,\n} from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"preferShadcn\";\ntype Options = readonly [];\n\nconst REPLACEMENTS: Readonly<Record<string, string>> = {\n select: \"Select\",\n textarea: \"Textarea\",\n dialog: \"Dialog\",\n};\n\n/** `<input type>` → shadcn primitive. Absent types (and text-likes) fall to Input. */\nconst INPUT_TYPE_REPLACEMENTS: Readonly<Record<string, string>> = {\n checkbox: \"Checkbox\",\n radio: \"RadioGroup\",\n range: \"Slider\",\n};\n\n/** `<input type>` values with no shadcn equivalent — never reported. */\nconst SKIPPED_INPUT_TYPES = new Set<string>([\"hidden\"]);\n\nconst kebabCase = (component: string): string =>\n component.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nconst literalTypeAttr = (\n node: TSESTree.JSXOpeningElement,\n): { readonly kind: \"literal\"; readonly value: string } | { readonly kind: \"dynamic\" } | null => {\n for (const attribute of node.attributes) {\n if (\n attribute.type !== AST_NODE_TYPES.JSXAttribute ||\n attribute.name.type !== AST_NODE_TYPES.JSXIdentifier ||\n attribute.name.name !== \"type\"\n ) {\n continue;\n }\n if (attribute.value?.type === AST_NODE_TYPES.Literal && typeof attribute.value.value === \"string\") {\n return { kind: \"literal\", value: attribute.value.value.toLowerCase() };\n }\n return { kind: \"dynamic\" };\n }\n return null;\n};\n\n/** Resolve an `<input>` to its shadcn primitive, or null to skip it entirely. */\nconst resolveInputReplacement = (node: TSESTree.JSXOpeningElement): string | null => {\n const typeAttr = literalTypeAttr(node);\n if (typeAttr === null || typeAttr.kind === \"dynamic\") return \"Input\";\n if (SKIPPED_INPUT_TYPES.has(typeAttr.value)) return null;\n return INPUT_TYPE_REPLACEMENTS[typeAttr.value] ?? \"Input\";\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 =\n elementName === \"input\" ? resolveInputReplacement(node) : REPLACEMENTS[elementName];\n\n if (replacement === undefined || replacement === null) {\n return;\n }\n\n context.report({\n node,\n messageId: \"preferShadcn\",\n data: {\n element: elementName,\n replacement,\n lowercase: kebabCase(replacement),\n },\n });\n },\n };\n },\n});\n","import {\n ESLintUtils,\n type TSESLint,\n type TSESTree,\n AST_NODE_TYPES,\n} 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\n/**\n * A `default` clause with an empty body that is followed by another `case`\n * falls through into that case, which does the real work (e.g.\n * `default: case Single: handle();`). There is nothing to assert here.\n */\nconst isFallthroughDefault = (\n node: TSESTree.SwitchStatement,\n defaultIndex: number,\n): boolean => {\n const defaultCase = node.cases[defaultIndex];\n return (\n defaultCase !== undefined &&\n defaultCase.consequent.length === 0 &&\n defaultIndex < node.cases.length - 1\n );\n};\n\n/**\n * A `default` clause is a deliberate, documented no-op when its body is empty\n * (or an empty block) but carries a comment — e.g. `default: // do nothing`.\n * We can't distinguish a config-string switch from an exhaustive union switch\n * without type info, so a written-out intent to do nothing is honoured;\n * injecting `assertNever` there would throw at runtime. A bare empty default\n * with no comment is still flagged.\n */\nconst isCommentOnlyNoopDefault = (\n defaultCase: TSESTree.SwitchCase,\n sourceCode: Readonly<TSESLint.SourceCode>,\n): boolean => {\n if (defaultCase.consequent.length === 0) {\n const defaultToken = sourceCode.getFirstToken(defaultCase);\n const colonToken = defaultToken\n ? sourceCode.getTokenAfter(defaultToken)\n : null;\n return (\n colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0\n );\n }\n const only = defaultCase.consequent[0];\n if (\n only !== undefined &&\n defaultCase.consequent.length === 1 &&\n only.type === AST_NODE_TYPES.BlockStatement &&\n only.body.length === 0\n ) {\n return sourceCode.getCommentsInside(only).length > 0;\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: \"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 defaultIndex = node.cases.findIndex(\n (caseNode) => 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 (defaultIndex === -1) return;\n const defaultCase = node.cases[defaultIndex];\n if (defaultCase === undefined) 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 // A fallthrough default hands control to a following case, which does\n // the work — there is nothing to assert.\n if (isFallthroughDefault(node, defaultIndex)) return;\n\n // A deliberate, comment-documented no-op default is honoured; we can't\n // prove the discriminant is a union without type info, and injecting\n // assertNever would throw at runtime on a config-string switch.\n if (isCommentOnlyNoopDefault(defaultCase, context.sourceCode)) return;\n\n // Otherwise the default is a bare, undocumented 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 === \"MemberExpression\") {\n if (\n !arg.computed &&\n arg.property.type === \"Identifier\" &&\n isSecretKeyword(arg.property.name)\n ) {\n context.report({\n node: arg,\n messageId: \"noSecretInLog\",\n data: { name: arg.property.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\nfunction isExternalSourceFile(sf: ts.SourceFile | undefined): boolean {\n if (sf === undefined) {\n return false;\n }\n return sf.isDeclarationFile || sf.fileName.includes(\"/node_modules/\");\n}\n\nfunction symbolIsExternallyDeclared(sym: ts.Symbol | undefined): boolean {\n return (\n sym?.declarations?.some((d) => isExternalSourceFile(d.getSourceFile())) ??\n false\n );\n}\n\n/**\n * The iterable expression a destructuring binding element draws its value from,\n * e.g. `Object.entries(x)` for `key` in `for (const [key] of Object.entries(x))`\n * or the RHS of `const { a } = rhs`.\n */\nfunction bindingSourceExpression(\n decl: ts.BindingElement,\n): ts.Expression | undefined {\n let node: ts.Node = decl.parent;\n while (\n !ts.isForOfStatement(node) &&\n !(ts.isVariableDeclaration(node) && node.initializer !== undefined)\n ) {\n if (node.parent === undefined) {\n return undefined;\n }\n node = node.parent;\n }\n return ts.isForOfStatement(node) ? node.expression : node.initializer;\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 /**\n * Whether the compared value provably originates from a type we don't own —\n * a property of a `.d.ts` / node_modules type (DOM `getComputedStyle().overflowY`,\n * `Task.status` from another package), the return of such a method\n * (`URLSearchParams.get()`, `str.toLowerCase()`), or a destructuring of one\n * (`Object.entries()` keys). A string-literal union is not an available fix\n * for these, so the cluster shape must not flag them.\n */\n function originIsExternal(node: ts.Node | undefined, depth: number): boolean {\n if (node === undefined || services === null || depth > 6) {\n return false;\n }\n const checker = services.program.getTypeChecker();\n if (\n ts.isParenthesizedExpression(node) ||\n ts.isNonNullExpression(node) ||\n ts.isAsExpression(node)\n ) {\n return originIsExternal(node.expression, depth + 1);\n }\n if (ts.isPropertyAccessExpression(node)) {\n return symbolIsExternallyDeclared(checker.getSymbolAtLocation(node.name));\n }\n if (ts.isCallExpression(node)) {\n return originIsExternal(node.expression, depth + 1);\n }\n if (ts.isIdentifier(node)) {\n const decl = checker.getSymbolAtLocation(node)?.valueDeclaration;\n if (decl === undefined) {\n return false;\n }\n if (ts.isVariableDeclaration(decl) && decl.initializer !== undefined) {\n return originIsExternal(decl.initializer, depth + 1);\n }\n if (ts.isBindingElement(decl)) {\n return originIsExternal(bindingSourceExpression(decl), depth + 1);\n }\n }\n return false;\n }\n\n function operandIsFlaggable(node: TSESTree.Node): boolean {\n return (\n operandIsRawString(node) &&\n !originIsExternal(services?.esTreeNodeToTSNodeMap.get(node), 0)\n );\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 (operandIsFlaggable(node.left)) {\n accumulate(leftKey, [rightLit], node);\n }\n } else if (rightKey !== null && leftLit !== null) {\n if (operandIsFlaggable(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 || !operandIsFlaggable(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"],"mappings":"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","names":["import_utils","import_utils","import_utils","import_utils","import_utils","propName","import_utils","import_utils","DEFAULT_IGNORE_PATTERNS","import_utils","import_utils","import_utils","isNode","import_utils","import_utils","import_utils","import_utils","findVariable","import_utils","import_utils","propName","keyName","import_utils","import_utils","import_utils","import_utils","import_utils","isNode","calleeName","import_utils","isNode","unwrap","import_utils","LOG_METHODS","LOGGER_NAMES","propertyKeyName","keyName","import_utils","import_utils","kebabCase"]}
|