@bombillazo/error-x 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm](https://img.shields.io/npm/dt/@bombillazo/error-x.svg?style=for-the-badge)](https://www.npmjs.com/package/@bombillazo/error-x)
5
5
  [![npm](https://img.shields.io/npm/l/@bombillazo/error-x?style=for-the-badge)](https://github.com/bombillazo/error-x/blob/master/LICENSE)
6
6
 
7
- A smart, isomorphic, and satisfying error library for TypeScript applications. Provides type-safe error handling with great DX, solving common pain points like unknown error types, lost stack traces, async error handling, and error serialization.
7
+ A smart, isomorphic, and opinionated error library for TypeScript applications. Provides type-safe error handling with great DX, solving common pain points like unknown error types, lost stack traces, async error handling, and error serialization.
8
8
 
9
9
  ## Features
10
10
 
@@ -12,11 +12,11 @@ A smart, isomorphic, and satisfying error library for TypeScript applications. P
12
12
  - 🔄 **Smart error conversion** from various formats (API responses, strings, Error objects)
13
13
  - 📝 **Auto-formatted messages and error codes** with proper capitalization and punctuation
14
14
  - 👤 **User-friendly messages** separate from technical messages
15
- - 🕒 **Automatic timestamps** for error tracking
16
15
  - 🔗 **Error chaining** with cause preservation and stack trace preservation
17
16
  - 📊 **Flexible metadata** for additional context
18
17
  - 🎛️ **Error handling options** for UI behavior and application actions
19
18
  - 📦 **Serialization/deserialization** support for network transfer and storage
19
+ - 🎨 **Pre-configured error presets** for common error types
20
20
 
21
21
  ## Installation
22
22
 
@@ -236,6 +236,179 @@ const error = new ErrorX({
236
236
  })
237
237
  ```
238
238
 
239
+ ## Error Presets
240
+
241
+ ErrorX provides pre-configured error templates for common scenarios, making it easy to create consistent, well-structured errors without repetition. All HTTP presets (400-511) are included with proper status codes, messages, and user-friendly text.
242
+
243
+ ### Features
244
+
245
+ - ✅ **Pre-configured templates** with httpStatus, code, name, message, and uiMessage
246
+ - ✅ **Type-safe** with full TypeScript support
247
+ - ✅ **Fully customizable** via destructuring and override pattern
248
+ - ✅ **Categorized by type** - all HTTP presets include `type: 'http'` for easy filtering
249
+ - ✅ **User-friendly messages** included for all presets
250
+
251
+ ### Usage Patterns
252
+
253
+ #### 1. Direct Usage
254
+
255
+ Use a preset as-is without modifications:
256
+
257
+ ```typescript
258
+ import { ErrorX } from '@bombillazo/error-x'
259
+
260
+ // Simple usage
261
+ throw new ErrorX(ErrorX.HTTP.NOT_FOUND)
262
+ // Result: 404 error with default message and UI message
263
+ ```
264
+
265
+ #### 2. Override Specific Fields
266
+
267
+ Customize the error while keeping other preset values:
268
+
269
+ ```typescript
270
+ throw new ErrorX({
271
+ ...ErrorX.HTTP.NOT_FOUND,
272
+ message: 'User not found',
273
+ metadata: { userId: 123 }
274
+ })
275
+ // Result: 404 error with custom message but keeps httpStatus, code, name, uiMessage, type
276
+ ```
277
+
278
+ #### 3. Add Metadata and Actions
279
+
280
+ Enhance presets with additional context and behaviors:
281
+
282
+ ```typescript
283
+ throw new ErrorX({
284
+ ...ErrorX.HTTP.UNAUTHORIZED,
285
+ metadata: { attemptedAction: 'viewProfile', userId: 456 },
286
+ actions: [
287
+ { action: 'logout', payload: { clearStorage: true } },
288
+ { action: 'redirect', payload: { redirectURL: '/login' } }
289
+ ]
290
+ })
291
+ ```
292
+
293
+ #### 4. Add Error Cause
294
+
295
+ Chain errors by adding a cause:
296
+
297
+ ```typescript
298
+ try {
299
+ // some operation
300
+ } catch (originalError) {
301
+ throw new ErrorX({
302
+ ...ErrorX.HTTP.INTERNAL_SERVER_ERROR,
303
+ cause: originalError,
304
+ metadata: { operation: 'database-query' }
305
+ })
306
+ }
307
+ ```
308
+
309
+ ### Available HTTP Presets
310
+
311
+ #### 4xx Client Errors
312
+
313
+ | Preset | Status | Description |
314
+ | ------ | ------ | ----------- |
315
+ | BAD_REQUEST | 400 | Invalid request data |
316
+ | UNAUTHORIZED | 401 | Authentication required |
317
+ | PAYMENT_REQUIRED | 402 | Payment required to access resource |
318
+ | FORBIDDEN | 403 | Insufficient permissions |
319
+ | NOT_FOUND | 404 | Resource not found |
320
+ | METHOD_NOT_ALLOWED | 405 | HTTP method not allowed |
321
+ | NOT_ACCEPTABLE | 406 | Requested format not supported |
322
+ | PROXY_AUTHENTICATION_REQUIRED | 407 | Proxy authentication required |
323
+ | REQUEST_TIMEOUT | 408 | Request took too long |
324
+ | CONFLICT | 409 | Resource conflict |
325
+ | GONE | 410 | Resource no longer available |
326
+ | LENGTH_REQUIRED | 411 | Missing length information |
327
+ | PRECONDITION_FAILED | 412 | Required condition not met |
328
+ | PAYLOAD_TOO_LARGE | 413 | Request payload too large |
329
+ | URI_TOO_LONG | 414 | Request URL too long |
330
+ | UNSUPPORTED_MEDIA_TYPE | 415 | File type not supported |
331
+ | RANGE_NOT_SATISFIABLE | 416 | Requested range cannot be satisfied |
332
+ | EXPECTATION_FAILED | 417 | Server cannot meet request requirements |
333
+ | IM_A_TEAPOT | 418 | I'm a teapot (RFC 2324) |
334
+ | UNPROCESSABLE_ENTITY | 422 | Validation failed |
335
+ | LOCKED | 423 | Resource is locked |
336
+ | FAILED_DEPENDENCY | 424 | Request failed due to dependency error |
337
+ | TOO_EARLY | 425 | Request sent too early |
338
+ | UPGRADE_REQUIRED | 426 | Upgrade required to continue |
339
+ | PRECONDITION_REQUIRED | 428 | Required conditions missing |
340
+ | TOO_MANY_REQUESTS | 429 | Rate limit exceeded |
341
+ | REQUEST_HEADER_FIELDS_TOO_LARGE | 431 | Request headers too large |
342
+ | UNAVAILABLE_FOR_LEGAL_REASONS | 451 | Content unavailable for legal reasons |
343
+
344
+ #### 5xx Server Errors
345
+
346
+ | Preset | Status | Description |
347
+ | ------ | ------ | ----------- |
348
+ | INTERNAL_SERVER_ERROR | 500 | Unexpected server error |
349
+ | NOT_IMPLEMENTED | 501 | Feature not implemented |
350
+ | BAD_GATEWAY | 502 | Upstream server error |
351
+ | SERVICE_UNAVAILABLE | 503 | Service temporarily down |
352
+ | GATEWAY_TIMEOUT | 504 | Upstream timeout |
353
+ | HTTP_VERSION_NOT_SUPPORTED | 505 | HTTP version not supported |
354
+ | VARIANT_ALSO_NEGOTIATES | 506 | Internal configuration error |
355
+ | INSUFFICIENT_STORAGE | 507 | Insufficient storage |
356
+ | LOOP_DETECTED | 508 | Infinite loop detected |
357
+ | NOT_EXTENDED | 510 | Additional extensions required |
358
+ | NETWORK_AUTHENTICATION_REQUIRED | 511 | Network authentication required |
359
+
360
+ ### Real-World Examples
361
+
362
+ #### API Endpoint
363
+
364
+ ```typescript
365
+ import { ErrorX } from '@bombillazo/error-x'
366
+
367
+ app.get('/users/:id', async (req, res) => {
368
+ const user = await db.users.findById(req.params.id)
369
+
370
+ if (!user) {
371
+ throw new ErrorX({
372
+ ...ErrorX.HTTP.NOT_FOUND,
373
+ message: 'User not found',
374
+ metadata: { userId: req.params.id }
375
+ })
376
+ }
377
+
378
+ res.json(user)
379
+ })
380
+ ```
381
+
382
+ #### Authentication Middleware
383
+
384
+ ```typescript
385
+ const requireAuth = (req, res, next) => {
386
+ if (!req.user) {
387
+ throw new ErrorX({
388
+ ...ErrorX.HTTP.UNAUTHORIZED,
389
+ actions: [
390
+ { action: 'redirect', payload: { redirectURL: '/login' } }
391
+ ]
392
+ })
393
+ }
394
+ next()
395
+ }
396
+ ```
397
+
398
+ #### Rate Limiting
399
+
400
+ ```typescript
401
+ if (isRateLimited(req.ip)) {
402
+ throw new ErrorX({
403
+ ...ErrorX.HTTP.TOO_MANY_REQUESTS,
404
+ metadata: {
405
+ ip: req.ip,
406
+ retryAfter: 60
407
+ }
408
+ })
409
+ }
410
+ ```
411
+
239
412
  ## Smart Features
240
413
 
241
414
  ### Auto Code Generation
@@ -246,7 +419,7 @@ Error codes are automatically generated from the error name:
246
419
  new ErrorX({ message: 'Failed', name: 'DatabaseError' })
247
420
  // code: 'DATABASE_ERROR'
248
421
 
249
- new ErrorX({ message: 'Failed', name: 'userAuthError' })
422
+ new ErrorX({ message: 'Failed', name: 'userAuthError' })
250
423
  // code: 'USER_AUTH_ERROR'
251
424
 
252
425
  new ErrorX({ message: 'Failed', name: 'API Timeout' })