Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,18 @@ jobs:
run: pnpm run test:coverage
if: matrix.node-version == 20

- name: Upload coverage reports
uses: codecov/codecov-action@v4
- name: Verify coverage thresholds
run: |
echo "Coverage thresholds are enforced in vitest.config.ts:"
echo " - Statements: 90%"
echo " - Branches: 85%"
echo " - Functions: 90%"
echo " - Lines: 90%"
echo "Test will fail if thresholds are not met."
if: matrix.node-version == 20

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
if: matrix.node-version == 20 && github.ref == 'refs/heads/main'
Comment thread
bombillazo marked this conversation as resolved.
Outdated
with:
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
token: ${{ secrets.CODECOV_TOKEN }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ node_modules
.ralph-tui
AGENTS.md
dist

# Coverage
coverage/
*.lcov
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![npm downloads](https://img.shields.io/npm/dm/@bombillazo/error-x.svg?style=for-the-badge)](https://www.npmjs.com/package/@bombillazo/error-x)
[![npm](https://img.shields.io/npm/dt/@bombillazo/error-x.svg?style=for-the-badge)](https://www.npmjs.com/package/@bombillazo/error-x)
[![npm](https://img.shields.io/npm/l/@bombillazo/error-x?style=for-the-badge)](https://github.com/bombillazo/error-x/blob/master/LICENSE)
[![codecov](https://img.shields.io/codecov/c/github/bombillazo/error-x?style=for-the-badge)](https://codecov.io/gh/bombillazo/error-x)

🚨❌

Expand Down Expand Up @@ -685,6 +686,64 @@ const resolver = new ErrorXResolver<MyConfig, MyResult>({

---

## Performance

ErrorX is designed to be fast enough for production use while providing rich error handling capabilities. Here are the key performance characteristics:

### Benchmarks

Run benchmarks locally with `pnpm bench`. Results from a typical run (Apple M2):

| Operation | ops/sec | Notes |
|-----------|---------|-------|
| `new Error()` (native) | ~525k | Baseline comparison |
| `new ErrorX()` | ~38k | ~14x slower than native Error |
| `new ErrorX(options)` | ~40k | Similar to basic ErrorX |
| `ErrorX.from(ErrorX)` | ~21M | Passthrough is extremely fast |
| `ErrorX.from(Error)` | ~32k | Converts native errors |
| `toJSON()` (simple) | ~5.4M | Very fast serialization |
| `toJSON()` (with chain) | ~1.4M | Chain adds overhead |
| `fromJSON()` (simple) | ~32k | Deserialization |
| `isErrorX()` | ~21M | Near-instant type guard |
| `aggregate()` (3 errors) | ~30k | Aggregation overhead |

### Performance Characteristics

**Error Creation (~38k ops/sec)**
- Creating an ErrorX is ~14x slower than native `Error` due to stack cleaning, timestamp generation, and chain management
- Adding metadata or httpStatus has negligible impact
- Adding a cause (chaining) reduces performance by ~2x due to chain flattening

**Serialization (toJSON)**
- Simple errors: ~5.4M ops/sec (extremely fast)
- With metadata: ~346k ops/sec (JSON serialization overhead)
- With error chain: ~1.4M ops/sec (iterates chain)

**Deserialization (fromJSON)**
- ~32k ops/sec regardless of metadata
- Chain reconstruction adds ~3x overhead per chained error

**Type Guards**
- `isErrorX()` and `isAggregateErrorX()`: ~21M ops/sec (instant)
- `isErrorXOptions()`: ~15M ops/sec (object key checking)

**Memory Considerations**
- Deep chains (50+ levels) process at ~343 ops/sec for full create/serialize/deserialize cycle
- Large aggregates (100 errors) process at ~135 ops/sec
- No memory leaks detected in chain or aggregate handling

### When to Use ErrorX

ErrorX is suitable for:
- Application-level error handling (not hot loops)
- API error responses
- Error logging and monitoring
- Domain error modeling

For performance-critical code paths (>100k errors/sec), consider using native `Error` and converting to `ErrorX` at boundaries.

---

## UI Messages

User-friendly messages are provided separately from error presets. This allows errors to remain technical while UI messages can be managed independently (e.g., for i18n).
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@types/node": "^24.6.0",
"@vitest/coverage-v8": "^3.2.4",
"husky": "^9.1.7",
"i18next": "^25.8.0",
"tsup": "^8.5.0",
"typescript": "^5.9.2",
"vitest": "^3.2.4"
Expand Down Expand Up @@ -52,6 +53,7 @@
"api-docs": "api-extractor run --local",
"api-docs:build": "pnpm build && mkdir -p ./etc && pnpm api-docs && pnpm api-docs:markdown && rm -rf ./etc ./temp",
"api-docs:markdown": "npx @microsoft/api-documenter markdown -i temp -o docs",
"bench": "vitest bench",
"build": "tsup",
"check": "biome check .",
"dev": "tsup --watch",
Expand Down
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading