# @othree.io/excuses

A collection of typed domain error classes for TypeScript applications.

## Install

```bash
npm install @othree.io/excuses
```

## Errors

| Error | Constructor | Description |
|---|---|---|
| `CannotDeleteError` | `(id?, type?, message?)` | Entity cannot be deleted |
| `ConflictError` | `(code?, message?)` | Resource conflict (e.g. optimistic locking) |
| `DuplicateError` | `(id?, type?, message?)` | Entity already exists |
| `InvalidDateError` | `(format?, value?, message?)` | Date failed format validation |
| `NotFoundError` | `(id?, type?, message?)` | Entity not found |
| `UnauthorizedError` | `()` | Unauthorized access |
| `UnexpectedError` | `(code?, message?)` | Catch-all for unclassified errors |

## Usage

```typescript
import { NotFoundError, ConflictError } from '@othree.io/excuses'

// With id and type — generates message automatically
throw new NotFoundError('123', 'User')
// => "User with id: 123 was not found"

// With a custom message
throw new NotFoundError(undefined, undefined, 'The requested user does not exist')

// Conflict with error code
throw new ConflictError('VERSION_MISMATCH', 'Resource was modified by another request')

// Type checking
if (error instanceof NotFoundError) {
    console.log(error.id) // '123'
}

// Each error has a static ERROR identifier
NotFoundError.ERROR // 'NotFoundError'
```

## Types

The `ErrorDetails` type is exported for use with `ConflictError` and `UnexpectedError`:

```typescript
import { ErrorDetails } from '@othree.io/excuses'

type ErrorDetails = {
    readonly code?: string
    readonly message?: string
}
```

## Build

The package ships dual CJS/ESM output:

```bash
npm run build   # Produces lib/cjs/ and lib/esm/
npm test        # Vitest with 100% coverage
```

## Commit message format

This project uses [semantic-release](https://semantic-release.gitbook.io/semantic-release/) with [Angular Commit Message Conventions](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format).

| Commit message | Release type |
|---|---|
| `fix(pencil): stop graphite breaking when too much pressure applied` | Patch Release |
| `feat(pencil): add 'graphiteWidth' option` | Feature Release |
| `perf(pencil): remove graphiteWidth option`<br><br>`BREAKING CHANGE: The graphiteWidth option has been removed.` | Breaking Release |
