CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-plugin-unicorn

More than 100 powerful ESLint rules for enforcing code quality, consistency, and modern JavaScript best practices

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

import-export-rules.mddocs/

Import and Export Rules

Rules governing module imports, exports, and dependency management for better module organization.

Capabilities

Import Style Rules

Rules for consistent import patterns and module loading.

/**
 * Enforces consistent import style patterns
 */
'unicorn/import-style': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    checkImport?: boolean; // Default: true
    checkDynamicImport?: boolean; // Default: false
    checkExportFrom?: boolean; // Default: false
    checkRequire?: boolean; // Default: false
    extendDefaultStyles?: boolean; // Default: true
    styles?: Record<string, {
      named?: 'camelCase' | 'kebabCase' | 'pascalCase' | false;
      default?: 'camelCase' | 'kebabCase' | 'pascalCase' | false;
      namespace?: 'camelCase' | 'kebabCase' | 'pascalCase' | false;
      unassigned?: boolean;
    }>;
  }
];

/**
 * Prefers node: protocol for Node.js built-in modules
 */
'unicorn/prefer-node-protocol': 'error' | 'warn' | 'off';

/**
 * Requires specific module specifiers for imports
 */
'unicorn/require-module-specifiers': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    patterns?: Record<string, string>;
  }
];

Usage Examples:

// ❌ Bad - inconsistent import style
import * as fs from 'fs';
import { readFile } from 'fs';

// ✅ Good - consistent import style (prefer named imports)
import { readFile, writeFile } from 'node:fs';

// ❌ Bad - missing node: protocol
import fs from 'fs';
import path from 'path';
import util from 'util';

// ✅ Good - using node: protocol
import fs from 'node:fs';
import path from 'node:path';
import util from 'node:util';

// ❌ Bad - bare module specifier when specific version needed
import lodash from 'lodash';

// ✅ Good - specific module specifier (if configured)
import lodash from 'lodash-es';

Export Pattern Rules

Rules for consistent export patterns and module structure.

/**
 * Prevents anonymous default exports
 */
'unicorn/no-anonymous-default-export': 'error' | 'warn' | 'off';

/**
 * Prefers export-from syntax for re-exports
 */
'unicorn/prefer-export-from': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    ignoreUsedVariables?: boolean; // Default: false
  }
];

/**
 * Prevents named default imports and exports
 */
'unicorn/no-named-default': 'error' | 'warn' | 'off';

Usage Examples:

// ❌ Bad - anonymous default export
export default function() {
  return 'helper';
}

// ✅ Good - named default export
export default function helper() {
  return 'helper';
}

// ❌ Bad - manual re-export
import { utility } from './utils.js';
export { utility };

// ✅ Good - export-from syntax
export { utility } from './utils.js';

// ❌ Bad - named default import
import { default as React } from 'react';

// ✅ Good - regular default import
import React from 'react';

Module System Rules

Rules for consistent module system usage and patterns.

/**
 * Prefers ES modules over CommonJS
 */
'unicorn/prefer-module': 'error' | 'warn' | 'off' | [
  'error' | 'warn',
  {
    checkDefaultCase?: boolean; // Default: false
  }
];

/**
 * Prefers import.meta properties over alternatives
 */
'unicorn/prefer-import-meta-properties': 'error' | 'warn' | 'off';

Usage Examples:

// ❌ Bad - CommonJS patterns in ES modules
const path = require('path');
module.exports = { helper };

// ✅ Good - ES module patterns
import path from 'node:path';
export { helper };

// ❌ Bad - __dirname in ES modules
const currentDir = __dirname;

// ✅ Good - import.meta.url
const currentDir = new URL('.', import.meta.url).pathname;

// ❌ Bad - __filename alternative
const currentFile = __filename;

// ✅ Good - import.meta.url for filename
const currentFile = new URL(import.meta.url).pathname;

Dynamic Import Rules

Rules for proper dynamic import usage.

/**
 * Import style rules also apply to dynamic imports when configured
 */
'unicorn/import-style': [
  'error',
  {
    checkDynamicImport: true, // Enable dynamic import checking
  }
];

Usage Examples:

// ❌ Bad - inconsistent dynamic import (if configured to prefer named)
const module = await import('lodash');

// ✅ Good - consistent with static import style
const { debounce } = await import('lodash');

// Dynamic imports with proper error handling
try {
  const { processData } = await import('./data-processor.js');
  await processData(input);
} catch (error) {
  console.error('Failed to load data processor:', error);
}

Package.json and Module Configuration

Rules for package.json and module resolution patterns.

/**
 * Requires specific patterns in package.json imports/exports
 * (This would be configured through require-module-specifiers)
 */
'unicorn/require-module-specifiers': [
  'error',
  {
    patterns: {
      'lodash': 'lodash-es', // Prefer ES module version
      'react-dom': 'react-dom/client', // Prefer specific entry point
    }
  }
];

Usage Examples:

// ❌ Bad - using CommonJS version when ES module preferred
import _ from 'lodash';

// ✅ Good - using ES module version
import _ from 'lodash-es';

// ❌ Bad - using legacy entry point
import { render } from 'react-dom';

// ✅ Good - using modern entry point
import { createRoot } from 'react-dom/client';

Conditional Imports and Exports

Rules for handling conditional module loading.

/**
 * Import style rules can be configured for different environments
 */
'unicorn/import-style': [
  'error',
  {
    styles: {
      'node:fs': {
        named: 'camelCase',
        default: false, // Discourage default import
      },
      'react': {
        default: 'pascalCase',
        named: 'camelCase',
      }
    }
  }
];

Usage Examples:

// Environment-specific imports
if (typeof window !== 'undefined') {
  // Browser-specific imports
  const { browserUtil } = await import('./browser-utils.js');
} else {
  // Node.js-specific imports  
  const { readFile } = await import('node:fs/promises');
}

// Conditional exports in package.json would be:
// {
//   "exports": {
//     "node": "./dist/node.js",
//     "default": "./dist/browser.js"
//   }
// }

TypeScript Import Rules

Rules specific to TypeScript import patterns.

/**
 * Import style rules for TypeScript-specific patterns
 */
'unicorn/import-style': [
  'error',
  {
    styles: {
      '@types/*': {
        default: false, // Types should use named imports
        named: 'camelCase',
      }
    }
  }
];

Usage Examples:

// ❌ Bad - default import for types
import Express from '@types/express';

// ✅ Good - named imports for types
import { Request, Response } from '@types/express';

// Type-only imports
import type { User } from './types.js';
import type { ApiResponse } from './api-types.js';

// Mixed imports
import { processUser, type UserConfig } from './user-utils.js';

Configuration Examples

Comprehensive Import/Export Rules

export default [
  {
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // Import style consistency
      'unicorn/import-style': [
        'error',
        {
          checkImport: true,
          checkDynamicImport: true,
          styles: {
            'node:fs': { named: 'camelCase', default: false },
            'node:path': { named: 'camelCase', default: false },
            'lodash': { named: 'camelCase', default: false },
            'react': { default: 'pascalCase' },
          }
        }
      ],
      
      // Module system preferences
      'unicorn/prefer-node-protocol': 'error',
      'unicorn/prefer-module': 'error',
      'unicorn/prefer-import-meta-properties': 'error',
      
      // Export patterns
      'unicorn/no-anonymous-default-export': 'error',
      'unicorn/prefer-export-from': 'error',
      'unicorn/no-named-default': 'error',
      
      // Module specifiers
      'unicorn/require-module-specifiers': [
        'error',
        {
          patterns: {
            'lodash': 'lodash-es',
            'react-dom': 'react-dom/client',
          }
        }
      ],
    },
  },
];

Node.js-Specific Configuration

export default [
  {
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // Require node: protocol for all built-ins
      'unicorn/prefer-node-protocol': 'error',
      
      // Prefer ES modules
      'unicorn/prefer-module': 'error',
      'unicorn/prefer-import-meta-properties': 'error',
      
      // Node.js import style
      'unicorn/import-style': [
        'error',
        {
          styles: {
            'node:fs': { named: 'camelCase' },
            'node:fs/promises': { named: 'camelCase' },
            'node:path': { named: 'camelCase' },
            'node:url': { named: 'camelCase' },
            'node:util': { named: 'camelCase' },
          }
        }
      ],
    },
  },
];

React Project Configuration

export default [
  {
    plugins: {
      unicorn: eslintPluginUnicorn,
    },
    rules: {
      // React-friendly import styles
      'unicorn/import-style': [
        'error',
        {
          styles: {
            'react': { default: 'pascalCase' },
            'react-dom/client': { named: 'camelCase' },
            '@types/react': { named: 'pascalCase' },
          }
        }
      ],
      
      // Export patterns for components
      'unicorn/no-anonymous-default-export': 'error',
      'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
      
      // Modern module patterns
      'unicorn/prefer-module': 'error',
      'unicorn/require-module-specifiers': [
        'error',
        {
          patterns: {
            'react-dom': 'react-dom/client'
          }
        }
      ],
    },
  },
];

docs

anti-pattern-prevention-rules.md

array-object-rules.md

code-quality-rules.md

code-style-rules.md

dom-browser-rules.md

import-export-rules.md

index.md

modern-javascript-rules.md

plugin-configuration.md

tile.json