{"id":30815134,"url":"https://github.com/rizqyfahmi/eslint-plugin-essential","last_synced_at":"2026-01-20T16:59:31.958Z","repository":{"id":305851299,"uuid":"1023983056","full_name":"rizqyfahmi/eslint-plugin-essential","owner":"rizqyfahmi","description":"Enforce code quality and consistency rules","archived":false,"fork":false,"pushed_at":"2025-07-26T09:41:53.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-26T17:43:22.733Z","etag":null,"topics":["eslint","eslint-plugin","eslint-rules","eslintplugin","javascript","jest","linter","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rizqyfahmi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-22T02:38:56.000Z","updated_at":"2025-07-26T09:41:54.000Z","dependencies_parsed_at":"2025-07-22T10:54:03.401Z","dependency_job_id":null,"html_url":"https://github.com/rizqyfahmi/eslint-plugin-essential","commit_stats":null,"previous_names":["rizqyfahmi/eslint-plugin-sentinel"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/rizqyfahmi/eslint-plugin-essential","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rizqyfahmi%2Feslint-plugin-essential","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rizqyfahmi%2Feslint-plugin-essential/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rizqyfahmi%2Feslint-plugin-essential/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rizqyfahmi%2Feslint-plugin-essential/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rizqyfahmi","download_url":"https://codeload.github.com/rizqyfahmi/eslint-plugin-essential/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rizqyfahmi%2Feslint-plugin-essential/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273874160,"owners_count":25183368,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eslint","eslint-plugin","eslint-rules","eslintplugin","javascript","jest","linter","typescript"],"created_at":"2025-09-06T08:05:37.248Z","updated_at":"2026-01-20T16:59:31.953Z","avatar_url":"https://github.com/rizqyfahmi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eslint-plugin-essential\n\n**A custom ESLint plugin to enforce project-specific code quality and consistency rules.**\n\n[![npm version](https://img.shields.io/npm/v/eslint-plugin-essential.svg)](https://npmjs.com/package/eslint-plugin-essential)\n[![npm downloads](https://img.shields.io/npm/dt/eslint-plugin-essential.svg)](https://npmjs.com/package/eslint-plugin-essential)\n[![License](https://img.shields.io/github/license/rizqyfahmi/eslint-plugin-essential.svg)](https://github.com/rizqyfahmi/eslint-plugin-essential/blob/master/LICENSE)\n[![codecov](https://codecov.io/gh/rizqyfahmi/eslint-plugin-essential/branch/master/graph/badge.svg)](https://codecov.io/gh/rizqyfahmi/eslint-plugin-essential)\n[![CI](https://github.com/rizqyfahmi/eslint-plugin-essential/actions/workflows/ci.yaml/badge.svg)](https://github.com/rizqyfahmi/eslint-plugin-essential/actions/workflows/ci.yaml)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\n## 📦 Installation\n\nInstall the plugin as a development dependency:\n\n```bash\nnpm install eslint-plugin-essential --save-dev\n````\n\n---\n\n## 🚀 Usage\n\nIn your ESLint configuration file (e.g., `.eslintrc.js`), import and configure the plugin:\n\n```js\nimport essential from \"eslint-plugin-essential\";\n\nexport default {\n  plugins: {\n    \"eslint-plugin-essential\": essential,\n  },\n  rules: {\n    \"eslint-plugin-essential/max-nested-loops\": [\"error\", { maxDepth: 1 }],\n    \"eslint-plugin-essential/max-nested-conditionals\": [\"error\", { maxDepth: 1 }],\n    \"eslint-plugin-essential/max-alternative-conditions\": [\"error\", {\n      maxElseIf: 2,\n      maxCase: 5\n    }],\n    \"eslint-plugin-essential/no-else\": \"error\",\n    \"eslint-plugin-essential/pattern-sort-import\": [\"error\", [\n      \"^react\",\n      \"^next\",\n      \"^mobx-react-lite$\",\n      \"^@/\",\n      \"^\\\\.\",\n    ]],\n    \"eslint-plugin-essential/pattern-comments\": [\"error\"]\n  },\n};\n```\n\n\u003e ℹ️ All rules are namespaced under `eslint-plugin-essential`.\n\n---\n\n## 🛠️ Available Rules\n\n### 1. `max-nested-loops`\n\n**Limits the depth of nested loops in your code.**\n\n#### ❌ Incorrect\n\n```js\nfor (let i = 0; i \u003c 10; i++) {\n  while (true) {  // ❌ Too deeply nested\n    // ...\n  }\n}\n```\n\n#### ✅ Correct\n\n```js\nfor (let i = 0; i \u003c 10; i++) {\n  // ...\n}\n```\n\n#### Options\n\n* `maxDepth` (number) – The maximum allowed nesting level (default: `1`)\n\n```js\n\"eslint-plugin-essential/max-nested-loops\": [\"error\", { maxDepth: 1 }]\n```\n\n---\n\n### 2. `max-nested-conditionals`\n\n**Limits the depth of nested conditional statements like `if`, `switch`, and ternary (`?:`) expressions.**\n\n#### ❌ Incorrect\n\n```js\nif (condition1) {\n  if (condition2) {\n    return 'Too Deep';\n  }\n}\n```\n\n```js\nconst result = condition1 ? (condition2 ? 'A' : 'B') : 'C';\n```\n\n#### ✅ Correct\n\n```js\nif (condition1) {\n  return 'Shallow enough';\n}\n```\n\n```js\nconst result = condition1 ? 'A' : 'B';\n```\n\n#### Options\n\n* `maxDepth` (number) – The maximum allowed nesting level (default: `1`)\n\n```js\n\"eslint-plugin-essential/max-nested-conditionals\": [\"error\", { maxDepth: 1 }]\n```\n\n---\n\n### 3. `max-alternative-conditions`\n\n**Limits the number of `else if` and `switch case` branches to reduce complex branching logic.**\n\n#### ❌ Incorrect\n\n```js\nif (a) {}\nelse if (b) {}\nelse if (c) {}\nelse if (d) {}\n```\n\n```js\nswitch (value) {\n  case 1: break;\n  case 2: break;\n  case 3: break;\n  case 4: break;\n  case 5: break;\n  case 6: break;\n}\n```\n\n#### ✅ Correct\n\n```js\nif (a) {}\nelse if (b) {}\n```\n\n```js\nswitch (value) {\n  case 1: break;\n  case 2: break;\n  case 3: break;\n}\n```\n\n#### Options\n\n* `maxElseIf` (number) – Maximum allowed `else if` branches (default: `2`)\n* `maxCase` (number) – Maximum allowed `switch` case clauses (default: `5`)\n\n```js\n\"eslint-plugin-essential/max-alternative-conditions\": [\"error\", {\n  maxElseIf: 2,\n  maxCase: 5\n}]\n```\n\n\u003e ℹ️ `else` blocks are **no longer counted or restricted** by this rule.\n\u003e Use `eslint-plugin-essential/no-else` to explicitly disallow `else`.\n\n---\n\n### 4. `no-else`\n\n**Disallows the use of `else` blocks.**\nEncourages early returns and guard clauses for simpler, flatter code structure. `else if` is still allowed.\n\n#### ❌ Incorrect\n\n```js\nif (condition) {\n  return true;\n} else {\n  return false;\n}\n```\n\n#### ✅ Correct\n\n```js\nif (condition) {\n  return true;\n}\nreturn false;\n```\n\n#### Options\n\nThis rule takes **no options**.\n\n```js\n\"eslint-plugin-essential/no-else\": \"error\"\n```\n\n---\n\n### 5. `pattern-sort-import`\n\n**Sorts import statements according to configured regex patterns without reordering imports within the same group.**\n\nThis rule enforces a custom order of import groups defined by regex patterns. Imports matching earlier patterns appear first, while imports within the same group keep their original order.\n\n#### ❌ Incorrect\n\n```ts\nimport Link from \"next/link\"\nimport { useEffect } from \"react\"\nimport { observer } from \"mobx-react-lite\"\nimport { TbInfoCircle } from \"react-icons/tb\"\nimport styles from \"./styles.module.css\"\nimport MyComponent from \"@/components/my-component\"\n```\n\n#### ✅ Correct\n\n```ts\nimport { useEffect } from \"react\"\nimport { TbInfoCircle } from \"react-icons/tb\"\nimport Link from \"next/link\"\nimport { observer } from \"mobx-react-lite\"\nimport MyComponent from \"@/components/my-component\"\nimport styles from \"./styles.module.css\"\n```\n\n#### Options\n\nAn array of regex strings defining the import group order. Imports are grouped by matching these patterns.\n\nExample:\n\n```js\n\"eslint-plugin-essential/pattern-sort-import\": [\"error\", [\n  \"^react\",\n  \"^next\",\n  \"^mobx-react-lite$\",\n  \"^@/\",\n  \"^\\\\.\",\n]]\n```\n\n---\n\n### 6. `pattern-comments`\n\n**Disallows all comments that do not match a specific pattern (regex).**\nUse this rule to enforce a consistent format for all comments (e.g., requiring tags like `TODO:`, `@public`, etc.).\n\n#### ❌ Incorrect\n\n```js\n// this is a random comment\n\n/* just a block comment */\n\n/** some unstructured JSDoc */\n```\n\n#### ✅ Correct\n\n```js\n// TODO: handle edge case\n\n/** @deprecated Use another function */\n\n/* @public This is a public method */\n```\n\n#### Options\n\nYou can customize which comment formats are allowed using a regular expression string.\n\n```js\n\"eslint-plugin-essential/pattern-comments\": [\"error\", {\n  allowPattern: \"^((TODO|FIXME|NOTE|BUG|HACK|OPTIMIZE|REVIEW|SECURITY):|@(public|private|deprecated))\"\n}]\n```\n\n* The example above allows only comments that start with:\n\n  * `TODO:`, `FIXME:`, `NOTE:`, `BUG:`, `HACK:`, `OPTIMIZE:`, `REVIEW:`, `SECURITY:`\n  * Or tags like `@public`, `@private`, `@deprecated`\n\n\u003e 💡 By default, the rule uses the same pattern shown above. If no `allowPattern` is provided, this default is enforced.\n\n---\n\n\n### 7. `pattern-restricted-import`\n\n**Disallows import paths that match specific regular expression patterns.**\nUse this rule to **restrict imports** from specific directories or files—such as test helpers, internal modules, or implementation details that should remain private.\n\n#### ❌ Incorrect\n\n```js\nimport helper from '../test/helper'        // 🚫 Matches /test/\nimport internal from '@/internal/api'      // 🚫 Matches ^@/internal/\nimport testUtil from './foo/bar.test.ts'   // 🚫 Matches \\.test$\n```\n\n#### ✅ Correct\n\n```js\nimport api from '@/public/api'\nimport { Button } from '@/components/ui'\n```\n\n#### Options\n\nProvide an array of regular expression strings to define restricted import paths.\n\n```js\n\"eslint-plugin-essential/pattern-restricted-import\": [\"error\", [\n  \"/test/\",\n  \"^@/internal/\",\n  \"\\\\.test$\"\n]]\n```\n\n\u003e ℹ️ This rule helps enforce **boundary protection** in your codebase by preventing unintended dependencies on test files or internal modules.\n\n---\n\n## 🔓 License\n\nSee the [LICENSE](https://github.com/rizqyfahmi/eslint-plugin-essential/blob/master/LICENSE) file for license rights and limitations (MIT).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frizqyfahmi%2Feslint-plugin-essential","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frizqyfahmi%2Feslint-plugin-essential","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frizqyfahmi%2Feslint-plugin-essential/lists"}