/eslint-config

🍰 Lint feature-sliced concepts by existing eslint plugins

Primary LanguageJavaScriptMIT LicenseMIT

WIP: At the moment at beta-testing - use carefully

npm npm npm bundle size GitHub Workflow Status

Linting of FeatureSliced concepts by existing eslint-plugins

Rules

Each rule has its own test cases and customization aspects

Get Started

  1. You'll first need to install ESLint:

    $ npm install -D eslint
    # or by yarn
    $ yarn add -D eslint
  2. Next, install @feature-sliced/eslint-config and dependencies:

    $ npm install -D @feature-sliced/eslint-config eslint-plugin-import eslint-plugin-boundaries
    # or by yarn
    $ yarn add -D @feature-sliced/eslint-config eslint-plugin-import eslint-plugin-boundaries
  3. Add config to the extends section of your .eslintrc configuration file (for recommended rules). You can omit the eslint-config postfix:

    {
        "extends": ["@feature-sliced"]
    }
  4. TYPESCRIPT-ONLY: Also setup TS-parser and TS-plugin (why?)

    Details

    Install dependencies:

    $ npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-import-resolver-typescript
    # or by yarn
    $ yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-import-resolver-typescript

    Configure @typescript-eslint/parser as parser and setup the eslint-import-resolver-typescript resolver in the .eslintrc config file:

    {
      "parser": "@typescript-eslint/parser",
      "settings": {
        "import/resolver": {
          "typescript": {
            "alwaysTryTypes": true
          }
        }
      }
    }

Usage

  • Support general aliases

    import { Input } from "~/shared/ui/input";
    import { Input } from "@/shared/ui/input";
    import { Input } from "@shared/ui/input";
    import { Input } from "$shared/ui/input";
    // But not - import { Input } from "$UIKit/input";
  • Support relative and absolute imports (but look at recommendations)

    import { ... } from "entities/foo";    // absolute imports
    import { ... } from "@/entities/foo";  // aliased imports
    import { ... } from "../entities/foo"; // relative imports
  • Case-agnostic

    import { ... } from "entities/user-post";  // Support kebab-case (recommended)
    import { ... } from "entities/UserPost";   // Support PascalCase
    import { ... } from "entities/userPost";   // Support camelCase
    import { ... } from "entities/user_post";  // Support snake_case
  • For exceptional cases, support ⚠️DANGEROUS-mode⚠️ (see more for specific rule)

Customization

  1. You can partially use the rules

    WARN: Don't use main config ("@feature-sliced") in customization to avoid rules conflicts.

    "extends": [
      "@feature-sliced/eslint-config/rules/import-order",
      "@feature-sliced/eslint-config/rules/public-api",
      "@feature-sliced/eslint-config/rules/layers-slices",
    ]
  2. You can use alternative experimental rules

    • Use import-order/experimental for formatting with spaces between groups and reversed order of layers (why?)

      "extends": [
        // ... Other rules or config
        "@feature-sliced/eslint-config/rules/import-order/experimental",
      ]
    • Use public-api/lite for less strict PublicAPI boundaries (why?)

      "extends": [
        // ... Other rules or config
        "@feature-sliced/eslint-config/rules/public-api/lite",
      ]
  3. You can use warnings instead of errors for specific rules

    "rules": {
       // feature-sliced/import-order
       "import/order": "warn" // ~ 1,
       // feature-sliced/public-api
       "import/no-internal-modules": "warn" // ~ 1,
       // feature-sliced/layers-slices
       "boundaries/element-types": "warn" // ~ 1,
    }
  4. You can use advanced FSD-specific messages processing

    # (feature-sliced/public-api)
    - 'Reaching to "features/search/ui" is not allowed.'
    + 'Violated usage of modules Public API | https://git.io/Jymjf'

See also