JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • 0
  • Score
    100M100P100Q16943F
  • License MIT

Zero-config ESLint, Prettier, and Husky setup for Node.js TypeScript backend projects

Package Exports

  • eslint-config-node-ts-backend
  • eslint-config-node-ts-backend/husky
  • eslint-config-node-ts-backend/prettier

Readme

eslint-config-node-ts-backend

A zero-config ESLint, Prettier, and Husky setup for Node.js TypeScript backend projects. This package provides a highly opinionated, yet flexible, linting and code formatting solution designed specifically for backend applications in monorepo environments.

Quick Start

Installation

npm install --save-dev eslint-config-node-ts-backend

Zero-Config Usage

// eslint.config.js
import rajeshConfig from 'eslint-config-node-ts-backend';

// Auto-detects TypeScript, Node.js, and applies best practices
export default rajeshConfig();

That's it! True zero configuration - the package automatically detects your project features and applies the appropriate rules.

Features

  • 🚀 Zero-config setup - Works out of the box with sensible defaults
  • 🎯 TypeScript-first - Comprehensive TypeScript linting with type-aware rules
  • 🔒 Security-focused - Built-in security vulnerability detection
  • 🏗️ Monorepo-ready - Designed for monorepo TypeScript projects
  • 🎨 Prettier integration - Seamless code formatting
  • 🐶 Husky & lint-staged - Pre-commit hooks for quality assurance
  • 🔧 Easily customizable - Override rules when needed

Included Plugins & Configurations

  • @typescript-eslint - TypeScript-specific linting rules
  • eslint-plugin-n - Node.js best practices
  • eslint-plugin-security - Security vulnerability detection
  • eslint-plugin-sonarjs - Code quality and complexity analysis
  • eslint-plugin-unicorn - Modern JavaScript/TypeScript patterns
  • eslint-config-prettier - Prettier integration
  • Flat Config - Uses ESLint's new flat configuration system

Installation

1. Install the package

npm install --save-dev eslint-config-rajesh-node-backend

2. Install peer dependencies

npm install --save-dev eslint prettier typescript

3. Install optional dependencies for pre-commit hooks

npm install --save-dev husky lint-staged

Usage

Basic Setup

1. Create ESLint configuration

Create eslint.config.js in your project root:

import config from 'eslint-config-node-ts-backend';

export default config;

2. Create Prettier configuration

Create .prettierrc.json in your project root:

{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 100,
  "useTabs": false,
  "quoteProps": "as-needed",
  "bracketSpacing": true,
  "bracketSameLine": false,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}

Or import the configuration:

// prettier.config.js
import config from 'eslint-config-node-ts-backend/prettier';

export default config;

3. Add scripts to package.json

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write \"**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,yml,yaml}\"",
    "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,yml,yaml}\"",
    "prepare": "husky install"
  }
}

Note: With ESLint v9+ flat config, the --ext flag is no longer needed. File extensions are configured in the config file itself.

Monorepo Setup

1. Install at monorepo root

# At monorepo root
npm install --save-dev eslint-config-node-ts-backend eslint prettier typescript

2. Create configurations at root

eslint.config.js (at monorepo root):

import config from '@rajeshbandarupalli/eslint-config-node-backend';

export default config;

package.json (at monorepo root):

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check ."
  }
}

tsconfig.eslint.json (at monorepo root):

{
  "extends": "./node_modules/eslint-config-node-ts-backend/tsconfig.eslint.json",
  "compilerOptions": {
    "tsconfigRootDir": "."
  },
  "include": [
    "packages/*/src/**/*",
    "apps/*/src/**/*"
  ]
}

3. Configure individual packages

In each package's eslint.config.js:

import config from '@rajeshbandarupalli/eslint-config-node-backend';

export default [
  ...config,
  {
    languageOptions: {
      parserOptions: {
        project: './tsconfig.json',
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
];

Husky & Lint-Staged Setup

Automatic Setup

node ./node_modules/eslint-config-node-ts-backend/husky-setup.js

Manual Setup

  1. Initialize Husky:
npx husky install
  1. Create pre-commit hook:
npx husky add .husky/pre-commit "npx lint-staged"
  1. Create .lintstagedrc.json:
{
  "*.{ts,tsx,js,jsx,cjs,mjs}": [
    "eslint --fix",
    "prettier --write"
  ],
  "*.{json,md,yml,yaml}": [
    "prettier --write"
  ]
}

Customization & Overriding Rules

Auto-Detection Features

The configuration automatically detects:

  • TypeScript: Looks for tsconfig.json
  • Node.js: Checks package.json for Node.js dependencies
  • Project Structure: Applies appropriate rules based on detected features
// eslint.config.js
import rajeshConfig from 'eslint-config-node-ts-backend';

export default rajeshConfig({
  typescript: true,     // Force TypeScript rules
  node: true,          // Force Node.js rules
  stylistic: true,     // Enable Prettier integration
  rules: {
    // Override specific rules
    '@typescript-eslint/no-explicit-any': 'off',
    'no-console': 'off',
    'unicorn/filename-case': ['error', { case: 'camelCase' }],
    
    // Add custom rules
    'prefer-const': 'error',
    'no-var': 'error',
  },
  ignores: [
    // Add custom ignore patterns
    'custom-build/**',
    'legacy-code/**',
  ],
});

Method 2: Extending the Base Configuration

// eslint.config.js
import baseConfig from 'eslint-config-node-ts-backend';

export default [
  ...baseConfig,
  {
    // Override rules for specific files
    files: ['**/*.test.ts', '**/*.spec.ts'],
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      'sonarjs/no-duplicate-string': 'off',
    },
  },
  {
    // Project-specific rules
    files: ['src/**/*.ts'],
    rules: {
      'no-console': 'error', // Stricter for production code
    },
  },
  {
    // Disable rules for specific directories
    files: ['scripts/**/*.js'],
    rules: {
      'unicorn/prefer-module': 'off',
      'n/no-process-exit': 'off',
    },
  },
];

Method 3: Environment-Specific Configurations

// eslint.config.js
import rajeshConfig from 'eslint-config-rajesh-node-backend';

const isProduction = process.env.NODE_ENV === 'production';

export default rajeshConfig({
  rules: {
    // Stricter rules in production
    'no-console': isProduction ? 'error' : 'warn',
    'no-debugger': isProduction ? 'error' : 'warn',
    '@typescript-eslint/no-explicit-any': isProduction ? 'error' : 'warn',
  },
});

Method 4: Legacy Helper (Backward Compatibility)

// eslint.config.js
import { createConfig } from 'eslint-config-node-ts-backend';

export default createConfig({
  rules: {
    'no-console': 'off',
  },
});

Common Rule Overrides

Disable Specific Rules

export default [
  ...baseConfig,
  {
    rules: {
      // Disable filename case enforcement
      'unicorn/filename-case': 'off',
      
      // Allow console.log in development
      'no-console': 'off',
      
      // Allow any type in legacy code
      '@typescript-eslint/no-explicit-any': 'off',
      
      // Disable cognitive complexity for complex business logic
      'sonarjs/cognitive-complexity': 'off',
    },
  },
];

Adjust Rule Severity

export default [
  ...baseConfig,
  {
    rules: {
      // Change from error to warning
      '@typescript-eslint/no-explicit-any': 'warn',
      'unicorn/prevent-abbreviations': 'warn',
      
      // Change from warning to error
      'no-console': 'error',
    },
  },
];

File-Specific Overrides

export default [
  ...baseConfig,
  {
    // Test files
    files: ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**/*.ts'],
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      'sonarjs/no-duplicate-string': 'off',
      'unicorn/consistent-function-scoping': 'off',
    },
  },
  {
    // Configuration files
    files: ['*.config.js', '*.config.ts', 'config/**/*.ts'],
    rules: {
      'unicorn/prefer-module': 'off',
      'n/no-process-env': 'off',
    },
  },
  {
    // Migration scripts
    files: ['migrations/**/*.ts', 'scripts/**/*.ts'],
    rules: {
      'no-console': 'off',
      'unicorn/filename-case': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
    },
  },
];

Prettier Customization

Override Prettier Settings

// prettier.config.js
import baseConfig from 'eslint-config-node-ts-backend/prettier';

export default {
  ...baseConfig,
  // Override specific settings
  printWidth: 120,
  tabWidth: 4,
  semi: false,
  singleQuote: false,
};

Project-Specific .prettierrc.json

{
  "semi": false,
  "singleQuote": false,
  "tabWidth": 4,
  "trailingComma": "es5",
  "printWidth": 120,
  "overrides": [
    {
      "files": "*.md",
      "options": {
        "printWidth": 80,
        "proseWrap": "always"
      }
    }
  ]
}

Troubleshooting

Common Issues

ESLint v9+ Flat Config Issues

Error: Invalid option '--ext' - perhaps you meant '-c'?

This error occurs when using ESLint v9+ with flat config format. The --ext flag is no longer supported.

Old way (doesn't work with flat config):

eslint . --ext .ts,.tsx,.js,.jsx,.cjs,.mjs

New way (works with flat config):

eslint .

File extensions are now configured in your eslint.config.js file automatically by this package.

TypeScript Project References

If you're using TypeScript project references in a monorepo:

// eslint.config.js
import config from '@rajeshbandarupalli/eslint-config-node-backend';

export default [
  ...config,
  {
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.json', './packages/*/tsconfig.json'],
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
];

Performance Issues

For large monorepos, you might want to exclude certain directories:

export default [
  ...config,
  {
    ignores: [
      'node_modules/**',
      'dist/**',
      'build/**',
      'coverage/**',
      // Add more patterns as needed
      'packages/*/node_modules/**',
      'apps/*/dist/**',
    ],
  },
];

Memory Issues

If ESLint runs out of memory:

# Increase Node.js memory limit
node --max-old-space-size=8192 ./node_modules/.bin/eslint .

Or add to package.json:

{
  "scripts": {
    "lint": "node --max-old-space-size=8192 ./node_modules/.bin/eslint ."
  }
}

Rule Explanations

TypeScript Rules

  • @typescript-eslint/no-floating-promises: Prevents unhandled promises
  • @typescript-eslint/prefer-nullish-coalescing: Encourages ?? over ||
  • @typescript-eslint/prefer-optional-chain: Encourages optional chaining
  • @typescript-eslint/require-await: Ensures async functions contain await

Security Rules

  • security/detect-object-injection: Prevents object injection vulnerabilities
  • security/detect-non-literal-fs-filename: Warns about dynamic file paths
  • security/detect-eval-with-expression: Prevents eval usage

Code Quality Rules

  • sonarjs/cognitive-complexity: Limits function complexity (max 15)
  • unicorn/prefer-array-find: Prefers .find() over .filter()[0]
  • unicorn/filename-case: Enforces kebab-case filenames

Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

License

MIT License - see LICENSE file for details.

Changelog

1.0.0

  • Initial release
  • TypeScript-first ESLint configuration
  • Prettier integration
  • Husky and lint-staged setup
  • Monorepo support
  • Comprehensive rule set for Node.js backend development