Exemples Toolchain JavaScript Biome

Exemples de toolchain JavaScript Biome incluant configuration, linting, formatting, bundling et tooling moderne JavaScript/TypeScript

💻 Configuration de Base Biome json

🟢 simple

Configuration complète de Biome pour projets JavaScript/TypeScript avec configuration moderne et meilleures pratiques

⏱️ 20 min 🏷️ biome, setup, toolchain, configuration
Prerequisites: Node.js, npm/yarn, Modern JavaScript/TypeScript
// Biome Basic Setup and Configuration
// Biome is the successor to Rome - an all-in-one JavaScript toolchain

// 1. Installation
// npm install --save-dev @biomejs/biome
// Or: yarn add --dev @biomejs/biome
// Or: pnpm add -D @biomejs/biome

// 2. Initialize Biome in your project
// npx @biomejs/biome init

// 3. biome.json - Main Biome Configuration
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "complexity": {
        "noExtraBooleanCast": "error",
        "noMultipleSpacesInRegularExpressionLiterals": "error",
        "noUselessCatch": "error",
        "noWith": "error"
      },
      "correctness": {
        "noUnusedVariables": "error",
        "noUndeclaredVariables": "error",
        "noUnreachable": "error",
        "noConstantCondition": "warn"
      },
      "style": {
        "noNegationElse": "error",
        "useShorthandArrayType": "error",
        "useTemplate": "error",
        "useImportType": "error"
      },
      "suspicious": {
        "noArrayIndexKey": "warn",
        "noAsyncPromiseExecutor": "error",
        "noCatchAssign": "error",
        "noDebugger": "error",
        "noDuplicateClassMembers": "error",
        "noEmptyBlockStatements": "error",
        "noExplicitAny": "warn",
        "noFallthroughSwitchClause": "error",
        "noGlobalObjectCalls": "error",
        "noImportAssign": "error",
        "noMisleadingCharacterClass": "error",
        "noRedeclare": "error",
        "noShadowRestrictedNames": "error",
        "noUnsafeNegation": "error"
      },
      "nursery": {
        "useSortedClasses": "error",
        "noUndeclaredDependencies": "warn",
        "noUselessRename": "error",
        "useIsNan": "error"
      }
    }
  },
  "formatter": {
    "enabled": true,
    "formatWithErrors": false,
    "indentStyle": "space",
    "indentSize": 2,
    "lineWidth": 80,
    "lineEnding": "lf",
    "quoteStyle": "single",
    "jsxQuoteStyle": "double",
    "attributePosition": "auto",
    "bracketSpacing": true,
    "bracketSameLine": false,
    "arrowParentheses": "asNeeded",
    "semicolons": "asNeeded",
    "trailingComma": "es5",
    "quoteProperties": "preserve"
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "jsxQuoteStyle": "double",
      "quoteProperties": "preserve",
      "trailingComma": "es5",
      "semicolons": "asNeeded",
      "arrowParentheses": "asNeeded",
      "bracketSpacing": true,
      "bracketSameLine": false,
      "attributePosition": "auto"
    },
    "globals": [
      "window",
      "document",
      "console",
      "process",
      "Buffer",
      "global"
    ]
  },
  "typescript": {
    "formatter": {
      "quoteStyle": "single",
      "jsxQuoteStyle": "double",
      "quoteProperties": "preserve",
      "trailingComma": "es5",
      "semicolons": "asNeeded",
      "arrowParentheses": "asNeeded",
      "bracketSpacing": true,
      "bracketSameLine": false,
      "attributePosition": "auto"
    }
  },
  "json": {
    "formatter": {
      "indentSize": 2,
      "lineWidth": 80,
      "trailingComma": "none"
    }
  },
  "css": {
    "formatter": {
      "enabled": true,
      "indentSize": 2,
      "lineWidth": 80
    }
  },
  "files": {
    "ignore": [
      "node_modules/**",
      "dist/**",
      "build/**",
      "coverage/**",
      "*.min.js",
      "*.min.css",
      ".next/**",
      ".nuxt/**",
      ".vite/**"
    ],
    "ignoreUnknown": true,
    "include": ["src/**/*", "tests/**/*"]
  }
}

// 4. package.json Scripts Integration
{
  "name": "my-biome-project",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "lint": "biome check",
    "lint:fix": "biome check --apply",
    "lint:unsafe": "biome check --apply-unsafe",
    "format": "biome format",
    "format:write": "biome format --write",
    "ci": "biome ci",
    "check": "biome check --write",
    "check:unsafe": "biome check --write --apply-unsafe",
    "organize-imports": "biome check --write --only=source.organizeImports"
  },
  "devDependencies": {
    "@biomejs/biome": "^1.9.4"
  }
}

// 5. Example Modern JavaScript File (src/app.js)
import { Database } from './database.js';
import { AuthService } from './auth.js';
import { User } from './types.js';
import './styles.css';

class App {
  #db;
  #auth;
  #currentUser = null;

  constructor() {
    this.#db = new Database();
    this.#auth = new AuthService();
    this.init();
  }

  async init() {
    try {
      await this.#db.connect();
      this.setupEventListeners();
      await this.checkAuthStatus();
      console.log('✅ App initialized successfully');
    } catch (error) {
      console.error('❌ App initialization failed:', error);
    }
  }

  setupEventListeners() {
    const form = document.querySelector('#login-form');

    form?.addEventListener('submit', async (event) => {
      event.preventDefault();
      await this.handleLogin(event);
    });

    document.querySelector('#logout-btn')?.addEventListener('click', () => {
      this.handleLogout();
    });
  }

  async handleLogin(event) {
    const formData = new FormData(event.target);
    const email = formData.get('email');
    const password = formData.get('password');

    if (!email || !password) {
      this.showError('Please fill in all fields');
      return;
    }

    try {
      const user = await this.#auth.login(email, password);
      this.#currentUser = user;
      this.updateUI();
      this.showSuccess('Login successful');
    } catch (error) {
      this.showError(error.message);
    }
  }

  async handleLogout() {
    try {
      await this.#auth.logout();
      this.#currentUser = null;
      this.updateUI();
      this.showSuccess('Logged out successfully');
    } catch (error) {
      this.showError('Logout failed:', error.message);
    }
  }

  async checkAuthStatus() {
    try {
      const user = await this.#auth.getCurrentUser();
      if (user) {
        this.#currentUser = user;
        this.updateUI();
      }
    } catch (error) {
      console.warn('Auth status check failed:', error.message);
    }
  }

  updateUI() {
    const authSection = document.querySelector('#auth-section');
    const userSection = document.querySelector('#user-section');

    if (this.#currentUser) {
      authSection?.classList.add('hidden');
      userSection?.classList.remove('hidden');

      const userName = document.querySelector('#user-name');
      if (userName) {
        userName.textContent = this.#currentUser.name;
      }
    } else {
      authSection?.classList.remove('hidden');
      userSection?.classList.add('hidden');
    }
  }

  showSuccess(message) {
    this.showNotification(message, 'success');
  }

  showError(message) {
    this.showNotification(message, 'error');
  }

  showNotification(message, type = 'info') {
    const notification = document.createElement('div');
    notification.className = `notification ${type}`;
    notification.textContent = message;

    document.body.appendChild(notification);

    setTimeout(() => {
      notification.remove();
    }, 3000);
  }
}

// Initialize app when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
  new App();
});

export { App };

// 6. Example TypeScript File (src/types.ts)
export interface User {
  id: string;
  email: string;
  name: string;
  avatar?: string;
  role: 'admin' | 'user' | 'moderator';
  createdAt: Date;
  updatedAt: Date;
}

export interface AuthResponse {
  user: User;
  token: string;
  refreshToken: string;
}

export interface LoginCredentials {
  email: string;
  password: string;
}

export interface DatabaseConfig {
  host: string;
  port: number;
  database: string;
  username: string;
  password: string;
}

export interface ApiResponse<T = unknown> {
  data: T;
  message: string;
  success: boolean;
  errors?: string[];
}

// Example generic API wrapper
export class ApiClient {
  private baseUrl: string;
  private apiKey?: string;

  constructor(baseUrl: string, apiKey?: string) {
    this.baseUrl = baseUrl;
    this.apiKey = apiKey;
  }

  private async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<ApiResponse<T>> {
    const url = `${this.baseUrl}${endpoint}`;

    const headers = {
      'Content-Type': 'application/json',
      ...(this.apiKey && { Authorization: `Bearer ${this.apiKey}` }),
      ...options.headers,
    };

    try {
      const response = await fetch(url, {
        ...options,
        headers,
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      return data;
    } catch (error) {
      throw new Error(`API request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  async get<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>(endpoint, { method: 'GET' });
  }

  async post<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>(endpoint, {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  async put<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>(endpoint, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>(endpoint, { method: 'DELETE' });
  }
}

// 7. Example Utility File (src/utils.js)
export const debounce = (callback, wait) => {
  let timeoutId = null;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => callback(...args), wait);
  };
};

export const throttle = (callback, limit) => {
  let waiting = false;
  return (...args) => {
    if (!waiting) {
      callback(...args);
      waiting = true;
      setTimeout(() => (waiting = false), limit);
    }
  };
};

export const formatCurrency = (amount, currency = 'USD', locale = 'en-US') => {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
  }).format(amount);
};

export const formatDate = (date, locale = 'en-US') => {
  return new Intl.DateTimeFormat(locale, {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  }).format(date);
};

export const generateId = () => {
  return Date.now().toString(36) + Math.random().toString(36).substr(2);
};

export const validateEmail = (email) => {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
};

export const validatePassword = (password) => {
  return {
    minLength: password.length >= 8,
    hasUpperCase: /[A-Z]/.test(password),
    hasLowerCase: /[a-z]/.test(password),
    hasNumbers: /\d/.test(password),
    hasSpecialChar: /[!@#$%^&*(),.?":{}|<>]/.test(password),
  };
};

export const copyToClipboard = async (text) => {
  try {
    await navigator.clipboard.writeText(text);
    return true;
  } catch (error) {
    // Fallback for older browsers
    const textArea = document.createElement('textarea');
    textArea.value = text;
    textArea.style.position = 'fixed';
    textArea.style.opacity = '0';
    document.body.appendChild(textArea);
    textArea.select();
    const success = document.execCommand('copy');
    textArea.remove();
    return success;
  }
};

// 8. Example CSS File (src/styles.css)
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --success-color: #28a745;
  --danger-color: #dc3545;
  --warning-color: #ffc107;
  --info-color: #17a2b8;
  --light-color: #f8f9fa;
  --dark-color: #343a40;

  --font-family-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-family-mono: 'SF Mono', Monaco, 'Inconsolata', 'Roboto Mono', monospace;

  --border-radius: 4px;
  --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  --transition: all 0.3s ease;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-family-sans);
  line-height: 1.6;
  color: var(--dark-color);
  background-color: var(--light-color);
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
}

.form-group {
  margin-bottom: 1rem;
}

.form-label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 600;
  color: var(--dark-color);
}

.form-input {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid #ced4da;
  border-radius: var(--border-radius);
  font-size: 1rem;
  transition: var(--transition);
}

.form-input:focus {
  outline: none;
  border-color: var(--primary-color);
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}

.btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: var(--border-radius);
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: var(--transition);
}

.btn--primary {
  background-color: var(--primary-color);
  color: white;
}

.btn--primary:hover {
  background-color: #0056b3;
}

.btn--secondary {
  background-color: var(--secondary-color);
  color: white;
}

.btn--danger {
  background-color: var(--danger-color);
  color: white;
}

.hidden {
  display: none !important;
}

.notification {
  position: fixed;
  top: 1rem;
  right: 1rem;
  padding: 1rem;
  border-radius: var(--border-radius);
  color: white;
  z-index: 1000;
  animation: slideIn 0.3s ease;
}

.notification--success {
  background-color: var(--success-color);
}

.notification--error {
  background-color: var(--danger-color);
}

.notification--info {
  background-color: var(--info-color);
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

// 9. Biome Ignore File (.biomeignore)
# Dependencies
node_modules/

# Build outputs
dist/
build/
out/
coverage/

# Environment files
.env
.env.local
.env.*.local

# IDE files
.vscode/
.idea/
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Temporary folders
tmp/
temp/

# Package manager files
package-lock.json
yarn.lock
pnpm-lock.yaml

# Generated files
*.generated.*
*.d.ts

# Third-party
vendor/
third-party/

// 10. Example Test File (tests/app.test.js)
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { App } from '../src/app.js';

// Mock DOM APIs
global.document = {
  querySelector: vi.fn(),
  createElement: vi.fn(() => ({
    addEventListener: vi.fn(),
    classList: { add: vi.fn(), remove: vi.fn() },
    textContent: '',
    appendChild: vi.fn(),
    remove: vi.fn()
  })),
  body: { appendChild: vi.fn() }
};

global.addEventListener = vi.fn();

describe('App', () => {
  let app;

  beforeEach(() => {
    vi.clearAllMocks();
    app = new App();
  });

  it('should initialize successfully', () => {
    expect(app).toBeDefined();
  });

  it('should show error for empty login fields', async () => {
    const mockEvent = {
      preventDefault: vi.fn(),
      target: {
        get: vi.fn((name) => {
          if (name === 'email') return '';
          if (name === 'password') return '';
          return null;
        })
      }
    };

    await app.handleLogin(mockEvent);

    expect(mockEvent.preventDefault).toHaveBeenCalled();
    // Add more assertions based on your showError implementation
  });

  it('should handle successful logout', async () => {
    await app.handleLogout();
    // Add assertions based on your logout implementation
  });
});

// 11. Project Structure
my-biome-project/
├── src/
│   ├── app.js
│   ├── database.js
│   ├── auth.js
│   ├── types.ts
│   ├── utils.js
│   └── styles.css
├── tests/
│   ├── app.test.js
│   └── utils.test.js
├── public/
│   └── index.html
├── biome.json
├── .biomeignore
├── package.json
├── vitest.config.js
└── README.md

// 12. Modern HTML File (public/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Biome Example App</title>
    <meta name="description" content="Modern JavaScript app with Biome toolchain">
    <link rel="stylesheet" href="../src/styles.css">
</head>
<body>
    <div class="container">
        <header class="header">
            <h1>Biome Example App</h1>
        </header>

        <main class="main">
            <section id="auth-section">
                <form id="login-form" class="form">
                    <h2>Login</h2>
                    <div class="form-group">
                        <label for="email" class="form-label">Email</label>
                        <input
                            type="email"
                            id="email"
                            name="email"
                            class="form-input"
                            placeholder="Enter your email"
                            required
                        >
                    </div>
                    <div class="form-group">
                        <label for="password" class="form-label">Password</label>
                        <input
                            type="password"
                            id="password"
                            name="password"
                            class="form-input"
                            placeholder="Enter your password"
                            required
                        >
                    </div>
                    <button type="submit" class="btn btn--primary">
                        Login
                    </button>
                </form>
            </section>

            <section id="user-section" class="hidden">
                <h2>Welcome back!</h2>
                <p>Signed in as: <span id="user-name"></span></p>
                <button id="logout-btn" class="btn btn--secondary">
                    Logout
                </button>
            </section>
        </main>
    </div>

    <script type="module" src="../src/app.js"></script>
</body>
</html>

// 13. Biome CLI Commands Usage
/*
# Check files for linting and formatting issues
npx @biomejs/biome check

# Auto-fix linting issues (safe fixes only)
npx @biomejs/biome check --apply

# Auto-fix linting issues (including unsafe fixes)
npx @biomejs/biome check --apply-unsafe

# Format files
npx @biomejs/biome format

# Format and write changes to files
npx @biomejs/biome format --write

# Run CI checks (fails if any issues found)
npx @biomejs/biome ci

# Check specific file or directory
npx @biomejs/biome check src/
npx @biomejs/biome check src/app.js

# Format specific file
npx @biomejs/biome format src/utils.js

# Organize imports only
npx @biomejs/biome check --write --only=source.organizeImports

# Generate configuration file
npx @biomejs/biome init

# Show Biome version
npx @biomejs/biome --version

# Get help
npx @biomejs/biome --help
npx @biomejs/biome check --help
*/

export { App };

💻 Configuration Avancée Biome json

🟡 intermediate ⭐⭐⭐⭐

Configuration avancée de Biome incluant règles personnalisées, optimisation de performance, gestion de workspace et collaboration d'équipe

⏱️ 45 min 🏷️ biome, advanced, configuration, performance
Prerequisites: Biome basics, JavaScript/TypeScript, Monorepo concepts, CI/CD
// Biome Advanced Configuration Examples
// Advanced configuration patterns for complex projects and teams

// 1. Advanced biome.json Configuration
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,

      // Complexity rules
      "complexity": {
        "noExtraBooleanCast": "error",
        "noMultipleSpacesInRegularExpressionLiterals": "error",
        "noUselessCatch": "error",
        "noWith": "error",
        "noExcessiveCognitiveComplexity": {
          "level": "warn",
          "options": {
            "max": 15
          }
        }
      },

      // Correctness rules
      "correctness": {
        "noUnusedVariables": "error",
        "noUndeclaredVariables": "error",
        "noUnreachable": "error",
        "noUnreachableSuper": "error",
        "noConstantCondition": "warn",
        "noUnusedLabels": "error",
        "noUndeclaredVariables": "error",
        "noSelfAssign": "error",
        "noSetterReturn": "error",
        "noInvalidConstructorSuper": "error"
      },

      // Security rules
      "security": {
        "noDangerouslySetInnerHtml": "error",
        "noGlobalEval": "error",
        "noImpliedEval": "error"
      },

      // Style rules
      "style": {
        "noNegationElse": "error",
        "useShorthandArrayType": "error",
        "useTemplate": "error",
        "useImportType": "error",
        "useExportType": "error",
        "noVar": "error",
        "useConst": "error",
        "useCollapsedElseIf": "error",
        "noArguments": "error",
        "useArrowFunction": "error",
        "useNumericLiterals": "error",
        "useWhile": "error",
        "useYield": "error",
        "useSimplifiedLogicExpression": "error",
        "noCommaOperator": "error"
      },

      // Suspicious rules
      "suspicious": {
        "noArrayIndexKey": "warn",
        "noAsyncPromiseExecutor": "error",
        "noCatchAssign": "error",
        "noClassAssign": "error",
        "noCompareNegZero": "error",
        "noControlCharactersInRegex": "error",
        "noDebugger": "error",
        "noDuplicateCase": "error",
        "noDuplicateClassMembers": "error",
        "noDuplicateObjectKeys": "error",
        "noDuplicateParameters": "error",
        "noEmptyBlockStatements": "error",
        "noExplicitAny": "warn",
        "noFallthroughSwitchClause": "error",
        "noFunctionAssign": "error",
        "noGlobalObjectCalls": "error",
        "noImportAssign": "error",
        "noMisleadingCharacterClass": "error",
        "noPrototypeBuiltins": "error",
        "noRedeclare": "error",
        "noShadowRestrictedNames": "error",
        "noUnsafeNegation": "error",
        "useAwait": "error",
        "useGetterReturn": "error",
        "useValidTypeof": "error",
        "noHookUseState": "error",
        "noReactSpecificProps": "error"
      },

      // Nursery rules (experimental)
      "nursery": {
        "useSortedClasses": "error",
        "noUndeclaredDependencies": "warn",
        "noUselessRename": "error",
        "useIsNan": "error",
        "noImportSideEffects": "error",
        "noStaticOnlyClass": "error",
        "useAtIndexInsteadOfForEach": "error",
        "noDuplicateElseIf": "error",
        "noSelfImport": "error",
        "useLiteralEnumMembers": "error",
        "useLiteralKeys": "error",
        "noUnnecessaryContinue": "error",
        "noUselessRename": "error",
        "noLabelVar": "error",
        "noEmptyCharacterClassInRegex": "error",
        "noInvalidConstructorSuper": "error",
        "useConsistentArrayType": "error",
        "useDefaultParameterLast": "error",
        "useExponentiationOperator": "error",
        "useFocusReturnInteractive": "error",
        "useForOf": "error",
        "useImportExtensions": "error",
        "useNodeAssertStrict": "error",
        "useNumberToFixedDigitsArgument": "error",
        "useOptionalChain": "error",
        "useRegexLiterals": "error",
        "useShorthandAssign": "error",
        "useThrowNewError": "error",
        "useUndeclaredVariables": "error",
        "noRestrictedGlobals": "error",
        "noUnnecessaryContinue": "error",
        "noMimeSniff": "error"
      }
    }
  },
  "formatter": {
    "enabled": true,
    "formatWithErrors": false,
    "indentStyle": "space",
    "indentSize": 2,
    "lineWidth": 100,
    "lineEnding": "lf",
    "quoteStyle": "single",
    "jsxQuoteStyle": "double",
    "attributePosition": "auto",
    "bracketSpacing": true,
    "bracketSameLine": false,
    "arrowParentheses": "asNeeded",
    "semicolons": "asNeeded",
    "trailingComma": "es5",
    "quoteProperties": "preserve",
    "ignore": ["src/generated/**", "**/*.min.js", "dist/**"]
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "jsxQuoteStyle": "double",
      "quoteProperties": "preserve",
      "trailingComma": "es5",
      "semicolons": "asNeeded",
      "arrowParentheses": "asNeeded",
      "bracketSpacing": true,
      "bracketSameLine": false,
      "attributePosition": "auto"
    },
    "globals": [
      "window",
      "document",
      "console",
      "process",
      "Buffer",
      "global",
      "setImmediate",
      "clearImmediate"
    ]
  },
  "typescript": {
    "formatter": {
      "quoteStyle": "single",
      "jsxQuoteStyle": "double",
      "quoteProperties": "preserve",
      "trailingComma": "es5",
      "semicolons": "asNeeded",
      "arrowParentheses": "asNeeded",
      "bracketSpacing": true,
      "bracketSameLine": false,
      "attributePosition": "auto"
    },
    "globals": []
  },
  "json": {
    "formatter": {
      "enabled": true,
      "indentSize": 2,
      "lineWidth": 100,
      "trailingComma": "none"
    }
  },
  "css": {
    "formatter": {
      "enabled": true,
      "indentSize": 2,
      "lineWidth": 120,
      "quoteStyle": "double"
    },
    "linter": {
      "enabled": true,
      "rules": {
        "cssValueNoUnknown": "error",
        "noDuplicateProperties": "error",
        "noEmptyBlockStatements": "error"
      }
    }
  },
  "files": {
    "ignore": [
      "node_modules/**",
      "dist/**",
      "build/**",
      "coverage/**",
      "*.min.js",
      "*.min.css",
      ".next/**",
      ".nuxt/**",
      ".vite/**",
      ".turbo/**",
      "src/generated/**",
      "vendor/**",
      "third-party/**",
      "**/*.bundle.js",
      "**/*.d.ts"
    ],
    "ignoreUnknown": true,
    "include": ["src/**/*", "tests/**/*"],
    "maxSize": 1000000
  }
}

// 2. Monorepo Workspace Configuration
// biome.json (Root)
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "workspace": {
    "enabled": true
  },
  "files": {
    "ignore": [
      "node_modules/**",
      "dist/**",
      "build/**",
      "*.d.ts"
    ]
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  }
}

// packages/frontend/biome.json
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "extends": "../../biome.json",
  "linter": {
    "rules": {
      "style": {
        "useConst": "warn"
      },
      "suspicious": {
        "noConsoleLog": "off"
      }
    }
  },
  "javascript": {
    "globals": [
      "window",
      "document",
      "console",
      "localStorage",
      "sessionStorage",
      "fetch",
      "URLSearchParams"
    ]
  },
  "css": {
    "formatter": {
      "enabled": true,
      "indentSize": 2
    }
  }
}

// packages/backend/biome.json
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "extends": "../../biome.json",
  "linter": {
    "rules": {
      "suspicious": {
        "noConsoleLog": "error"
      },
      "security": {
        "noDangerouslySetInnerHtml": "error"
      }
    }
  },
  "javascript": {
    "globals": [
      "process",
      "Buffer",
      "console",
      "global",
      "__dirname",
      "__filename",
      "module",
      "exports",
      "require"
    ]
  },
  "typescript": {
    "globals": [
      "process",
      "Buffer",
      "global",
      "__dirname",
      "__filename"
    ]
  }
}

// 3. Environment-Specific Configurations
// biome.production.json
{
  "linter": {
    "rules": {
      "suspicious": {
        "noConsoleLog": "error",
        "noDebugger": "error"
      },
      "correctness": {
        "noUnusedVariables": "error"
      }
    }
  },
  "formatter": {
    "lineWidth": 80
  }
}

// biome.development.json
{
  "linter": {
    "rules": {
      "suspicious": {
        "noConsoleLog": "off",
        "noDebugger": "off"
      },
      "correctness": {
        "noUnusedVariables": "warn"
      }
    }
  },
  "formatter": {
    "lineWidth": 120
  }
}

// 4. Performance-Optimized Configuration
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": false,
      "style": {
        "useConst": "error",
        "noVar": "error"
      },
      "correctness": {
        "noUnusedVariables": "error",
        "noUndeclaredVariables": "error"
      }
    }
  },
  "formatter": {
    "enabled": true,
    "lineWidth": 100
  },
  "files": {
    "maxSize": 1000000,
    "ignoreUnknown": true,
    "ignore": [
      "node_modules/**",
      "dist/**",
      "build/**",
      "*.min.js",
      "large-files/**",
      "coverage/**"
    ]
  }
}

// 5. Custom Rules Configuration
{
  "linter": {
    "enabled": true,
    "rules": {
      "suspicious": {
        "noExplicitAny": {
          "level": "warn",
          "options": {
            "fixToUnknown": false
          }
        }
      },
      "complexity": {
        "noExcessiveCognitiveComplexity": {
          "level": "warn",
          "options": {
            "max": 10,
            "ignoreSimpleControlFlow": true
          }
        }
      },
      "style": {
        "useNamingConvention": {
          "level": "error",
          "options": {
            "strictCase": false
          }
        }
      }
    }
  }
}

// 6. Language-Specific Overrides
{
  "overrides": [
    {
      "include": ["**/*.test.js", "**/*.test.ts", "**/*.spec.js", "**/*.spec.ts"],
      "linter": {
        "rules": {
          "suspicious": {
            "noExplicitAny": "off"
          },
          "style": {
            "useConst": "off"
          }
        }
      }
    },
    {
      "include": ["**/*.config.js", "**/*.config.ts"],
      "linter": {
        "rules": {
          "security": {
            "noGlobalEval": "off"
          }
        }
      }
    },
    {
      "include": ["**/stories/**/*", "**/.storybook/**/*"],
      "linter": {
        "rules": {
          "suspicious": {
            "noConsoleLog": "off"
          }
        }
      }
    },
    {
      "include": ["**/*.d.ts"],
      "linter": {
        "enabled": false
      }
    }
  ]
}

// 7. Custom Presets
// biome.presets.json
{
  "strict": {
    "linter": {
      "rules": {
        "recommended": true,
        "suspicious": {
          "noExplicitAny": "error"
        },
        "style": {
          "useNamingConvention": "error"
        }
      }
    }
  },
  "lenient": {
    "linter": {
      "rules": {
        "recommended": true,
        "suspicious": {
          "noExplicitAny": "off"
        },
        "style": {
          "useNamingConvention": "off"
        }
      }
    }
  },
  "react": {
    "linter": {
      "rules": {
        "recommended": true,
        "suspicious": {
          "noReactSpecificProps": "error",
          "noHookUseState": "error"
        }
      }
    },
    "javascript": {
      "globals": ["React", "JSX"]
    }
  }
}

// 8. CI/CD Integration Configuration
// .github/workflows/biome.yml
name: Biome CI

on: [push, pull_request]

jobs:
  biome:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18, 20]

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run Biome check
        run: npx @biomejs/biome ci

      - name: Check formatting
        run: npx @biomejs/biome format --write

  biome-performance:
    name: Biome Performance
    runs-on: ubuntu-latest
    needs: biome

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Measure Biome performance
        run: |
          echo "📊 Measuring Biome performance..."
          time npx @biomejs/biome check src/
          time npx @biomejs/biome format src/

// 9. Pre-commit Hooks
// package.json
{
  "scripts": {
    "lint": "biome check",
    "lint:fix": "biome check --apply",
    "format": "biome format",
    "format:write": "biome format --write",
    "ci": "biome ci",
    "prepare": "husky install"
  },
  "devDependencies": {
    "@biomejs/biome": "^1.9.4",
    "husky": "^8.0.3",
    "lint-staged": "^13.2.0"
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx,json,css}": [
      "biome check --apply",
      "biome format --write"
    ]
  }
}

// 10. Advanced Project Configuration Scripts
// scripts/setup-biome.js
import { execSync } from 'child_process';
import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';

class BiomeSetup {
  constructor(projectPath = process.cwd()) {
    this.projectPath = projectPath;
  }

  async setup() {
    console.log('🚀 Setting up Biome for the project...');

    try {
      await this.installBiome();
      await this.initializeConfig();
      await this.setupScripts();
      await this.setupGitHooks();
      await this.createBiomeignore();

      console.log('✅ Biome setup completed successfully!');
    } catch (error) {
      console.error('❌ Biome setup failed:', error.message);
      process.exit(1);
    }
  }

  async installBiome() {
    console.log('📦 Installing Biome...');
    execSync('npm install --save-dev @biomejs/biome', { stdio: 'inherit' });
  }

  async initializeConfig() {
    console.log('⚙️ Initializing Biome configuration...');
    execSync('npx @biomejs/biome init', { stdio: 'inherit' });
  }

  async setupScripts() {
    console.log('📝 Setting up npm scripts...');

    const packageJsonPath = join(this.projectPath, 'package.json');
    const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));

    packageJson.scripts = {
      ...packageJson.scripts,
      lint: 'biome check',
      'lint:fix': 'biome check --apply',
      'lint:unsafe': 'biome check --apply-unsafe',
      format: 'biome format',
      'format:write': 'biome format --write',
      ci: 'biome ci',
      'organize-imports': 'biome check --write --only=source.organizeImports'
    };

    writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
  }

  async setupGitHooks() {
    console.log('🪝 Setting up Git hooks...');

    try {
      execSync('npm install --save-dev husky lint-staged', { stdio: 'inherit' });
      execSync('npm pkg set scripts.prepare="husky install"', { stdio: 'inherit' });
      execSync('echo "npx husky install" | npm run prepare', { stdio: 'inherit' });

      const huskyConfig = {
        '.husky/pre-commit': 'npx lint-staged'
      };

      for (const [hook, command] of Object.entries(huskyConfig)) {
        const hookPath = join(this.projectPath, hook);
        execSync(`echo '${command}' > ${hookPath}`, { stdio: 'inherit' });
        execSync(`chmod +x ${hookPath}`, { stdio: 'inherit' });
      }
    } catch (error) {
      console.warn('⚠️ Git hooks setup failed:', error.message);
    }
  }

  async createBiomeignore() {
    console.log('🚫 Creating .biomeignore file...');

    const biomeignoreContent = `
# Dependencies
node_modules/

# Build outputs
dist/
build/
out/
coverage/

# Environment files
.env
.env.local
.env.*.local

# IDE files
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Logs
*.log

# Generated files
*.d.ts
*.generated.*
    `.trim();

    const biomeignorePath = join(this.projectPath, '.biomeignore');
    writeFileSync(biomeignorePath, biomeignoreContent);
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const setup = new BiomeSetup();
  setup.setup();
}

export { BiomeSetup };

// 11. Performance Monitoring
// scripts/biome-performance.js
import { performance } from 'perf_hooks';
import { execSync } from 'child_process';

class BiomePerformanceMonitor {
  constructor() {
    this.files = [];
  }

  measurePerformance() {
    console.log('📊 Measuring Biome performance...');

    // Discover files
    this.discoverFiles();

    // Measure formatting performance
    const formatStart = performance.now();
    this.runFormat();
    const formatEnd = performance.now();

    // Measure linting performance
    const lintStart = performance.now();
    this.runLint();
    const lintEnd = performance.now();

    const formatTime = formatEnd - formatStart;
    const lintTime = lintEnd - lintStart;

    this.displayResults({
      formatTime,
      lintTime,
      totalTime: formatTime + lintTime,
      fileCount: this.files.length
    });

    return {
      formatTime,
      lintTime,
      totalTime: formatTime + lintTime,
      fileCount: this.files.length
    };
  }

  discoverFiles() {
    try {
      const result = execSync('find src -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx"', { encoding: 'utf8' });
      this.files = result.trim().split('\n').filter(Boolean);
    } catch (error) {
      console.warn('Could not discover files:', error.message);
    }
  }

  runFormat() {
    if (this.files.length > 0) {
      execSync(`npx @biomejs/biome format ${this.files.join(' ')}`, { stdio: 'pipe' });
    }
  }

  runLint() {
    if (this.files.length > 0) {
      execSync(`npx @biomejs/biome check ${this.files.join(' ')}`, { stdio: 'pipe' });
    }
  }

  displayResults(results) {
    console.log('\n📈 Performance Results:');
    console.log(`   Files processed: ${results.fileCount}`);
    console.log(`   Formatting: ${results.formatTime.toFixed(2)}ms`);
    console.log(`   Linting: ${results.lintTime.toFixed(2)}ms`);
    console.log(`   Total: ${results.totalTime.toFixed(2)}ms`);
    console.log(`   Avg per file: ${(results.totalTime / results.fileCount).toFixed(2)}ms`);
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const monitor = new BiomePerformanceMonitor();
  monitor.measurePerformance();
}

export { BiomePerformanceMonitor };

💻 Guide de Migration Biome javascript

🔴 complex ⭐⭐⭐⭐⭐

Guide complet de migration d'ESLint/Prettier/Rome vers Biome avec scripts d'automatisation et meilleures pratiques

⏱️ 90 min 🏷️ biome, migration, automation, advanced
Prerequisites: Advanced JavaScript/TypeScript, CLI usage, Build tools, Package managers
// Biome Migration Guide
// Complete migration from ESLint/Prettier/Rome to Biome

// 1. Migration Assessment Script
// scripts/assess-migration.js
import { readFileSync, existsSync, writeFileSync } from 'fs';
import { execSync } from 'child_process';
import { join } from 'path';

class MigrationAssessment {
  constructor(projectPath = process.cwd()) {
    this.projectPath = projectPath;
  }

  assess() {
    console.log('🔍 Assessing project for Biome migration...');

    const assessment = {
      hasEslint: this.checkESLint(),
      hasPrettier: this.checkPrettier(),
      hasRome: this.checkRome(),
      hasTypeScript: this.checkTypeScript(),
      framework: this.detectFramework(),
      dependencies: this.analyzeDependencies(),
      complexity: this.assessComplexity(),
      migrationComplexity: 'moderate',
      recommendations: []
    };

    this.generateRecommendations(assessment);
    this.displayReport(assessment);

    return assessment;
  }

  checkESLint() {
    const files = [
      '.eslintrc.js',
      '.eslintrc.json',
      '.eslintrc.yml',
      '.eslintrc.yaml',
      'eslint.config.js'
    ];

    return files.some(file => existsSync(join(this.projectPath, file)));
  }

  checkPrettier() {
    const files = [
      '.prettierrc',
      '.prettierrc.json',
      '.prettierrc.yml',
      '.prettierrc.yaml',
      'prettier.config.js'
    ];

    return files.some(file => existsSync(join(this.projectPath, file)));
  }

  checkRome() {
    const files = [
      'rome.json',
      '.romerc'
    ];

    return files.some(file => existsSync(join(this.projectPath, file)));
  }

  checkTypeScript() {
    return existsSync(join(this.projectPath, 'tsconfig.json'));
  }

  detectFramework() {
    const packageJson = this.readPackageJson();
    const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };

    if (deps.next) return 'nextjs';
    if (deps.react) return 'react';
    if (deps.vue) return 'vue';
    if (deps['@angular/core']) return 'angular';
    if (deps.svelte) return 'svelte';

    return 'vanilla';
  }

  analyzeDependencies() {
    const packageJson = this.readPackageJson();
    const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };

    const lintingDeps = Object.keys(deps).filter(dep =>
      dep.includes('eslint') ||
      dep.includes('prettier') ||
      dep.includes('rome')
    );

    return {
      lintingDeps,
      totalDeps: Object.keys(deps).length,
      hasLintingDeps: lintingDeps.length > 0
    };
  }

  assessComplexity() {
    let score = 0;

    // Check for configuration files
    if (this.checkESLint()) score += 3;
    if (this.checkPrettier()) score += 2;
    if (this.checkRome()) score += 1;

    // Check TypeScript
    if (this.checkTypeScript()) score += 2;

    // Check dependencies
    const { lintingDeps } = this.analyzeDependencies();
    if (lintingDeps.length > 5) score += 2;
    if (lintingDeps.length > 10) score += 1;

    if (score <= 3) return 'simple';
    if (score <= 7) return 'medium';
    return 'complex';
  }

  generateRecommendations(assessment) {
    const recommendations = [];

    if (assessment.hasRome) {
      recommendations.push('✅ You already use Rome! Migration to Biome will be seamless');
      recommendations.push('🔄 Simply replace @romejs/biome with @biomejs/biome');
    } else {
      recommendations.push('🚀 Biome provides better performance and unified tooling');
    }

    if (assessment.hasESLint && assessment.hasPrettier) {
      recommendations.push('🎯 Biome can replace both ESLint and Prettier with a single tool');
      recommendations.push('⚡ Expect 10-100x faster formatting and linting');
    }

    if (assessment.framework === 'nextjs') {
      recommendations.push('📦 Next.js has built-in Biome support in recent versions');
    }

    if (assessment.complexity === 'complex') {
      recommendations.push('🔧 Consider migrating in stages for complex projects');
      recommendations.push('📋 Document your current linting rules before migration');
    }

    recommendations.push('🧪 Test thoroughly after migration');
    recommendations.push('👥 Involve your team in the migration process');

    assessment.recommendations = recommendations;
  }

  displayReport(assessment) {
    console.log('\n📊 Migration Assessment Report\n');
    console.log(`🔧 ESLint: ${assessment.hasEslint ? '✅' : '❌'}`);
    console.log(`🎨 Prettier: ${assessment.hasPrettier ? '✅' : '❌'}`);
    console.log(`🦀 Rome: ${assessment.hasRome ? '✅' : '❌'}`);
    console.log(`📘 TypeScript: ${assessment.hasTypeScript ? '✅' : '❌'}`);
    console.log(`🎯 Framework: ${assessment.framework}`);
    console.log(`📊 Complexity: ${assessment.complexity}`);
    console.log(`📦 Linting dependencies: ${assessment.dependencies.lintingDeps.length}\n`);

    console.log('💡 Recommendations:');
    assessment.recommendations.forEach(rec => {
      console.log(`  ${rec}`);
    });
  }

  readPackageJson() {
    const packageJsonPath = join(this.projectPath, 'package.json');
    return JSON.parse(readFileSync(packageJsonPath, 'utf8'));
  }
}

// 2. ESLint to Biome Migration
// scripts/migrate-eslint.js
class ESLintToBiomeMigrator {
  constructor(projectPath = process.cwd()) {
    this.projectPath = projectPath;
  }

  migrate() {
    console.log('🔄 Migrating from ESLint to Biome...');

    const eslintConfig = this.loadESLintConfig();
    const prettierConfig = this.loadPrettierConfig();

    const biomeConfig = this.convertToBiomeConfig(eslintConfig, prettierConfig);

    this.writeBiomeConfig(biomeConfig);
    this.updatePackageJson();
    this.removeOldConfig();
    this.installBiome();

    console.log('✅ ESLint to Biome migration completed!');
  }

  loadESLintConfig() {
    const possibleConfigs = [
      'eslint.config.js',
      '.eslintrc.js',
      '.eslintrc.json',
      '.eslintrc.yml',
      '.eslintrc.yaml'
    ];

    for (const configFile of possibleConfigs) {
      const configPath = join(this.projectPath, configFile);
      if (existsSync(configPath)) {
        try {
          return require(configPath);
        } catch (error) {
          console.warn(`Could not load ${configFile}:`, error.message);
        }
      }
    }

    return null;
  }

  loadPrettierConfig() {
    const possibleConfigs = [
      'prettier.config.js',
      '.prettierrc',
      '.prettierrc.json',
      '.prettierrc.yml',
      '.prettierrc.yaml'
    ];

    for (const configFile of possibleConfigs) {
      const configPath = join(this.projectPath, configFile);
      if (existsSync(configPath)) {
        try {
          if (configFile.endsWith('.js')) {
            return require(configPath);
          } else {
            return JSON.parse(readFileSync(configPath, 'utf8'));
          }
        } catch (error) {
          console.warn(`Could not load ${configFile}:`, error.message);
        }
      }
    }

    return null;
  }

  convertToBiomeConfig(eslintConfig, prettierConfig) {
    const biomeConfig = {
      $schema: "https://biomejs.dev/schemas/1.9.4/schema.json",
      linter: {
        enabled: true,
        rules: {
          recommended: true
        }
      },
      formatter: {
        enabled: true,
        formatWithErrors: false
      },
      javascript: {
        globals: []
      },
      files: {
        ignore: [
          "node_modules/**",
          "dist/**",
          "build/**"
        ]
      }
    };

    // Convert ESLint rules to Biome rules
    if (eslintConfig && eslintConfig.rules) {
      biomeConfig.linter.rules = this.convertRules(eslintConfig.rules);
    }

    // Convert Prettier config to Biome formatter config
    if (prettierConfig) {
      biomeConfig.formatter = {
        ...biomeConfig.formatter,
        ...this.convertPrettierConfig(prettierConfig)
      };
    }

    return biomeConfig;
  }

  convertRules(eslintRules) {
    const biomeRules = { recommended: true };

    // Rule mapping from ESLint to Biome
    const ruleMap = {
      // Style rules
      'no-var': { style: { noVar: 'error' } },
      'prefer-const': { style: { useConst: 'error' } },
      'prefer-arrow-callback': { style: { useArrowFunction: 'error' } },
      'prefer-template': { style: { useTemplate: 'error' } },
      'no-console': { suspicious: { noConsoleLog: 'error' } },
      'no-debugger': { suspicious: { noDebugger: 'error' } },
      'no-unused-vars': { correctness: { noUnusedVariables: 'error' } },
      'no-undef': { correctness: { noUndeclaredVariables: 'error' } },
      'no-duplicate-imports': { style: { noDuplicateImports: 'error' } }
    };

    for (const [eslintRule, config] of Object.entries(eslintRules)) {
      if (config === 'error' || config === 2) {
        if (ruleMap[eslintRule]) {
          this.mergeRule(biomeRules, ruleMap[eslintRule]);
        }
      } else if (config === 'warn' || config === 1) {
        if (ruleMap[eslintRule]) {
          this.mergeRule(biomeRules, ruleMap[eslintRule], 'warn');
        }
      }
    }

    return biomeRules;
  }

  mergeRule(biomeRules, rule, level = 'error') {
    for (const [category, rules] of Object.entries(rule)) {
      if (!biomeRules[category]) {
        biomeRules[category] = {};
      }
      Object.assign(biomeRules[category], rules);
    }
  }

  convertPrettierConfig(prettierConfig) {
    const formatterConfig = {};

    if (prettierConfig.tabWidth !== undefined) {
      formatterConfig.indentSize = prettierConfig.tabWidth;
    }

    if (prettierConfig.useTabs !== undefined) {
      formatterConfig.indentStyle = prettierConfig.useTabs ? 'tab' : 'space';
    }

    if (prettierConfig.printWidth !== undefined) {
      formatterConfig.lineWidth = prettierConfig.printWidth;
    }

    if (prettierConfig.singleQuote !== undefined) {
      formatterConfig.quoteStyle = prettierConfig.singleQuote ? 'single' : 'double';
    }

    if (prettierConfig.trailingComma !== undefined) {
      formatterConfig.trailingComma = prettierConfig.trailingComma;
    }

    if (prettierConfig.semi !== undefined) {
      formatterConfig.semicolons = prettierConfig.semi ? 'always' : 'asNeeded';
    }

    return formatterConfig;
  }

  writeBiomeConfig(biomeConfig) {
    const configPath = join(this.projectPath, 'biome.json');
    writeFileSync(configPath, JSON.stringify(biomeConfig, null, 2));
    console.log('⚙️ Created biome.json');
  }

  updatePackageJson() {
    const packageJsonPath = join(this.projectPath, 'package.json');
    const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));

    // Remove ESLint and Prettier dependencies
    const depsToRemove = [
      'eslint',
      '@typescript-eslint/eslint-plugin',
      '@typescript-eslint/parser',
      'eslint-config-prettier',
      'eslint-plugin-react',
      'eslint-plugin-react-hooks',
      'prettier'
    ];

    depsToRemove.forEach(dep => {
      delete packageJson.devDependencies?.[dep];
      delete packageJson.dependencies?.[dep];
    });

    // Add Biome dependency
    packageJson.devDependencies = {
      ...packageJson.devDependencies,
      '@biomejs/biome': '^1.9.4'
    };

    // Update scripts
    packageJson.scripts = {
      ...packageJson.scripts,
      lint: 'biome check',
      'lint:fix': 'biome check --apply',
      format: 'biome format',
      'format:write': 'biome format --write',
      ci: 'biome ci'
    };

    // Remove old scripts
    const oldScripts = ['eslint', 'prettier', 'eslint:fix', 'prettier:write'];
    oldScripts.forEach(script => {
      delete packageJson.scripts?.[script];
    });

    writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
    console.log('📦 Updated package.json');
  }

  removeOldConfig() {
    const oldConfigs = [
      '.eslintrc.js',
      '.eslintrc.json',
      '.eslintrc.yml',
      '.eslintrc.yaml',
      'eslint.config.js',
      '.prettierrc',
      '.prettierrc.json',
      '.prettierrc.yml',
      '.prettierrc.yaml',
      'prettier.config.js'
    ];

    oldConfigs.forEach(config => {
      const configPath = join(this.projectPath, config);
      if (existsSync(configPath)) {
        execSync(`rm "${configPath}"`, { stdio: 'pipe' });
        console.log(`🗑️ Removed ${config}`);
      }
    });
  }

  installBiome() {
    console.log('📦 Installing Biome...');
    execSync('npm install', { stdio: 'inherit' });
  }
}

// 3. Rome to Biome Migration
// scripts/migrate-rome.js
class RomeToBiomeMigrator {
  constructor(projectPath = process.cwd()) {
    this.projectPath = projectPath;
  }

  migrate() {
    console.log('🔄 Migrating from Rome to Biome...');

    const romeConfig = this.loadRomeConfig();
    const biomeConfig = this.convertRomeToBiome(romeConfig);

    this.writeBiomeConfig(biomeConfig);
    this.updatePackageJson();
    this.removeRomeConfig();
    this.installBiome();

    console.log('✅ Rome to Biome migration completed!');
  }

  loadRomeConfig() {
    const configPath = join(this.projectPath, 'rome.json');
    if (!existsSync(configPath)) {
      throw new Error('rome.json not found');
    }

    return JSON.parse(readFileSync(configPath, 'utf8'));
  }

  convertRomeToBiome(romeConfig) {
    // Most Rome configurations are compatible with Biome
    // Just need to update the schema URL and any breaking changes
    const biomeConfig = {
      ...romeConfig,
      $schema: "https://biomejs.dev/schemas/1.9.4/schema.json"
    };

    // Update any deprecated options
    if (biomeConfig.javascript) {
      biomeConfig.javascript = this.updateJavaScriptConfig(biomeConfig.javascript);
    }

    return biomeConfig;
  }

  updateJavaScriptConfig(jsConfig) {
    // Handle any breaking changes between Rome and Biome
    return {
      ...jsConfig,
      // Update any deprecated options here
    };
  }

  writeBiomeConfig(biomeConfig) {
    const configPath = join(this.projectPath, 'biome.json');
    writeFileSync(configPath, JSON.stringify(biomeConfig, null, 2));
    console.log('⚙️ Created biome.json');
  }

  updatePackageJson() {
    const packageJsonPath = join(this.projectPath, 'package.json');
    const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));

    // Remove Rome dependency
    delete packageJson.devDependencies?.['rome'];
    delete packageJson.dependencies?.['rome'];

    // Add Biome dependency
    packageJson.devDependencies = {
      ...packageJson.devDependencies,
      '@biomejs/biome': '^1.9.4'
    };

    // Update scripts to use Biome CLI
    const scriptMap = {
      'rome check': 'biome check',
      'rome check --apply': 'biome check --apply',
      'rome format': 'biome format',
      'rome format --write': 'biome format --write',
      'rome ci': 'biome ci'
    };

    for (const [oldScript, newScript] of Object.entries(scriptMap)) {
      if (packageJson.scripts?.[oldScript]) {
        packageJson.scripts[newScript] = packageJson.scripts[oldScript];
        delete packageJson.scripts[oldScript];
      }
    }

    writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
    console.log('📦 Updated package.json');
  }

  removeRomeConfig() {
    const configPath = join(this.projectPath, 'rome.json');
    if (existsSync(configPath)) {
      execSync(`rm "${configPath}"`, { stdio: 'pipe' });
      console.log('🗑️ Removed rome.json');
    }
  }

  installBiome() {
    console.log('📦 Installing Biome...');
    execSync('npm install', { stdio: 'inherit' });
  }
}

// 4. Migration Verification
// scripts/verify-migration.js
class MigrationVerifier {
  constructor(projectPath = process.cwd()) {
    this.projectPath = projectPath;
  }

  async verify() {
    console.log('🔍 Verifying migration...');

    const checks = [
      this.checkBiomeConfig(),
      this.checkPackageJson(),
      this.checkBiomeFunctionality(),
      this.checkCodeQuality()
    ];

    const results = await Promise.allSettled(checks);
    const failures = results.filter(r => r.status === 'rejected');

    if (failures.length === 0) {
      console.log('✅ All verification checks passed!');
      return true;
    } else {
      console.log(`❌ ${failures.length} verification checks failed:`);
      failures.forEach((failure, index) => {
        console.log(`  ${index + 1}. ${failure.reason}`);
      });
      return false;
    }
  }

  async checkBiomeConfig() {
    const configPath = join(this.projectPath, 'biome.json');
    if (!existsSync(configPath)) {
      throw new Error('biome.json not found');
    }

    const config = JSON.parse(readFileSync(configPath, 'utf8'));
    if (!config.linter && !config.formatter) {
      throw new Error('Invalid biome.json configuration');
    }
  }

  async checkPackageJson() {
    const packageJsonPath = join(this.projectPath, 'package.json');
    const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));

    if (!packageJson.devDependencies?.['@biomejs/biome']) {
      throw new Error('@biomejs/biome not found in dependencies');
    }

    // Check if old dependencies are removed
    const oldDeps = ['eslint', 'prettier', 'rome'];
    const hasOldDeps = oldDeps.some(dep =>
      packageJson.devDependencies?.[dep] || packageJson.dependencies?.[dep]
    );

    if (hasOldDeps) {
      console.warn('⚠️ Old linting dependencies still present');
    }
  }

  async checkBiomeFunctionality() {
    try {
      execSync('npx @biomejs/biome --version', { stdio: 'pipe' });
    } catch (error) {
      throw new Error('Biome CLI not working');
    }

    try {
      execSync('npx @biomejs/biome check --write', { stdio: 'pipe' });
      execSync('npx @biomejs/biome format --write', { stdio: 'pipe' });
    } catch (error) {
      throw new Error('Biome check/format failed');
    }
  }

  async checkCodeQuality() {
    // Run CI to check for issues
    try {
      execSync('npx @biomejs/biome ci', { stdio: 'pipe' });
    } catch (error) {
      throw new Error('Biome CI checks failed');
    }
  }
}

// 5. Usage Examples
// CLI execution
if (import.meta.url === `file://${process.argv[1]}`) {
  const args = process.argv.slice(2);
  const command = args[0];

  switch (command) {
    case 'assess':
      const assessor = new MigrationAssessment();
      assessor.assess();
      break;

    case 'eslint':
      const eslintMigrator = new ESLintToBiomeMigrator();
      eslintMigrator.migrate();
      break;

    case 'rome':
      const romeMigrator = new RomeToBiomeMigrator();
      romeMigrator.migrate();
      break;

    case 'verify':
      const verifier = new MigrationVerifier();
      verifier.verify().then(success => {
        process.exit(success ? 0 : 1);
      });
      break;

    default:
      console.log(`
Usage: npm run migrate [command]

Commands:
  assess     - Assess project migration readiness
  eslint     - Migrate from ESLint/Prettier to Biome
  rome       - Migrate from Rome to Biome
  verify     - Verify migration was successful
      `);
  }
}

export { MigrationAssessment, ESLintToBiomeMigrator, RomeToBiomeMigrator, MigrationVerifier };