diff --git a/apps/docs-website/docs/configuration.mdx b/apps/docs-website/docs/configuration.mdx index 6a697a6c..04ae5342 100644 --- a/apps/docs-website/docs/configuration.mdx +++ b/apps/docs-website/docs/configuration.mdx @@ -348,72 +348,10 @@ As outlined in the [criteria](./core-philosophy/criteria.md) page, Sheriff comes ```ts pathsOverrides: { - tsconfigLocation: string | string[]; tests: string[]; } ``` -#### `pathsOverrides.tsconfigLocation` - -By default, Sheriff will use the `project: true` option to locate the `tsconfig.json` of your project. - -But, if you have multiple `tsconfig.json` files in your project (like `tsconfig.json`, `tsconfig.eslint.json`, `tsconfig.node.json`, etc...), you can use this parameter to specify which config Sheriff will pickup. - -You can pass it a path as a string (or a list of paths as a array of strings, see: [one-tsconfigjson-per-package](https://typescript-eslint.io/linting/typed-linting/monorepos/#one-tsconfigjson-per-package-and-an-optional-one-in-the-root)). - -Example: - - - - -```js title="eslint.config.js" -import sheriff from "eslint-config-sheriff"; -import { defineFlatConfig } from "eslint-define-config"; - -const sheriffOptions = { - react: false, - next: false, - astro: false, - lodash: false, - playwright: false, - jest: false, - vitest: false, - pathsOverrides: { - // highlight-next-line - tsconfigLocation: "./tsconfig.eslint.json", - }, -}; - -export default defineFlatConfig([...sheriff(sheriffOptions)]); -``` - - - - -```js title="eslint.config.js" -const { sheriff } = require("eslint-config-sheriff"); -const { defineFlatConfig } = require("eslint-define-config"); - -const sheriffOptions = { - react: false, - next: false, - astro: false, - lodash: false, - playwright: false, - jest: false, - vitest: false, - pathsOverrides: { - // highlight-next-line - tsconfigLocation: "./tsconfig.eslint.json", - }, -}; - -module.exports = defineFlatConfig([...sheriff(sheriffOptions)]); -``` - - - - #### `pathsOverrides.tests` By default, Sheriff will apply Jest or Vitest rules only on specific files. diff --git a/packages/eslint-config-sheriff/src/getAstroConfig.ts b/packages/eslint-config-sheriff/src/getAstroConfig.ts index 6a1c3764..cd43ea26 100644 --- a/packages/eslint-config-sheriff/src/getAstroConfig.ts +++ b/packages/eslint-config-sheriff/src/getAstroConfig.ts @@ -1,8 +1,9 @@ import astro from 'eslint-plugin-astro'; +import { getLegacyCompatDirname } from './utils/getLegacyCompatDirname'; export const getAstroConfig = ( hasReact: boolean, - customTSConfigPath: string | string[] | undefined, + disableProjectService: boolean, ) => { return [ ...astro.configs.recommended, @@ -11,7 +12,10 @@ export const getAstroConfig = ( files: ['**/*.astro'], languageOptions: { parserOptions: { - project: customTSConfigPath || true, + ...(disableProjectService ? {} : { projectService: true }), + tsconfigRootDir: disableProjectService + ? undefined + : getLegacyCompatDirname(), }, }, settings: { diff --git a/packages/eslint-config-sheriff/src/getBaseConfig.ts b/packages/eslint-config-sheriff/src/getBaseConfig.ts index 4f3d97a3..c792615c 100644 --- a/packages/eslint-config-sheriff/src/getBaseConfig.ts +++ b/packages/eslint-config-sheriff/src/getBaseConfig.ts @@ -28,8 +28,6 @@ import globals from 'globals'; export const getBaseConfig = ( userConfigChoices: SheriffSettings, ): TSESLint.FlatConfig.ConfigArray => { - const customTSConfigPath = userConfigChoices.pathsOverrides?.tsconfigLocation; - return tseslint.config( { files: [supportedFileTypes], @@ -46,7 +44,9 @@ export const getBaseConfig = ( }, { files: [`**/*{${allJsExtensions}}`], - languageOptions: getLanguageOptionsTypescript(customTSConfigPath), + languageOptions: getLanguageOptionsTypescript( + userConfigChoices.disableProjectService ?? false, + ), }, { files: [supportedFileTypes], diff --git a/packages/eslint-config-sheriff/src/getExportableConfig.ts b/packages/eslint-config-sheriff/src/getExportableConfig.ts index 3463dd8b..eac542f4 100644 --- a/packages/eslint-config-sheriff/src/getExportableConfig.ts +++ b/packages/eslint-config-sheriff/src/getExportableConfig.ts @@ -24,7 +24,7 @@ export const getExportableConfig = ( if (userConfigChoices.react || userConfigChoices.next) { // we insert reactConfig this way because it's an array. It's an array because it contains multiple configs, currently: react, react-hooks, react-a11y and react-refresh. exportableConfig.push( - ...getReactConfig(userConfigChoices.pathsOverrides?.tsconfigLocation), + ...getReactConfig(userConfigChoices.disableProjectService ?? false), ); } @@ -60,11 +60,14 @@ export const getExportableConfig = ( } if (userConfigChoices.astro) { - const customTSConfigPath = - userConfigChoices.pathsOverrides?.tsconfigLocation; const hasReact = Boolean(userConfigChoices.react); - exportableConfig.push(...getAstroConfig(hasReact, customTSConfigPath)); + exportableConfig.push( + ...getAstroConfig( + hasReact, + userConfigChoices.disableProjectService ?? false, + ), + ); } if (userConfigChoices.playwright) { diff --git a/packages/eslint-config-sheriff/src/getReactConfig.ts b/packages/eslint-config-sheriff/src/getReactConfig.ts index 478d9cda..828f83c3 100644 --- a/packages/eslint-config-sheriff/src/getReactConfig.ts +++ b/packages/eslint-config-sheriff/src/getReactConfig.ts @@ -16,13 +16,13 @@ import { getLanguageOptionsTypescriptReact } from './utils/getLanguageOptionsTyp import { type TSESLint } from '@typescript-eslint/utils'; export const getReactConfig = ( - customTSConfigPath?: string | string[], + disableProjectService: boolean, ): TSESLint.FlatConfig.ConfigArray => { return tseslint.config( { // we are specifically not including .astro files here, to not overwrite astro-eslint-parser. files: [`**/*{${allJsExtensions},${allJsxExtensions}}`], - languageOptions: getLanguageOptionsTypescriptReact(customTSConfigPath), + languageOptions: getLanguageOptionsTypescriptReact(disableProjectService), }, { files: [supportedFileTypes], diff --git a/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescript.ts b/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescript.ts index 45fabebd..ccd21861 100644 --- a/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescript.ts +++ b/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescript.ts @@ -1,13 +1,15 @@ -import tseslint from 'typescript-eslint'; +import { getLegacyCompatDirname } from './getLegacyCompatDirname'; export const getLanguageOptionsTypescript = ( - userChosenTSConfig?: string | string[], + disableProjectService: boolean, ) => { return { - parser: tseslint.parser, parserOptions: { ecmaFeatures: { modules: true }, - project: userChosenTSConfig || true, + ...(disableProjectService ? {} : { projectService: true }), + tsconfigRootDir: disableProjectService + ? undefined + : getLegacyCompatDirname(), }, }; }; diff --git a/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescriptReact.ts b/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescriptReact.ts index 78ec9a79..f031a46f 100644 --- a/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescriptReact.ts +++ b/packages/eslint-config-sheriff/src/utils/getLanguageOptionsTypescriptReact.ts @@ -1,14 +1,16 @@ import globals from 'globals'; -import tseslint from 'typescript-eslint'; +import { getLegacyCompatDirname } from './getLegacyCompatDirname'; export const getLanguageOptionsTypescriptReact = ( - userChosenTSConfig?: string | string[], + disableProjectService: boolean, ) => { return { - parser: tseslint.parser, parserOptions: { ecmaFeatures: { modules: true, jsx: true }, - project: userChosenTSConfig || true, + ...(disableProjectService ? {} : { projectService: true }), + tsconfigRootDir: disableProjectService + ? undefined + : getLegacyCompatDirname(), jsxPragma: null, // useful for typescript x react@17 https://github.com/jsx-eslint/eslint-plugin-react/blob/8cf47a8ac2242ee00ea36eac4b6ae51956ba4411/index.js#L165-L179 }, globals: { diff --git a/packages/eslint-config-sheriff/src/utils/getLegacyCompatDirname.ts b/packages/eslint-config-sheriff/src/utils/getLegacyCompatDirname.ts new file mode 100644 index 00000000..54b12bd6 --- /dev/null +++ b/packages/eslint-config-sheriff/src/utils/getLegacyCompatDirname.ts @@ -0,0 +1,8 @@ +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +export const getLegacyCompatDirname = () => { + const isESM = typeof import.meta !== 'undefined'; + return isESM ? dirname(fileURLToPath(import.meta.url)) : __dirname; + // return url.fileURLToPath(new URL('.', isESM ? import.meta.url : __filename)); // alternative code +}; diff --git a/packages/sheriff-types/src/index.ts b/packages/sheriff-types/src/index.ts index a54bfb8d..b3f50072 100644 --- a/packages/sheriff-types/src/index.ts +++ b/packages/sheriff-types/src/index.ts @@ -89,10 +89,6 @@ export interface SheriffSettings extends Partial { * This parameter allows you to override the paths for some Sheriff settings. */ pathsOverrides?: { - /** - * With this setting, if you have multiple tsconfig.json files in your project (like tsconfig.json, tsconfig.eslint.json, tsconfig.node.json, etc...) you can specify which config Sheriff will pickup. You can also specify a list of paths, see: https://typescript-eslint.io/linting/typed-linting/monorepos/#one-tsconfigjson-per-package-and-an-optional-one-in-the-root. - */ - tsconfigLocation?: string | string[]; /** * This setting overrides the default Sheriff filepaths for test files. It accepts an array of filepaths, dictaced by minimatch syntax. Sheriff will apply Jest or Vitest rules only on these files. */ @@ -115,6 +111,15 @@ export interface SheriffSettings extends Partial { * This setting accepts an array of filepaths, dictaced by minimatch syntax. Only the matching files found in this array will be linted. All other files will be ignored. This is useful if you want to lint only a subset of your project. */ files?: string[]; + /** + * `projectService` is enabled by default. If for whatever reason `projectService` is causing you issues, you can disable it. + * For example, if you want to just use the legacy `project` option. + * See https://typescript-eslint.io/packages/parser/#projectservice. + * + * WARNING: disabling `projectService` is extremely discouraged, as the entire linting will probably break. + * At the very least, you should enable the `project` option as an alternative. + */ + disableProjectService?: boolean; } export interface ServerResponse {