npm package: @geren32/nestjs-error-handler
Description: Unified error handling layer for NestJS: single response format, error codes for i18n, categories (business/validation/auth/system), safe production logging
Latest version: 1.0.0

# @softdoes/nestjs-error-handler

Unified error handling layer for NestJS: single response format, stable error codes, Prisma-aware mapping, and configurable logging.

## Features

- Single response shape: `{ success: false, error: { code, category, message?, details?, requestId? }, statusCode }`
- Error categories: `business` | `validation` | `auth` | `system`
- Common Prisma client errors mapped automatically
- Production-safe responses when `hideInternalDetails` is enabled
- Configurable logger adapter so logs can go through your app logger

## Install

```bash
npm i @softdoes/nestjs-error-handler
```

Peer dependencies: `@nestjs/common` and `@nestjs/core` `^10 || ^11`.

## Setup

```ts
import { Module } from '@nestjs/common';
import { ErrorHandlerModule } from '@softdoes/nestjs-error-handler';

import appLogger from './common/logger/logger';

@Module({
  imports: [
    ErrorHandlerModule.register({
      hideInternalDetails: true,
      includeRequestId: true,
      getRequestId: (req) => req.headers?.['x-request-id'] as string | undefined,
      logger: {
        warn: (message, payload) => appLogger.warn(message, payload),
        error: (message, payload) => appLogger.error(message, payload),
      },
    }),
  ],
})
export class AppModule {}
```

Remove any existing global exception filter so this package stays the single response formatter.

## Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `hideInternalDetails` | `boolean` | `false` | When `true`, internal messages and details are hidden from responses |
| `includeRequestId` | `boolean` | `true` | Include `error.requestId` when available |
| `getRequestId` | `(req) => string \| undefined` | `x-request-id` header | Custom request id extractor |
| `logger` | `{ warn(...), error(...) }` | Nest `Logger` fallback | Custom logger adapter |

The application should decide the value itself, for example `hideInternalDetails: config.isProduction`.

## Throwing errors

```ts
import {
  AuthError,
  BusinessError,
  ErrorCodes,
  SystemError,
  ValidationError,
} from '@softdoes/nestjs-error-handler';

throw new BusinessError(ErrorCodes.USER_NOT_FOUND, { httpStatus: 404 });
throw new ValidationError(ErrorCodes.VALIDATION_FAILED, {
  details: { field: 'email', reason: 'invalid' },
});
throw new AuthError(ErrorCodes.INVALID_CREDENTIALS);
throw new SystemError(ErrorCodes.INTERNAL_ERROR, { cause: err });
```

## Prisma errors

The package maps common Prisma errors automatically:

- `P2002` -> `UNIQUE_CONSTRAINT` (`409`)
- `P2003` -> `FOREIGN_KEY_CONSTRAINT` (`400`)
- `P2025` -> `RECORD_NOT_FOUND` (`404`)
- `P2000` -> `VALUE_TOO_LONG` (`400`)

## Response behavior

When `hideInternalDetails` is `true`, the response keeps only `code`, `category`, and optionally `requestId`. For `system` errors a generic `"Internal server error"` message is returned.

When `hideInternalDetails` is `false`, the response also includes `message` and `details` when available.

## Notes

- Use stable `code` values for frontend i18n.
- Nest built-in exceptions are normalized to the same response shape.
- Prisma support is implemented without a hard dependency on Prisma packages.