post-image

How To Publish Your ESLint Rules as NPM Package

June 22, 2022

Tutorial

Share on Twitter

Table of contents

Disclaimer

In this tutorial, I’ll focus on the specific use case for typescript code-based. You don’t have to imitate this tutorial 100%. You can adjust the specific parts based on your needs

Introduction

Lately, I’ve been too lazy if I have to rewrite the exact same ESLint rules for my personal projects. Look at this. You maybe noticed this in my previous blog titled, Standardize Your Next.js Project.

{
  "env": {
    "node": true
  },
  "extends": [
    "next/core-web-vitals",
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "plugins": ["import", "unused-imports", "@typescript-eslint"],
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"],
        "moduleDirectory": ["node_modules", "src/"]
      }
    }
  },
  "rules": {
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/no-non-null-assertion": "off",
    "@typescript-eslint/no-inferrable-types": "off",
    "@next/next/no-img-element": "off",
    "unused-imports/no-unused-imports": "error",
    "unused-imports/no-unused-vars": [
      "warn",
      {
        "vars": "all",
        "varsIgnorePattern": "^_",
        "args": "after-used",
        "argsIgnorePattern": "^_"
      }
    ],

    "no-eq-null": "warn",
    "import/order": [
      "warn",
      {
        "groups": [
          ["builtin", "external"],
          "internal",
          "parent",
          ["sibling", "index"],
          "object"
        ],
        "newlines-between": "always",
        "alphabetize": {
          "order": "asc",
          "caseInsensitive": true
        }
      }
    ],
    "complexity": "warn",
    "no-console": ["error"]
  }
}

json

Then I knew an old friend who told me that he created his own ESLint rules as an npm package. You can see his here. Like before, I asked him why he put an effort to create this thing? Simply because when he creates a new project (especially a personal project), he just needs to extend the ESLint rules. No need to rewrite the whole ESLint rules from scratch.

module.exports = {
  extends: ['sznm'],
};

jsx

So, his statement inspires me to create my own ESLint config library.

Preparation

First thing first, don’t forget to make an empty directory, then run npm init or yarn init. You can change eslint-config-test with your preferred folder name. Remember that eslint-config prefix must exist so it can be published at the NPM registry as the ESLint Config library.

mkdir eslint-config-test
cd eslint-config-test
yarn init

bash

You will have package.json file like this.

{
  "name": "eslint-config-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

json

Now, install the dependencies that we’ll use to make our ESLint config. Remember, you don’t have to imitate this 100%. You may have some other preferred tools, that’s okay.

yarn add @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-plugin-import eslint-plugin-sonarjs eslint-plugin-unused-imports

bash

Setup The ESLint Rules

Now, you can start to write your own preferred ESLint rules. Start with creating eslintrc.js file, then modify it. Here’s mine, you can use it as a reference.

module.exports = {
  env: {
    node: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:sonarjs/recommended",
  ],
  parser: "@typescript-eslint/parser",
  plugins: ["@typescript-eslint", "import", "unused-imports"],
  settings: {
    "import/resolver": {
      node: {
        extensions: [".js", ".jsx", ".ts", ".tsx"],
        moduleDirectory: ["node_modules", "src/"],
      },
    },
  },
  rules: {
    "no-unused-vars": "off",
    "no-var": "warn",
    "@typescript-eslint/no-unused-vars": "off",
    "unused-imports/no-unused-imports": "error",
    "unused-imports/no-unused-vars": [
      "warn",
      {
        vars: "all",
        varsIgnorePattern: "^_",
        args: "after-used",
        argsIgnorePattern: "^_",
      },
    ],
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/no-non-null-assertion": "off",
    "@typescript-eslint/no-inferrable-types": "off",
    "import/order": [
      "warn",
      {
        groups: [
          ["builtin", "external"],
          "internal",
          "parent",
          ["sibling", "index"],
          "object",
        ],
        "newlines-between": "always",
        alphabetize: {
          order: "asc",
          caseInsensitive: true,
        },
      },
    ],
    complexity: "warn",
    "no-console": ["error"],
  },
};

jsx

After you finish this step, now you can import it at index.js file.

const eslintrc = require("./.eslintrc.js");
module.exports = eslintrc;

jsx

Publish It To NPM Registry

Yep, technically you can now publish your rules. You can run npm publish or yarn publish. Then follow the step in the terminal. You can also create an NPM registry account if you don’t have it before.

Now how to use it? When you want to use it, you can easily extend it at your eslintrc file in your project folder. Here’s mine, you can access it at eslint-config-yehezgun.

Closing

This tutorial seems short, but it will have a long-term effect on you. You can now just need to adjust the ESLint config that has been published if you want to make some changes, then it will be implemented to all the projects that use the ESLint rules (you have to update the dependencies too).

Thanks for reading, hope it helps.

Reference:

Back To Articles Page
Home
Projects
Articles
About Me