/* eslint-disable max-lines-per-function, max-lines -- config file needs a lot of lines */
/**
 * ESLint 9 Flat Config - Shared Base
 *
 * Publishable factory functions for ESLint base configuration shared across
 * all Lisa-supported stacks (TypeScript, Expo, NestJS, CDK). Projects import
 * these factories to build their stack-specific ESLint config arrays.
 * @see https://eslint.org/docs/latest/use/configure/configuration-files-new
 * @module configs/eslint/base
 */
import eslintComments from "@eslint-community/eslint-plugin-eslint-comments";
import js from "@eslint/js";
import functional from "eslint-plugin-functional";
import jsdoc from "eslint-plugin-jsdoc";
import oxlint from "eslint-plugin-oxlint";
import prettier from "eslint-plugin-prettier/recommended";
import sonarjs from "eslint-plugin-sonarjs";
import globals from "globals";
import tseslint from "typescript-eslint";
const specFilePattern = "**/*spec.ts";
/**
 * Default ignore patterns used when not specified in project config.
 * Projects can override via eslint.ignore.config.json.
 */
export const defaultIgnores = [
    "build/**",
    "dist/**",
    ".build/**",
    ".esbuild/**",
    ".serverless/**",
    ".webpack/**",
    ".warmup/**",
    "node_modules/**",
    "**/node_modules/**",
    "src/graphql/**",
    "src/graphql.ts",
    "src/graphql-generated/**",
    "src/generated/**",
    "graphql/**",
    "graphql-generated/**",
    "generated/**",
    "components/ui/**",
    ".lisabak/**",
    ".claude/worktrees/**",
    // Second agent worktree root — sibling checkouts also land in a bare
    // `.worktrees/`. Linting them from the primary checkout reports another
    // branch's in-flight code as errors here (measured: 1122 in this repo),
    // which turns the pre-push gate into noise developers push past.
    ".worktrees/**",
    ".claude-active-project/**",
    ".claude-active-plan/**",
    "coverage/**",
    specFilePattern,
    "resolver-test.setup.ts",
    "**/*.factory.ts",
    "**/test-utils/**",
    "**/test/**",
    "**/database/migrations/**",
    "cypress/**",
    "e2e/**",
    "playwright-report/**",
    ".lighthouseci/**",
    ".expo/**",
    ".github/**",
    "public/**",
    ".dead/**",
    "example/**",
    "tmp/**",
    ".vscode/**",
    "*.config.js",
    "*.config.ts",
    "babel.config.js",
    "metro.config.js",
    "webpack.*.js",
    "*.d.ts",
    "esbuild.plugins.js",
    // `scripts/**` and `projects/**/scripts/**` used to sit here. They were
    // removed because Lisa INSTALLS its own `.mjs` guard scripts into exactly
    // that tree, so the ignore hid the files Lisa itself authored: a shipped
    // script resolved to no rules at all, and `eslint` reported success on it
    // for its entire life while an external scanner found CRITICAL issues in it.
    // A file nobody lints is indistinguishable from a clean file.
    //
    // Do NOT "fix" this by re-adding `scripts/**` with a negated
    // `!scripts/**/*.mjs` alongside it. Measured: ESLint cannot unignore a file
    // inside an ignored DIRECTORY, so the negation rescues only top-level
    // `scripts/*.mjs` and silently leaves nested ones (e.g.
    // `scripts/lib/*.mjs`, which Lisa ships) uncovered — partial coverage that
    // reads as complete. Rules that genuinely do not apply to standalone CLI
    // scripts are relaxed by `getScriptsFilesOverride()` instead, which is
    // visible in `eslint --print-config` output rather than invisible.
    "lib/**/*.js",
    "cdk.out/**",
    "wiki/**",
    ".lisa.config.json",
];
/**
 * Default thresholds used when not specified in project config.
 * Projects can override via eslint.thresholds.config.json.
 */
export const defaultThresholds = {
    cognitiveComplexity: 10,
    maxLines: 300,
    maxLinesPerFunction: 75,
};
/**
 * Base ESLint configurations that should be applied to all TypeScript projects.
 * This includes recommended configs from ESLint, TypeScript-ESLint, and plugins.
 * @returns {Array} Array of ESLint flat config objects
 */
export const getBaseConfigs = () => [
    // Base configurations
    js.configs.recommended,
    // TypeScript configuration
    ...tseslint.configs.recommended,
    // Functional programming - manual configuration since v7 requires type info
    {
        plugins: {
            functional,
        },
    },
    // Code quality
    ...(sonarjs.configs?.recommended ? [sonarjs.configs.recommended] : []),
    {
        plugins: {
            "@eslint-community/eslint-comments": eslintComments,
        },
        rules: {
            ...eslintComments.configs.recommended.rules,
        },
    },
    // Documentation
    jsdoc.configs["flat/recommended-typescript-flavor"],
    // Prettier (must be last of shared configs)
    prettier,
    // eslint-plugin-oxlint: turn OFF every ESLint rule that oxlint already
    // covers in the hybrid Phase 2 pipeline. Must come AFTER every other
    // config so the disables override prior enables.
    // @see https://github.com/oxc-project/eslint-plugin-oxlint
    ...oxlint.configs["flat/recommended"],
    ...oxlint.configs["flat/typescript"],
    ...oxlint.configs["flat/import"],
    ...oxlint.configs["flat/jsdoc"],
    ...oxlint.configs["flat/promise"],
    ...oxlint.configs["flat/node"],
    ...oxlint.configs["flat/unicorn"],
    ...oxlint.configs["flat/jest"],
    ...oxlint.configs["flat/vitest"],
];
/**
 * Shared rules that apply to all TypeScript projects.
 * These are rules that should be identical across typescript, expo, nestjs, etc.
 * @param {object} thresholds - Threshold values for configurable rules
 * @param {number} thresholds.cognitiveComplexity - Max cognitive complexity
 * @param {number} thresholds.maxLines - Max lines per file
 * @param {number} thresholds.maxLinesPerFunction - Max lines per function
 * @returns {object} Rules configuration object
 */
export const getSharedRules = (thresholds) => ({
    // Prettier: Disabled because running Prettier inside ESLint is redundant and slower.
    // We use `format:check` from package.json for formatting validation and editor Prettier integration.
    // The eslint-config-prettier (imported above) still disables conflicting ESLint rules.
    // @see https://prettier.io/docs/en/integrating-with-linters.html
    "prettier/prettier": "off",
    // Import rules
    "no-restricted-imports": [
        "warn",
        {
            patterns: ["@/features/*/*"],
        },
    ],
    // File size - threshold loaded from eslint.thresholds.config.json
    "max-lines": [
        "error",
        {
            max: thresholds.maxLines,
            skipBlankLines: true,
            skipComments: true,
        },
    ],
    "max-lines-per-function": [
        "error",
        {
            max: thresholds.maxLinesPerFunction,
            skipBlankLines: true,
            skipComments: true,
        },
    ],
    // Folder naming
    // NOTE: eslint-plugin-folders is not compatible with ESLint 9 flat config
    // The rule has no schema defined and ESLint 9 validates rule options strictly
    // This needs to be addressed in a separate PR or the plugin needs to be updated
    // "folders/match-regex": ["error", "^([a-z][a-z0-9]*)(-[a-z0-9]+)*$", "/src/"],
    // SonarJS rules - threshold loaded from eslint.thresholds.config.json
    "sonarjs/cognitive-complexity": ["error", thresholds.cognitiveComplexity],
    "sonarjs/no-identical-functions": "error",
    "sonarjs/no-duplicate-string": "error",
    "sonarjs/no-nested-functions": "error",
    "sonarjs/no-nested-template-literals": "warn",
    "sonarjs/prefer-immediate-return": "warn",
    "sonarjs/prefer-single-boolean-return": "warn",
    "sonarjs/no-collapsible-if": "warn",
    "sonarjs/pseudo-random": "error",
    "sonarjs/no-clear-text-protocols": "error",
    "sonarjs/prefer-read-only-props": "error",
    "sonarjs/no-empty-test-file": "warn",
    "sonarjs/no-nested-conditional": "off",
    "sonarjs/no-commented-code": "warn",
    "sonarjs/no-ignored-exceptions": "warn",
    "sonarjs/todo-tag": "warn",
    // Next takes forever and doesn't provide much value
    "sonarjs/deprecation": "off",
    // Next takes forever and doesn't provide value
    "sonarjs/aws-restricted-ip-admin-access": "off",
    // This gives too many false positives
    "sonarjs/no-hardcoded-ip": "off",
    // This just seems to be wrong and gives all kinds of false positives
    "sonarjs/different-types-comparison": "off",
    // This duplicates another lint check
    "sonarjs/no-unused-vars": "off",
    // ESLint comments
    "@eslint-community/eslint-comments/require-description": "error",
    "@eslint-community/eslint-comments/disable-enable-pair": "error",
    "@eslint-community/eslint-comments/no-unlimited-disable": "error",
    // General rules
    "no-extra-boolean-cast": "off",
    "prefer-const": "error",
    "no-param-reassign": "error",
    "no-var": "error",
    "brace-style": "error",
    "prefer-template": "error",
    radix: "error",
    "space-before-blocks": "error",
    "no-unused-vars": "off",
    // TypeScript rules
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/no-unused-vars": [
        "error",
        {
            argsIgnorePattern: "^_",
            varsIgnorePattern: "^_|^unstable_settings$|^React$",
            caughtErrorsIgnorePattern: "^_",
            destructuredArrayIgnorePattern: "^_",
            ignoreRestSiblings: true,
        },
    ],
    // New rules in typescript-eslint v8 - disabled temporarily
    "@typescript-eslint/no-require-imports": "off",
    "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
    "@typescript-eslint/ban-ts-comment": "off",
    "@typescript-eslint/prefer-as-const": "off",
    "@typescript-eslint/no-empty-object-type": "off",
    "@typescript-eslint/no-unused-expressions": "off",
    "@typescript-eslint/no-unsafe-function-type": "off",
    // Functional rules - configured to avoid type-checking requirements
    // Rules that require type info are disabled
    "functional/no-mixed-types": "off",
    "functional/functional-parameters": "off",
    "functional/prefer-immutable-types": "off",
    "functional/no-expression-statements": "off",
    "functional/no-conditional-statements": "off",
    "functional/prefer-property-signatures": "off",
    "functional/no-return-void": "off",
    "functional/no-throw-statements": "off",
    "functional/prefer-readonly-type": "off",
    "functional/prefer-tacit": "off",
    "functional/readonly-type": "off",
    "functional/type-declaration-immutability": "off",
    // Rules we want - these work without type info
    // NOTE: functional/immutable-data requires type info - enabled in TypeScript file config below
    "functional/immutable-data": "off",
    "functional/no-let": "error",
    // JSDoc rules
    "jsdoc/require-jsdoc": [
        "error",
        {
            require: {
                FunctionDeclaration: true,
                MethodDefinition: true,
                ClassDeclaration: true,
                ArrowFunctionExpression: false,
                FunctionExpression: false,
            },
            contexts: [
                "TSInterfaceDeclaration",
                "TSTypeAliasDeclaration",
                "VariableDeclaration[declarations.0.init.type='ArrowFunctionExpression']:has([id.name=/^[A-Z]/])",
            ],
        },
    ],
    "jsdoc/require-description": "error",
    "jsdoc/require-param": "error",
    "jsdoc/require-returns": "error",
    "jsdoc/require-param-description": "error",
    "jsdoc/require-returns-description": "error",
    "jsdoc/require-property-description": "error",
    // prettier-ignore
    "jsdoc/check-tag-names": ["error", { definedTags: ["remarks", "precondition", "entity", "security", "jest-config-loader", "jest-config-loader-options"] }],
    "jsdoc/no-types": "off",
    "jsdoc/require-param-type": "off",
    "jsdoc/require-returns-type": "off",
    "jsdoc/require-property-type": "off",
});
/**
 * Base language options for all files.
 * @returns {object} Language options configuration
 */
export const getBaseLanguageOptions = () => ({
    globals: {
        ...globals.browser,
        ...globals.node,
        ...globals.es2021,
    },
    parserOptions: {
        ecmaVersion: 2021,
        sourceType: "module",
    },
});
/**
 * JavaScript files override - relaxes certain rules for JS files.
 * @returns {object} ESLint flat config object for JS files
 */
export const getJsFilesOverride = () => ({
    files: ["**/*.js", "**/*.mjs"],
    rules: {
        "sonarjs/cognitive-complexity": "off",
        "@typescript-eslint/no-require-imports": "off", // CommonJS files
        "max-lines-per-function": "off",
    },
});
/**
 * Glob patterns covering the repository-maintenance script tree that Lisa
 * installs into every consumer (`scripts/`), plus nested `scripts/` trees such
 * as `projects/<name>/scripts/`. Exported so the coverage test can assert the
 * shipped `.mjs` paths land inside the same set the override targets.
 */
export const scriptsFilePatterns = ["scripts/**", "**/scripts/**"];
/**
 * Every `jsdoc/*` rule the plugin defines, mapped to "off". Built from the
 * plugin's own rule registry so the scripts profile cannot drift as the plugin
 * gains rules.
 */
const jsdocRulesOff = Object.fromEntries(Object.keys(jsdoc.rules ?? {}).map(name => [`jsdoc/${name}`, "off"]));
/**
 * Standalone-script override — the rule profile for the `scripts/` tree.
 *
 * These files are repository-maintenance CLIs invoked by a developer or a CI
 * runner, not application source and not published library API. They were
 * previously excluded from linting entirely; that is the defect this override
 * exists to make survivable. Every rule turned off here is turned off because
 * it encodes an assumption about application code that a CLI script does not
 * meet — correctness and bug-finding rules (including the SonarJS rules an
 * external scanner also runs, e.g. `sonarjs/no-alphabetical-sort`) stay ON,
 * because those are precisely what the exclusion was hiding.
 * @returns {object} ESLint flat config object for standalone scripts
 */
export const getScriptsFilesOverride = () => ({
    files: scriptsFilePatterns,
    rules: {
        // The whole JSDoc regime exists for the published library surface. A script
        // has no consumers to document for; its interface is its `--help` text.
        // Derived from the plugin's own rule list rather than enumerated, so a
        // future jsdoc rule cannot re-open this by being added upstream — and every
        // resulting `jsdoc/*: off` is still visible in `eslint --print-config`.
        ...jsdocRulesOff,
        // The functional-purity profile targets application state. Scripts are
        // sequential I/O: read argv, walk the tree, write a report, set an exit code.
        "functional/no-let": "off",
        "functional/immutable-data": "off",
        "functional/no-classes": "off",
        // The `no-restricted-syntax` ban on `process.env` redirects app code to a
        // config service. A standalone script has no such service — argv and the
        // environment ARE its configuration.
        "no-restricted-syntax": "off",
        // Declaration-order and size limits are tuned for composed application
        // modules; a script is one linear procedure by design.
        "code-organization/enforce-statement-order": "off",
        "max-lines": "off",
        "max-lines-per-function": "off",
        "sonarjs/cognitive-complexity": "off",
        // SonarJS security HOTSPOTS (not bugs) whose threat model is a server
        // process handling untrusted input. A maintenance script inherits the PATH
        // of the shell that invoked it — pinning absolute paths to `git`/`npm`
        // would break across macOS, Linux, and CI images — and it sets the exec bit
        // on files it generates on purpose.
        "sonarjs/no-os-command-from-path": "off",
        "sonarjs/os-command": "off",
        "sonarjs/file-permissions": "off",
        // Promoted from `warn`, deliberately, against the direction of everything
        // else in this block. A swallowed exception is the failure this whole
        // change exists to end: an error that went somewhere and said nothing, so a
        // broken command reads as a measured zero and a crash passes for a clean
        // result. At `warn` it is invisible under `eslint --quiet` — the same
        // disappearing act one layer up. Measured cost in the shipped and local
        // script trees at the time of promotion: zero occurrences.
        "sonarjs/no-ignored-exceptions": "error",
        // ReDoS hotspot. These regexes run over files already inside the checkout,
        // supplied by the same person running the script.
        "sonarjs/slow-regex": "off",
    },
});
/**
 * Shared hooks and components override - relaxes import restrictions.
 * @returns {object} ESLint flat config object for shared files
 */
export const getSharedFilesOverride = () => ({
    files: ["hooks/shared/**/*", "components/shared/**/*"],
    rules: {
        "no-restricted-imports": "off",
    },
});
/**
 * Test files override - configures Jest globals and relaxes rules for tests.
 * @param additionalPatterns - Additional file patterns to include
 * @returns {object} ESLint flat config object for test files
 */
export const getTestFilesOverride = (additionalPatterns = []) => ({
    files: [
        "**/*.test.js",
        "**/*.test.ts",
        "**/*spec.js",
        specFilePattern,
        "jest.setup.js",
        "jest.setup.ts",
        "jest.setup.pre.js",
        "**/__tests__/*",
        "**/test/**",
        ...additionalPatterns,
    ],
    languageOptions: {
        globals: {
            ...globals.jest,
        },
    },
    rules: {
        "@typescript-eslint/no-explicit-any": "off",
        // Tests often need to mutate state for mocks, setup, and assertions
        "functional/immutable-data": "off",
        // Tests often need let for setup/teardown and incrementing counters
        "functional/no-let": "off",
        // Tests need to manipulate process.env for environment setup
        "no-restricted-syntax": "off",
        // Tests can be longer than typical functions
        "max-lines-per-function": "off",
        // Arrange-act-assert tests interleave mock-setup side effects with
        // consts that read the resulting state, so definition-order cannot apply
        "code-organization/enforce-statement-order": "off",
    },
});
/**
 * TypeScript files override - enables type-checked linting.
 * @param filePatterns - File patterns to match
 * @param tsconfigRootDir - Root directory for tsconfig.json (pass __dirname from calling module)
 * @returns {object} ESLint flat config object for TypeScript files
 */
export const getTsFilesOverride = (filePatterns = ["**/*.ts"], tsconfigRootDir) => ({
    files: filePatterns,
    languageOptions: {
        parserOptions: {
            project: "tsconfig.eslint.json",
            tsconfigRootDir,
        },
    },
    rules: {
        // Enable immutable-data rule now that type-checking is available
        "functional/immutable-data": [
            "error",
            {
                ignoreClasses: true,
                ignoreImmediateMutation: true,
                ignoreNonConstDeclarations: {
                    treatParametersAsConst: true,
                },
                ignoreAccessorPattern: ["*.displayName", "*.current", "*.value"],
            },
        ],
    },
});
/**
 * TypeScript test files override - must come after TypeScript config.
 * @param filePatterns - File patterns for test files
 * @returns {object} ESLint flat config object for TypeScript test files
 */
export const getTsTestFilesOverride = (filePatterns = ["**/*.test.ts", specFilePattern]) => ({
    files: filePatterns,
    rules: {
        // Tests often need to mutate state for mocks, setup, and assertions
        "functional/immutable-data": "off",
        // Tests can be longer than typical functions
        "max-lines-per-function": "off",
    },
});
// Re-export plugins and configs for use in project-specific configs
export { eslintComments, functional, globals, js, jsdoc, prettier, sonarjs, tseslint, };
/* eslint-enable max-lines-per-function, max-lines -- config file needs a lot of lines */
//# sourceMappingURL=base.js.map