Custom ESLint rules #2/5: setup a sample project

Creating a sample monorepo

Our beloved teammates want to eat pineapple pizza! It's illegal! In the previous bite, we decided what to do to save them. Now we are going to discuss how to do it.

ESLint plugins

ESLint allows custom ruleset definitions using plugins. Like any other extended ruleset on the web, we can create our plugin and either publish it to an npm registry or share it in our monorepo. Or even use the npm link command by hand (have fun! 🀯).

NOTE: in the past, it was possible to add rules without using a separate npm package, but the ESLint team decided to support only the plugin way.

Let's jump straight into the code.

Sample project setup

I will create a monorepo using npm workspaces with two packages:

  • our ESLint plugin

  • a sample application to test our plugin

According to the official docs, an ESLint plugin must be named eslint-plugin-<our-plugin-name>. In our case let's call it eslint-plugin-pizza.

Let's create a project folder named yummy-pizza (yes, forgive me, naming is hard) containing the two packages.

yummy-pizza $ npm i -y
yummy-pizza $ mkdir packages/ packages/eslint-plugin-pizza packages/app packages/eslint-plugin-pizza/rules packages/app/src

You should end up with something like this:

yummy-pizza/
β”œβ”€ packages/
β”‚  β”œβ”€ eslint-plugin-pizza/
β”‚  β”‚  β”œβ”€ rules/
β”‚  β”œβ”€ app/
β”‚  β”‚  β”œβ”€ src/
β”œβ”€ package.json
  • packages folder will contain all of our modules in our monorepo

  • eslint-plugin-pizza is our ESLint plugin folder

  • eslint-plugin-pizza/rules is where all of our rules will be placed

  • app is this sample test application

Let's configure our npm workspaces. We need to modify our package.json file and add the workspaces section.

// yummy-pizza/package.json

{
  "name": "yummy-pizza",
  "version": "1.0.0",
  "description": "Sample of custom ESLint plugin definition",
  "author": "Gabriele Buffolino",
  "license": "ISC",
  // each folder inside `packages` will be a node package
  "workspaces": [
    "packages/*"
  ]
}

Just delete the test script for now. The next step is to turn our two folders into proper npm packages.

yummy-pizza $ cd ./packages/eslint-plugin-pizza
yummy-pizza/packages/eslint-plugin-pizza $ npm init -y
yummy-pizza/packages/eslint-plugin-pizza $ cd ../app
yummy-pizza/packages/app $ npm init -y

Here's the updated layout tree:

yummy-pizza/
β”œβ”€ packages/
β”‚  β”œβ”€ eslint-plugin-pizza/
β”‚  β”‚  β”œβ”€ rules/
β”‚  β”‚  β”œβ”€ package.json
β”‚  β”œβ”€ app/
β”‚  β”‚  β”œβ”€ src/
β”‚  β”‚  β”œβ”€ package.json
β”œβ”€ package.json

Let's clean up a bit our newly created package.json files, we should get something like these:

// yummy-pizza/eslint-plugin-pizza/package.json
{
  "name": "eslint-plugin-pizza",
  "version": "1.0.0",
  "description": "Custom ESLint plugin for pizza",
  "type": "module", // we will use ES6 module syntax
  "main": "index.js",
  "author": "Gabriele Buffolino",
  "license": "ISC"
}

// yummy-pizza/app/package.json
{
  "name": "app",
  "version": "1.0.0",
  "description": "Sample application",
  "type": "module", // we will use ES6 module syntax
  "author": "Gabriele Buffolino",
  "license": "ISC"
}

Keep the main field in our plugin package.json, it will be required later on, and delete again the test scripts (we will cover tests in a separate bite in this series). Now your layout is complete and ready to hold our precious code.

In the next bite, we will create our rule.

References

Β