npm package: @serejke/eslint-plugin-pino-enforce-static-message
Description: ESLint rule to enforce static log messages for Pino loggers
Author: Sergei Patrikeev
Latest version: 0.1.0

# @serejke/eslint-plugin-pino-enforce-static-message

ESLint rule to enforce static log messages for Pino loggers. Ensures dynamic data is passed via context objects for proper log aggregation and querying.

## Why?

Dynamic log messages break log aggregation tools:

```typescript
// BAD - Each unique userId creates a separate log entry type
logger.info(`User ${userId} logged in`);

// GOOD - All logins group under "User logged in"
logger.info({ userId }, 'User logged in');
```

## Installation

```bash
npm install --save-dev @serejke/eslint-plugin-pino-enforce-static-message
# or
pnpm add -D @serejke/eslint-plugin-pino-enforce-static-message
```

## Usage

### Flat Config (ESLint 9+)

```javascript
// eslint.config.js
import pinoEnforceStaticMessage from '@serejke/eslint-plugin-pino-enforce-static-message';

export default [
  {
    plugins: {
      '@serejke/pino-enforce-static-message': pinoEnforceStaticMessage,
    },
    rules: {
      '@serejke/pino-enforce-static-message/enforce-static-message': 'error',
    },
  },
];
```

### With Options

```javascript
rules: {
  '@serejke/pino-enforce-static-message/enforce-static-message': ['error', {
    allowInTests: true,
    testFilePatterns: ['**/*.test.ts', '**/test/**/*.ts'],
    excludeMethods: ['child', 'flush'],
  }],
}
```

## Rule: `enforce-static-message`

### What it checks

1. **Static message enforcement**: Log messages must be string literals
2. **Error key convention**: Error objects must use `err` as the key name (Pino convention)

### Valid

```typescript
// Static message only
logger.info('Server started');

// Context object + static message
logger.info({ userId, action }, 'User action recorded');

// Error with 'err' key
logger.error({ err: error, requestId }, 'Request failed');

// Child logger (exempt from checks)
const childLogger = logger.child({ module: moduleName });
```

### Invalid

```typescript
// Template literal
logger.info(`Processing ${count} items`);
// Error: Log message must be a static string literal

// String concatenation
logger.error('Failed: ' + error.message);
// Error: Log message must be a static string literal

// Wrong key for Error
logger.error({ error: e }, 'Failed');
// Error: Use 'err' as the key name for Error objects
// Auto-fixed to: logger.error({ err: e }, 'Failed');
```

## Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `allowInTests` | `boolean` | `true` | Skip rule in test files |
| `testFilePatterns` | `string[]` | `['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**/*.ts']` | Glob patterns for test files |
| `additionalMethods` | `string[]` | `[]` | Additional method names to check |
| `excludeMethods` | `string[]` | `['child']` | Method names to exclude from checking |

## Checked Methods

By default, the rule checks these Pino log methods:
- `trace()`
- `debug()`
- `info()`
- `warn()`
- `error()`
- `fatal()`

## Auto-fix

The rule provides auto-fix for the `error` → `err` key rename:

```typescript
// Before
logger.error({ error: e }, 'Failed');

// After auto-fix
logger.error({ err: e }, 'Failed');
```

## License

MIT