/** * ═══════════════════════════════════════════════════════════════════════════ * DO NOT EDIT THIS FILE — IT IS MANAGED AND WILL BE OVERWRITTEN ON UPDATES. * ═══════════════════════════════════════════════════════════════════════════ * * This file is the source of truth for the default `oxlint` and `oxfmt` * configuration. It is automatically regenerated when the template is * updated — any manual changes will be lost. * * To customize linting rules, edit `oxlint.config.ts`. * To customize formatting settings, edit `oxfmt.config.ts`. * * Those two files are preserved across template updates and are designed * to receive user overrides. */ import {defineConfig} from 'oxlint'; import {configs as regexpConfigs} from 'eslint-plugin-regexp'; /** Filter out core ESLint rules bundled into eslint-plugin-regexp recommended config */ const regexpPluginRules = Object.fromEntries(Object.entries(regexpConfigs.recommended.rules).filter(([key]) => key.startsWith('regexp/'))); const commonIgnore = ['**/.*', 'node_modules/**', 'dist/**', 'build/**', 'coverage/**', 'temp/**', 'public/**', '**/*.md']; export const linter = defineConfig({ options: { typeAware: true, typeCheck: true, }, plugins: ['unicorn', 'typescript', 'oxc', 'import', 'react', 'jsdoc', 'promise', 'vitest'], jsPlugins: ['eslint-plugin-regexp'], categories: { correctness: 'error', nursery: 'error', pedantic: 'error', perf: 'error', restriction: 'error', style: 'error', suspicious: 'error', }, rules: { ...regexpPluginRules, 'eslint/capitalized-comments': 'off', // TODO: consider enabling 'eslint/complexity': 'off', // TODO: consider enabling 'eslint/curly': ['error', 'all'], 'eslint/id-length': 'off', 'eslint/init-declarations': 'off', // TODO: consider enabling 'eslint/max-depth': 'off', // TODO: consider enabling 'eslint/max-lines': 'off', // TODO: consider enabling 'eslint/max-lines-per-function': 'off', // TODO: consider enabling 'eslint/max-params': 'off', // TODO: consider enabling 'eslint/max-statements': 'off', // TODO: consider enabling 'eslint/no-await-in-loop': 'warn', 'eslint/no-console': 'off', 'eslint/no-continue': 'off', 'eslint/no-inline-comments': 'off', 'eslint/no-magic-numbers': 'off', 'eslint/no-negated-condition': 'off', // TODO: consider enabling 'eslint/no-nested-ternary': 'off', 'eslint/no-warning-comments': 'off', 'eslint/no-undefined': 'off', // TODO: consider enabling 'eslint/no-plusplus': 'off', 'eslint/one-var': 'off', 'eslint/sort-imports': 'off', 'eslint/sort-keys': 'off', 'eslint/no-ternary': 'off', 'eslint/no-void': ['error', {allowAsStatement: true}], 'typescript/consistent-type-definitions': ['error', 'type'], 'typescript/dot-notation': ['error', {allowPattern: '^[a-zA-Z]+(_[a-zA-Z]+)+$'}], 'typescript/no-import-type-side-effects': 'off', 'typescript/no-unused-vars': [ 'error', { caughtErrors: 'none', argsIgnorePattern: '^_', }, ], 'typescript/prefer-readonly-parameter-types': 'off', 'import/consistent-type-specifier-style': ['error', 'prefer-inline'], 'import/exports-last': 'off', 'import/group-exports': 'off', 'import/max-dependencies': 'off', 'import/no-named-export': 'off', 'import/no-namespace': 'off', // TODO: consider enabling 'import/no-nodejs-modules': 'off', 'import/no-unassigned-import': ['error', {allow: ['**/*.css']}], 'import/prefer-default-export': 'off', 'import/no-default-export': 'off', 'jsdoc/require-param': 'error', 'jsdoc/require-param-type': 'off', 'jsdoc/require-returns': 'warn', 'jsdoc/require-returns-type': 'off', 'oxc/no-async-await': 'off', 'oxc/no-map-spread': 'off', // TODO: consider enabling 'oxc/no-optional-chaining': 'off', 'oxc/no-rest-spread-properties': 'off', 'unicorn/escape-case': 'off', 'unicorn/filename-case': 'off', // TODO: consider enabling 'unicorn/max-nested-calls': ['warn', {max: 5}], 'unicorn/no-array-reduce': 'off', // TODO: consider enabling 'unicorn/no-array-sort': 'off', // TODO: consider enabling 'unicorn/no-hex-escape': 'off', 'unicorn/no-immediate-mutation': 'off', 'unicorn/no-negated-condition': 'off', 'unicorn/no-nested-ternary': 'off', 'unicorn/no-null': 'off', // TODO: consider enabling 'unicorn/no-process-exit': 'off', // TODO: consider enabling 'unicorn/no-typeof-undefined': 'off', // TODO: consider enabling 'unicorn/prefer-module': 'off', // TODO: consider enabling 'unicorn/prefer-number-coercion': 'off', // TODO: consider enabling 'react/function-component-definition': 'off', // TODO: consider enabling 'react/jsx-filename-extension': ['error', {extensions: ['.tsx']}], 'react/jsx-max-depth': ['error', {max: 5}], 'react/jsx-no-literals': 'off', 'react/react-in-jsx-scope': 'off', 'vitest/max-expects': 'off', 'vitest/no-conditional-in-test': 'off', 'vitest/no-hooks': 'off', 'vitest/no-importing-vitest-globals': 'off', 'vitest/prefer-describe-function-title': 'off', 'vitest/prefer-expect-assertions': 'off', 'vitest/prefer-lowercase-title': 'off', 'vitest/prefer-to-be-falsy': 'off', // NOTE: Pick strictness: keep prefer-strict-boolean-matchers, disable truthy/falsy rules. 'vitest/prefer-to-be-truthy': 'off', // NOTE: Pick strictness: keep prefer-strict-boolean-matchers, disable truthy/falsy rules. 'vitest/require-hook': 'off', 'vitest/require-test-timeout': 'off', }, overrides: [ { // Relax strict type rules for unit tests to allow easier mocking and test scaffolding files: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'], rules: { 'typescript/no-unsafe-type-assertion': 'off', 'typescript/no-explicit-any': 'off', 'typescript/no-unsafe-assignment': 'off', 'typescript/no-unsafe-member-access': 'off', 'no-useless-undefined': 'off', }, }, { files: ['tests/e2e/**/*.e2e-test.ts', '**/*.e2e-test.ts'], rules: { 'vitest/prefer-importing-vitest-globals': 'off', }, }, ], settings: { 'jsx-a11y': { polymorphicPropName: undefined, components: {}, attributes: {}, }, next: { rootDir: [], }, react: { formComponents: [], linkComponents: [], version: undefined, }, jsdoc: { ignorePrivate: false, ignoreInternal: false, ignoreReplacesDocs: true, overrideReplacesDocs: true, augmentsExtendsReplacesDocs: false, implementsReplacesDocs: false, exemptDestructuredRootsFromChecks: false, tagNamePreference: {}, }, vitest: { typecheck: false, }, }, env: { builtin: true, }, globals: {}, ignorePatterns: commonIgnore, }); export const formatter = { printWidth: 160, embeddedLanguageFormatting: 'off', useTabs: true, singleQuote: true, bracketSpacing: false, ignorePatterns: commonIgnore, overrides: [ { files: ['src/**/*.{scss,css}'], options: { singleQuote: false, }, }, ], };