diff --git a/README.md b/README.md index 490c145..8fff3fd 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ pnpm add -D @jimmy.codes/eslint-config Then if you want a simple configuration: -```js +```mjs // eslint.config.mjs import eslintConfig from "@jimmy.codes/eslint-config"; @@ -57,92 +57,66 @@ And add the following to your `.vscode/settings.json`: This package contains rules that can be enabled or disabled as follows: -```js +```ts import eslintConfig from "@jimmy.codes/eslint-config"; export default eslintConfig({ /** - * Are TypeScript rules enabled? + * Are astro rules enabled? + * @default false + */ + astro?: boolean; + /** + * Are Jest rules enabled? + * @default false + */ + jest?: boolean; + /** + * Are playwright rules enabled? * @default false */ - typescript: true, + playwright?: boolean; /** * Are React rules enabled? * @default false */ - react: true, + react?: boolean; + /** + * Are Tanstack Query rules enabled? + * @default false + */ + tanstackQuery?: boolean; /** - * Are Astro rules enabled? + * Are Testing Library rules enabled? * @default false */ - astro: true, + testingLibrary?: boolean; /** - * Are testing rules enabled? + * Are TypeScript rules enabled? * @default false */ - testing: true, + typescript?: boolean; + /** + * Are Vitest rules enabled? + * @default false + */ + vitest?: boolean; }); ``` Or you can turn off auto detection to disable rules based on a project's dependencies: -```js +```ts import eslintConfig from "@jimmy.codes/eslint-config"; export default eslintConfig({ autoDetect: false }); ``` -#### TypeScript - -You can also change the project location which can be helpful for monorepos: - -> [!WARNING] -> This is [not recommended nor needed since the introduction of `projectService`](https://typescript-eslint.io/getting-started/typed-linting#can-i-customize-the-tsconfig-used-for-typed-linting) which this config uses by default. - -```js -import eslintConfig from "@jimmy.codes/eslint-config"; - -export default eslintConfig({ - typescript: { - project: ["./tsconfig.eslint.json", "./packages/*/tsconfig.json"], - }, -}); -``` - -#### Testing - -By default [vitest](https://vitest.dev) is used as the testing framework but you can override and add additional rules for utilities: - -```js -import eslintConfig from "@jimmy.codes/eslint-config"; - -export default eslintConfig({ - testing: { - framework: "jest", - utilities: ["testing-library"], - }, -}); -``` - -#### React - -You can add additional rules for utilities: - -```js -import eslintConfig from "@jimmy.codes/eslint-config"; - -export default eslintConfig({ - react: { - utilities: ["@tanstack/query"], - }, -}); -``` - #### Extending the Configuration You can also extend the configuration: -```js +```ts import eslintConfig from "@jimmy.codes/eslint-config"; export default eslintConfig( @@ -164,6 +138,8 @@ export default eslintConfig( ); ``` +#### Ignores + You can also extend what is ignored: ```ts diff --git a/src/factory.spec.ts b/src/factory.spec.ts index e3eae9f..f9f7735 100644 --- a/src/factory.spec.ts +++ b/src/factory.spec.ts @@ -46,7 +46,7 @@ describe("eslintConfig", () => { ); }); - it("should create configuration w/ react & @tanstack/query", async () => { + it("should create configuration w/ react & @tanstack/query (deprecated)", async () => { await expect( eslintConfig({ autoDetect: false, @@ -61,6 +61,12 @@ describe("eslintConfig", () => { }); it("should create configuration w/ jest", async () => { + const configs = await jimmyDotCodes({ autoDetect: false, jest: true }); + + expect(configs.at(7)?.name).toBe("jimmy.codes/jest"); + }); + + it("should create configuration w/ jest (deprecated)", async () => { await expect( eslintConfig({ autoDetect: false, testing: { framework: "jest" } }), ).resolves.toStrictEqual( @@ -72,6 +78,12 @@ describe("eslintConfig", () => { }); it("should create configuration w/ vitest", async () => { + const configs = await jimmyDotCodes({ autoDetect: false, vitest: true }); + + expect(configs.at(7)?.name).toBe("jimmy.codes/vitest"); + }); + + it("should create configuration w/ vitest (deprecated)", async () => { await expect( eslintConfig({ autoDetect: false, testing: true }), ).resolves.toStrictEqual( @@ -83,6 +95,19 @@ describe("eslintConfig", () => { }); it("should create configuration w/ jest & react & testing library", async () => { + const configs = await jimmyDotCodes({ + autoDetect: false, + jest: true, + react: true, + testingLibrary: true, + }); + + expect(configs.at(7)?.name).toBe("jimmy.codes/react"); + expect(configs.at(8)?.name).toBe("jimmy.codes/jest"); + expect(configs.at(9)?.name).toBe("jimmy.codes/testing-library"); + }); + + it("should create configuration w/ jest & react & testing library (deprecated)", async () => { await expect( eslintConfig({ autoDetect: false, @@ -99,6 +124,19 @@ describe("eslintConfig", () => { }); it("should create configuration w/ vitest & react & testing library", async () => { + const configs = await jimmyDotCodes({ + autoDetect: false, + react: true, + testingLibrary: true, + vitest: true, + }); + + expect(configs.at(7)?.name).toBe("jimmy.codes/react"); + expect(configs.at(8)?.name).toBe("jimmy.codes/vitest"); + expect(configs.at(9)?.name).toBe("jimmy.codes/testing-library"); + }); + + it("should create configuration w/ vitest & react & testing library (deprecated)", async () => { await expect( eslintConfig({ autoDetect: false, @@ -142,6 +180,15 @@ describe("eslintConfig", () => { ); }); + it("should create configuration w/ tanstackQuery", async () => { + const configs = await jimmyDotCodes({ + autoDetect: false, + tanstackQuery: true, + }); + + expect(configs.at(7)?.name).toBe("jimmy.codes/react/query"); + }); + describe("autoDetect", () => { it("should include typescript when auto detection is enabled", async () => { vi.mocked(isPackageExists).mockImplementation((name) => { diff --git a/src/factory.ts b/src/factory.ts index a432ba1..8a005e9 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -42,23 +42,33 @@ export const eslintConfig = async ( autoDetect = true, configs = [], ignores = [], + jest = false, playwright = false, react = false, + tanstackQuery = false, testing = false, + testingLibrary = false, typescript = false, + vitest = false, }: Options = {}, ...moreConfigs: Linter.Config[] | TypedConfigItem[] ) => { const reactOptions = getReactOptions(react); - const testingOptions = getTestingOptions(testing); + const testingOptions = getTestingOptions(testing, { + jest, + testingLibrary, + vitest, + }); const typescriptOptions = getTypescriptOptions(typescript); const isTypescriptEnabled = typescript || !!typescriptOptions || (autoDetect && hasTypescript()); const isReactEnabled = react || (autoDetect && hasReact()); - const isTestingEnabled = testing || (autoDetect && hasTesting()); + const isTestingEnabled = + testing || jest || vitest || (autoDetect && hasTesting()); const isAstroEnabled = astro || (autoDetect && hasAstro()); const isTanstackQueryEnabled = shouldEnableTanstackQuery( reactOptions, + tanstackQuery, autoDetect, ); const isTestingLibraryEnabled = shouldEnableTestingLibrary( diff --git a/src/types.ts b/src/types.ts index 9c0fbf0..56fc39c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,6 +4,9 @@ import type { RuleOptions } from "./rules.gen"; export type Rules = RuleOptions; +/** + * @deprecated + */ export interface TypescriptOptions { /** * Location of `tsconfig.json` used for [type aware linting](https://typescript-eslint.io/getting-started/typed-linting) @@ -16,6 +19,9 @@ type TestingFrameworks = "jest" | "vitest"; type TestingUtilities = "testing-library"; type ReactUtilities = "@tanstack/query"; +/** + * @deprecated + */ export interface TestingOptions { /** * Which testing framework are you using? @@ -29,6 +35,10 @@ export interface TestingOptions { utilities?: TestingUtilities[]; } +/** + * @deprecated + */ + export interface ReactOptions { /** * Enable additional rules for utilities such as: @@ -46,6 +56,7 @@ export type TypedConfigItem = Omit< * * @see [Using plugins in your configuration](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#using-plugins-in-your-configuration) */ + // TODO: add undefined plugins?: Record; }; @@ -70,6 +81,11 @@ export interface Options { * @see [Ignoring files](https://eslint.org/docs/latest/use/configure/ignore) */ ignores?: string[]; + /** + * Are Jest rules enabled? + * @default false + */ + jest?: boolean; /** * Are playwright rules enabled? * @default false @@ -80,14 +96,30 @@ export interface Options { * @default false */ react?: boolean | ReactOptions; + /** + * Are Tanstack Query rules enabled? + * @default false + */ + tanstackQuery?: boolean; /** * Are testing rules enabled? * @default false + * @deprecated please use {@link Options.jest}, {@link Options.vitest}, or {@link Options.testingLibrary} instead. */ testing?: boolean | TestingOptions; + /** + * Are Testing Library rules enabled? + * @default false + */ + testingLibrary?: boolean; /** * Are TypeScript rules enabled? * @default false */ typescript?: boolean | TypescriptOptions; + /** + * Are Vitest rules enabled? + * @default false + */ + vitest?: boolean; } diff --git a/src/utils/get-options.spec.ts b/src/utils/get-options.spec.ts index 1151676..a7f5198 100644 --- a/src/utils/get-options.spec.ts +++ b/src/utils/get-options.spec.ts @@ -21,16 +21,29 @@ describe("getTypescriptOptions", () => { describe("getTestingOptions", () => { it("should return default options when a boolean is provided", () => { - expect(getTestingOptions(true)).toStrictEqual({ + expect( + getTestingOptions(true, { + jest: false, + testingLibrary: false, + vitest: false, + }), + ).toStrictEqual({ framework: "vitest", }); }); it("should return override options when an object is provided", () => { expect( - getTestingOptions({ - framework: "jest", - utilities: ["testing-library"], - }), + getTestingOptions( + { + framework: "jest", + utilities: ["testing-library"], + }, + { + jest: false, + testingLibrary: false, + vitest: false, + }, + ), ).toStrictEqual({ framework: "jest", utilities: ["testing-library"], diff --git a/src/utils/get-options.ts b/src/utils/get-options.ts index 3d08933..63e46da 100644 --- a/src/utils/get-options.ts +++ b/src/utils/get-options.ts @@ -4,12 +4,22 @@ export const getTypescriptOptions = (options: boolean | TypescriptOptions) => { return typeof options === "object" ? options : undefined; }; -export const getTestingOptions = (options: boolean | TestingOptions) => { +export const getTestingOptions = ( + options: boolean | TestingOptions, + configs: { + jest: boolean; + testingLibrary: boolean; + vitest: boolean; + }, +) => { return typeof options === "object" ? options - : { - framework: "vitest" as const, - }; + : ({ + framework: configs.vitest ? "vitest" : configs.jest ? "jest" : "vitest", + ...(configs.testingLibrary && { + utilities: ["testing-library" as const], + }), + } as const); }; export const getReactOptions = (options: boolean | ReactOptions) => { diff --git a/src/utils/should-enable.ts b/src/utils/should-enable.ts index c4c6d8f..d69cbf4 100644 --- a/src/utils/should-enable.ts +++ b/src/utils/should-enable.ts @@ -4,10 +4,13 @@ import { hasReactQuery, hasTestingLibrary } from "./has-dependency"; export const shouldEnableTanstackQuery = ( { utilities = [] }: ReactOptions, + tanstackQuery: boolean, autoDetect: boolean, ) => { return ( - utilities.includes("@tanstack/query") || (autoDetect && hasReactQuery()) + tanstackQuery || + utilities.includes("@tanstack/query") || + (autoDetect && hasReactQuery()) ); };