From 79e0ff2b03142a0f1c6d9ebf324215ef2818dd60 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Fri, 22 Nov 2024 16:20:31 -0700 Subject: [PATCH 1/4] docs: Update README for eslint-config-turbo with Flat Config instructions. --- packages/eslint-config-turbo/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/eslint-config-turbo/README.md b/packages/eslint-config-turbo/README.md index 834b887134852..2db7ade347ff5 100644 --- a/packages/eslint-config-turbo/README.md +++ b/packages/eslint-config-turbo/README.md @@ -16,7 +16,20 @@ npm install eslint --save-dev npm install eslint-config-turbo --save-dev ``` -## Usage +## Usage (Flat Config `eslint.config.js`) + +``` +{ +import turboConfig from "eslint-config-turbo/flat"; + +export default [ + ...turboConfig + // Other configuration +]; +} +``` + +## Usage (Legacy `eslintrc*`) Add `turbo` to the extends section of your eslint configuration file. You can omit the `eslint-config-` prefix: From 8d6fbe00b0ca31fdbf2c14da5079a4574d6f05da Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Fri, 22 Nov 2024 16:52:50 -0700 Subject: [PATCH 2/4] WIP --- packages/eslint-config-turbo/README.md | 41 ++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/eslint-config-turbo/README.md b/packages/eslint-config-turbo/README.md index 2db7ade347ff5..fac8e1dd81f7e 100644 --- a/packages/eslint-config-turbo/README.md +++ b/packages/eslint-config-turbo/README.md @@ -18,15 +18,34 @@ npm install eslint-config-turbo --save-dev ## Usage (Flat Config `eslint.config.js`) +```js +import turboConfig from "eslint-config-turbo/flat"; + +export default [ + ...turboConfig, + // Other configuration +]; ``` -{ + +You can also configure rules available in the configuration: + +```js import turboConfig from "eslint-config-turbo/flat"; export default [ - ...turboConfig + ...turboConfig, // Other configuration + { + rules: { + "turbo/no-undeclared-env-vars": [ + "error", + { + allowList: ["^ENV_[A-Z]+$"], + }, + ], + }, + }, ]; -} ``` ## Usage (Legacy `eslintrc*`) @@ -38,3 +57,19 @@ Add `turbo` to the extends section of your eslint configuration file. You can om "extends": ["turbo"] } ``` + +You can also configure rules available in the configuration: + +```json +{ + "plugins": ["turbo"], + "rules": { + "turbo/no-undeclared-env-vars": [ + "error", + { + "allowList": ["^ENV_[A-Z]+$"] + } + ] + } +} +``` From 060fb069f5724cdeaa274c9e1d3c1493e6244982 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Mon, 25 Nov 2024 12:59:32 -0700 Subject: [PATCH 3/4] docs: Update ESLint documentation with ESLint v9. --- docs/repo-docs/guides/tools/eslint.mdx | 212 +++++++++++++++---------- 1 file changed, 126 insertions(+), 86 deletions(-) diff --git a/docs/repo-docs/guides/tools/eslint.mdx b/docs/repo-docs/guides/tools/eslint.mdx index f11dd047d5d41..14b30df52238f 100644 --- a/docs/repo-docs/guides/tools/eslint.mdx +++ b/docs/repo-docs/guides/tools/eslint.mdx @@ -12,132 +12,175 @@ ESLint is a static analysis tool for quickly finding and fixing problems in your - - This page is written for ESLint v8. If you'd like to contribute to add a - version for v9, the core team is happy to review your pull request. - +In this guide, we'll cover: -## Installing ESLint +- [ESLint v9 with Flat Configuration](#eslint-v9-flat-configs) +- [ESLint v8 with legacy configuration](#eslint-v8-legacy) +- [How to set up a `lint` task (applies to both versions)](#setting-up-a-lint-task) -Install ESLint into each package where you'd like to run it: +We will share configurations across the monorepo's Workspace, ensuring configuration is consistent across packages and composable to maintain high cache hit ratios. - - +## ESLint v9 (Flat Configs) -```bash title="Terminal" -npm install eslint --workspace=web --workspace=docs --workspace=@repo/ui --save-dev -``` +Using ESLint v9's Flat Configs, we will end up with a file structure like this: - - You can keep ESLint versions in sync using a tool like - [syncpack](https://jamiemason.github.io/syncpack). - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +This structure includes: + +- A package called `@repo/eslint-config` in `./packages/eslint-config` that holds all ESLint configuration +- Two applications, each with their own `eslint.config.js` +- A `ui` package that also has its own `eslint.config.js` + +### About the configuration package + +The `@repo/eslint-config` package has three configuration files, `base.js`, `next.js`, and `react-internal.js`. They are [exported from `package.json`](https://github.com/vercel/turborepo/blob/main/examples/basic/packages/eslint-config/package.json#L6) so that they can be used by other packages, according to needs. Examples of the configurations can be found [in the Turborepo GitHub repository](https://github.com/vercel/turborepo/tree/main/examples/basic/packages/eslint-config) and are available in `npx create-turbo@latest`. + +Notably, the `next.js` and `react-internal.js` configurations use the `base.js` configuration for consistency, extending it with more configuration for their respective requirements. Additionally, notice that [the `package.json` for `eslint-config`](https://github.com/vercel/turborepo/blob/main/examples/basic/packages/eslint-config/package.json) has all of the ESLint dependencies for the repository. This is useful, since it means we don't need to re-specify the dependencies in the packages that import `@repo/eslint-config`. + +### Using the configuration package + +In our `web` app, we first need to add `@repo/eslint-config` as a dependency. + + + +```jsonc title="./apps/web/package.json" +{ + "devDependencies": { + "@repo/eslint-config": "*" + } +} +``` + + +```jsonc title="./apps/web/package.json" +{ + "devDependencies": { + "@repo/eslint-config": "*" + } +} +``` + + +```jsonc title="./apps/web/package.json" +{ + "devDependencies": { + "@repo/eslint-config": "workspace:*" + } +} +``` + + - +We can then import the configuration like this: - +```js title="./apps/web/eslint.config.js" +import { nextJsConfig } from '@repo/eslint-config/next-js'; -```bash title="Terminal" -yarn workspace web add eslint --dev -yarn workspace docs add eslint --dev -yarn workspace @repo/ui add eslint --dev +/** @type {import("eslint").Linter.Config} */ +export default nextJsConfig; ``` - +Additionally, you can add configuration specific to the package like this: - +```js title="./apps/web/eslint.config.js" +import { nextJsConfig } from "@repo/eslint-config/next-js"; -```bash title="Terminal" -pnpm install eslint --save-dev --filter=@repo/ui --filter=docs --filter=web +/** @type {import("eslint").Linter.Config} */ +export default [ + ...nextJsConfig; + // Other configurations +] ``` - - +## ESLint v8 (Legacy) -## Sharing configuration + + ESLint v8 is end-of-life as of October 5, 2024. We encourage you to upgrade to + ESLint v9 or later. This documentation is here to help with existing projects + that have not yet upgraded. + -Sharing an ESLint config across packages makes their source code more consistent. Let's imagine a Workspace like this: +Using legacy configuration from ESLint v8 and lower, we will end up with a file structure like this: - + - + - - - - + + + + + + + + + + + -We've got a package called `@repo/eslint-config`, and two applications, each with their own `.eslintrc.js`. +There's a package called `@repo/eslint-config`, and two applications, each with their own `.eslintrc.js`. -### Our `@repo/eslint-config` package +### The `@repo/eslint-config` package -Our `@repo/eslint-config` file contains two files, `next.js`, and `library.js`. These are two different ESLint configs, which we can use in different workspaces, depending on our needs. +The `@repo/eslint-config` file contains two files, `next.js`, and `library.js`. These are two different ESLint configurations, which we can use in different packages, depending on our needs. -Let's investigate the `next.js` lint configuration: +A configuration for Next.js may look like this: ```js title="./packages/eslint-config/next.js" -const { resolve } = require('node:path'); - -const project = resolve(process.cwd(), 'tsconfig.json'); - -/* - * This is a custom ESLint configuration for use with - * Next.js apps. - * - * This config extends the Vercel Engineering Style Guide. - * For more information, see https://github.com/vercel/style-guide - * - */ - +/* Custom ESLint configuration for use with Next.js apps. */ module.exports = { extends: [ - require.resolve('@vercel/style-guide/eslint/node'), - require.resolve('@vercel/style-guide/eslint/typescript'), - require.resolve('@vercel/style-guide/eslint/browser'), - require.resolve('@vercel/style-guide/eslint/react'), - require.resolve('@vercel/style-guide/eslint/next'), - // Turborepo custom eslint configuration configures the following rules: - // - https://github.com/vercel/turborepo/blob/main/packages/eslint-plugin-turbo/docs/rules/no-undeclared-env-vars.md 'eslint-config-turbo', + 'eslint-config-next', + // ...your other ESLint configurations ].map(require.resolve), - parserOptions: { - project, - }, - globals: { - React: true, - JSX: true, - }, - settings: { - 'import/resolver': { - typescript: { - project, - }, - }, - }, - ignorePatterns: ['node_modules/', 'dist/'], - // add rules configurations here - rules: { - 'import/no-default-export': 'off', - }, + // ...your other configuration }; ``` -It's a typical ESLint config that extends the [Vercel style guide](https://github.com/vercel/style-guide), nothing fancy. - The `package.json` looks like this: ```json title="./packages/eslint-config/package.json" @@ -146,8 +189,9 @@ The `package.json` looks like this: "version": "0.0.0", "private": true, "devDependencies": { - "@vercel/style-guide": "latest", - "eslint-config-turbo": "latest" + "eslint": "^8", + "eslint-config-turbo": "latest", + "eslint-config-next": "latest" } } ``` @@ -199,10 +243,6 @@ module.exports = { By adding `@repo/eslint-config/next.js` to our `extends` array, we're telling ESLint to look for a package called `@repo/eslint-config`, and reference the file `next.js`. -### Summary - -This setup ships by default when you [create a new monorepo](/repo/docs/crafting-your-repository#from-zero-to-turbo) with `npx create-turbo@latest`. You can also look at [our basic example](https://github.com/vercel/turborepo/tree/main/examples/basic) to see a working version. - ## Setting up a `lint` task The `package.json` for each package where you'd like to run ESLint should look like this: From 3d283dd202db5f2181d5de8e7cad5ed5c65e89f3 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Mon, 25 Nov 2024 13:04:30 -0700 Subject: [PATCH 4/4] WIP --- packages/eslint-plugin-turbo/README.md | 74 +++++++++++++------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/eslint-plugin-turbo/README.md b/packages/eslint-plugin-turbo/README.md index 21299b643f0f8..cc8f6367ffdb4 100644 --- a/packages/eslint-plugin-turbo/README.md +++ b/packages/eslint-plugin-turbo/README.md @@ -16,45 +16,9 @@ npm install eslint --save-dev npm install eslint-plugin-turbo --save-dev ``` -## Usage (Legacy `eslintrc*`) - -Add `turbo` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: - -```json -{ - "plugins": ["turbo"] -} -``` - -Then configure the rules you want to use under the rules section. - -```json -{ - "rules": { - "turbo/no-undeclared-env-vars": "error" - } -} -``` - -## Example (Legacy `eslintrc*`) - -```json -{ - "plugins": ["turbo"], - "rules": { - "turbo/no-undeclared-env-vars": [ - "error", - { - "allowList": ["^ENV_[A-Z]+$"] - } - ] - } -} -``` - ## Usage (Flat Config `eslint.config.js`) -In ESLint v8, both the legacy system and the new flat config system are supported. In ESLint v9, only the new system will be supported. See the [official ESLint docs](https://eslint.org/docs/latest/use/configure/configuration-files). +ESLint v9 uses the Flat Config format seen below: ```js import turbo from "eslint-plugin-turbo"; @@ -100,3 +64,39 @@ export default [ }, ]; ``` + +## Usage (Legacy `eslintrc*`) + +Add `turbo` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: + +```json +{ + "plugins": ["turbo"] +} +``` + +Then configure the rules you want to use under the rules section. + +```json +{ + "rules": { + "turbo/no-undeclared-env-vars": "error" + } +} +``` + +## Example (Legacy `eslintrc*`) + +```json +{ + "plugins": ["turbo"], + "rules": { + "turbo/no-undeclared-env-vars": [ + "error", + { + "allowList": ["^ENV_[A-Z]+$"] + } + ] + } +} +```