npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hemia/error-handler

v0.0.3

Published

Hemia Error Handler

Readme

@hemia/error-handler

Librería flexible para gestionar códigos de error a través de los sistemas de Hemia. Soporta errores de bases de datos (MySQL, PostgreSQL, MongoDB), errores comunes, y permite agregar errores personalizados con traducciones en múltiples idiomas.

📦 Instalación

Instala el paquete desde NPM:

NPM

npm install @hemia/error-handler
# o con bun
bun install @hemia/error-handler

🚀 Características

  • ✅ Soporte para errores de bases de datos (MySQL, PostgreSQL, MongoDB)
  • ✅ Gestión de errores comunes de aplicación
  • ✅ Sistema de internacionalización (i18n) integrado
  • Estructuras anidadas con dot notation (schema_error.field_required)
  • Interpolación de parámetros con {{param}}
  • ✅ Soporte para errores personalizados sin dependencia de BD
  • ✅ Mapeos dinámicos de errores en tiempo de ejecución
  • ✅ Múltiples idiomas (en, es, y personalizados)
  • ✅ TypeScript con tipos completos
  • ✅ API flexible con múltiples formas de uso

📖 Uso Básico

1. Con Base de Datos (Modo Clásico)

import { ErrorHandler, dbEnum, langEnum } from '@hemia/error-handler';

// Constructor simple
const handler = new ErrorHandler(dbEnum.mysql, langEnum.es);

// Obtener mensaje de error
const error = handler.getErrorMessage('1062'); // MySQL duplicate key error
console.log(error);
// {
//   message: 'Entrada duplicada',
//   messageDev: 'Duplicate entry for key',
//   code: '1062',
//   status: 409
// }

2. Estructuras Anidadas con Dot Notation

import { ErrorHandler, langEnum } from '@hemia/error-handler';

const handler = new ErrorHandler({
  lang: langEnum.es,
  customLocales: {
    'en': {
      schema_error: {
        field_must_be_text: {
          message: "Field must be text.",
          messageDev: "The field must be of type text",
          status: 400
        },
        field_min_length: {
          message: "Minimum length is {{length}} characters.",
          messageDev: "The field does not meet the minimum length requirement of {{length}} characters",
          status: 400
        },
        validation: {
          email: {
            invalid_format: {
              message: "Invalid email format.",
              messageDev: "Email field does not comply with RFC 5322 format",
              status: 400
            }
          }
        }
      }
    },
    'es': {
      schema_error: {
        field_must_be_text: {
          message: "El campo debe de ser texto.",
          messageDev: "El campo debe ser de tipo texto",
          status: 400
        },
        field_min_length: {
          message: "El mínimo de caracteres es {{length}}.",
          messageDev: "El campo no cumple con el requerimiento de longitud mínima de {{length}} caracteres",
          status: 400
        },
        validation: {
          email: {
            invalid_format: {
              message: "El formato del email es inválido.",
              messageDev: "El campo email no cumple con el formato RFC 5322",
              status: 400
            }
          }
        }
      }
    }
  }
});

// Uso con dot notation (sin parámetros)
const error1 = handler.getErrorMessage('schema_error.field_must_be_text');
console.log(error1);
// { message: "El campo debe de ser texto.", messageDev: "...", status: 400 }

// Con parámetros de interpolación (sin necesidad de pasar null para lang)
const error2 = handler.getErrorMessage('schema_error.field_min_length', { length: 5 });
console.log(error2);
// { message: "El mínimo de caracteres es 5.", messageDev: "... 5 caracteres", status: 400 }

// Muy anidado
const error3 = handler.getErrorMessage('schema_error.validation.email.invalid_format');
console.log(error3);
// { message: "El formato del email es inválido.", ... }

// Con idioma específico
const error4 = handler.getErrorMessage('schema_error.field_must_be_text', langEnum.en);
console.log(error4);
// { message: "Field must be text.", ... }

// Con idioma y parámetros
const error5 = handler.getErrorMessage('schema_error.field_min_length', langEnum.en, { length: 10 });
console.log(error5);
// { message: "Minimum length is 10 characters.", ... }

3. Sin Base de Datos (Solo Errores Personalizados)

import { ErrorHandler, langEnum } from '@hemia/error-handler';

const handler = new ErrorHandler({
  lang: langEnum.es,
  customLocales: {
    'en': {
      'VALIDATION_ERROR': {
        message: 'Validation failed',
        messageDev: 'Input validation failed. Check required fields.',
        status: 400
      },
      'AUTH_ERROR': {
        message: 'Authentication failed',
        messageDev: 'Invalid credentials provided',
        status: 401
      }
    },
    'es': {
      'VALIDATION_ERROR': {
        message: 'Error de validación',
        messageDev: 'La validación de entrada falló. Revise los campos requeridos.',
        status: 400
      },
      'AUTH_ERROR': {
        message: 'Autenticación fallida',
        messageDev: 'Credenciales inválidas proporcionadas',
        status: 401
      }
    }
  },
  customErrorMappings: {
    'ERR_VAL_001': 'VALIDATION_ERROR',
    'ERR_AUTH_001': 'AUTH_ERROR'
  }
});

const error = handler.getErrorMessage('ERR_VAL_001');
console.log(error);
// {
//   message: 'Error de validación',
//   messageDev: 'La validación de entrada falló...',
//   code: 'ERR_VAL_001',
//   status: 400
// }

4. Modo Híbrido (BD + Errores Personalizados)

import { ErrorHandler, dbEnum, langEnum } from '@hemia/error-handler';

const handler = new ErrorHandler({
  dbType: dbEnum.postgres,
  lang: langEnum.en,
  customLocales: {
    'en': {
      'BUSINESS_RULE_VIOLATION': {
        message: 'Business rule violation',
        messageDev: 'The operation violates business rules',
        status: 422
      }
    }
  },
  customErrorMappings: {
    'BIZ_001': 'BUSINESS_RULE_VIOLATION'
  }
});

// Maneja errores de PostgreSQL
const dbError = handler.getErrorMessage('23505'); // Unique violation

// Maneja errores personalizados
const bizError = handler.getErrorMessage('BIZ_001');

🎯 API Avanzada

Formas de Usar getErrorMessage()

El método getErrorMessage tiene múltiples sobrecargas para máxima flexibilidad:

// 1. Solo código de error (usa idioma por defecto de la instancia)
handler.getErrorMessage('schema_error.field_required');

// 2. Código + parámetros (sin necesidad de pasar null)
handler.getErrorMessage('schema_error.field_min_length', { length: 5 });

// 3. Código + idioma específico
handler.getErrorMessage('schema_error.field_required', langEnum.en);

// 4. Código + idioma + parámetros
handler.getErrorMessage('schema_error.field_min_length', langEnum.en, { length: 10 });

Métodos de Instancia

getErrorMessage(errorCode, langOrParams?, params?): ErrorMessage

Obtiene el mensaje de error traducido con soporte para:

  • Dot notation para estructuras anidadas
  • Interpolación de parámetros con {{param}}
  • Sobrecarga flexible sin necesidad de valores null
// Estructura anidada con parámetros
const error = handler.getErrorMessage('schema_error.field_min_length', { length: 5 });
console.log(error.message); // "El mínimo de caracteres es 5."

addErrorMappings(mappings: { [key: string]: string }): void

Agrega mapeos de errores dinámicamente.

handler.addErrorMappings({
  'APP_001': 'VALIDATION_ERROR',
  'APP_002': 'AUTH_ERROR'
});

clearErrorMappings(): void

Limpia todos los mapeos personalizados.

handler.clearErrorMappings();

getErrorMappings(): { [key: string]: string }

Obtiene los mapeos actuales.

const mappings = handler.getErrorMappings();

setLanguage(lang: langEnum): void

Cambia el idioma de la instancia.

handler.setLanguage(langEnum.es);

getLanguage(): string

Obtiene el idioma actual de la instancia.

const currentLang = handler.getLanguage();

Funciones Globales de i18n

registerLocale(lang: string, locale: any): void

Registra o fusiona traducciones para un idioma. Soporta estructuras anidadas.

import { registerLocale } from '@hemia/error-handler';

// Estructura plana
registerLocale('fr', {
  'VALIDATION_ERROR': {
    message: 'Erreur de validation',
    messageDev: 'La validation a échoué',
    status: 400
  }
});

// Estructura anidada
registerLocale('de', {
  schema_error: {
    field_required: {
      message: 'Feld ist erforderlich',
      messageDev: 'Required field missing',
      status: 400
    },
    field_min_length: {
      message: 'Mindestlänge ist {{length}} Zeichen',
      messageDev: 'Field does not meet minimum length of {{length}}',
      status: 400
    }
  }
});

setLocale(lang: string, locale: any): void

Reemplaza completamente las traducciones de un idioma.

import { setLocale } from '@hemia/error-handler';

setLocale('es', {
  'ERROR_001': { message: 'Error 1', messageDev: 'Dev msg' }
});

setLanguage(lang: string): void

Cambia el idioma global por defecto.

import { setLanguage } from '@hemia/error-handler';

setLanguage('es');

getCurrentLanguage(): string

Obtiene el idioma global actual.

import { getCurrentLanguage } from '@hemia/error-handler';

const lang = getCurrentLanguage(); // 'en'

getAvailableLanguages(): string[]

Obtiene todos los idiomas disponibles.

import { getAvailableLanguages } from '@hemia/error-handler';

const languages = getAvailableLanguages(); // ['en', 'es', 'fr']

🌍 Ejemplo Completo: Aplicación Multiidioma con Estructuras Anidadas

import { ErrorHandler, langEnum, registerLocale } from '@hemia/error-handler';

// 1. Registrar estructura anidada para francés
registerLocale('fr', {
  schema_error: {
    field_required: {
      message: 'Le champ est requis',
      messageDev: 'Required field missing',
      status: 400
    },
    field_min_length: {
      message: 'Longueur minimale est {{length}} caractères',
      messageDev: 'Field does not meet minimum length of {{length}}',
      status: 400
    }
  }
});

// 2. Crear handler con estructura anidada compleja
const handler = new ErrorHandler({
  lang: langEnum.en,
  customLocales: {
    'en': {
      user: {
        not_found: {
          message: 'User not found',
          messageDev: 'The requested user does not exist in the database',
          status: 404
        },
        account: {
          suspended: {
            message: 'Account is suspended',
            messageDev: 'User account has been suspended by administrator',
            status: 403
          },
          expired: {
            message: 'Account has expired',
            messageDev: 'User subscription expired on {{date}}',
            status: 403
          }
        }
      },
      payment: {
        insufficient_funds: {
          message: 'Insufficient funds',
          messageDev: 'Account balance is {{balance}}, required {{required}}',
          status: 402
        }
      }
    },
    'es': {
      user: {
        not_found: {
          message: 'Usuario no encontrado',
          messageDev: 'El usuario solicitado no existe en la base de datos',
          status: 404
        },
        account: {
          suspended: {
            message: 'Cuenta suspendida',
            messageDev: 'La cuenta del usuario ha sido suspendida por el administrador',
            status: 403
          },
          expired: {
            message: 'Cuenta expirada',
            messageDev: 'La suscripción del usuario expiró el {{date}}',
            status: 403
          }
        }
      },
      payment: {
        insufficient_funds: {
          message: 'Fondos insuficientes',
          messageDev: 'El saldo de la cuenta es {{balance}}, se requiere {{required}}',
          status: 402
        }
      }
    }
  },
  customErrorMappings: {
    'USR_404': 'user.not_found',
    'USR_SUSPENDED': 'user.account.suspended',
    'USR_EXPIRED': 'user.account.expired',
    'PAY_001': 'payment.insufficient_funds'
  }
});

// 3. Uso con diferentes niveles de anidación

// Simple
const error1 = handler.getErrorMessage('user.not_found');
console.log(error1); 
// { message: 'User not found', status: 404, ... }

// Anidado 2 niveles
const error2 = handler.getErrorMessage('user.account.suspended', langEnum.es);
console.log(error2); 
// { message: 'Cuenta suspendida', status: 403, ... }

// Con parámetros
const error3 = handler.getErrorMessage('user.account.expired', { date: '2025-01-15' });
console.log(error3); 
// { message: 'Account has expired', messageDev: 'User subscription expired on 2025-01-15', ... }

// Con idioma y parámetros
const error4 = handler.getErrorMessage(
  'payment.insufficient_funds', 
  langEnum.es, 
  { balance: 50, required: 100 }
);
console.log(error4); 
// { message: 'Fondos insuficientes', messageDev: 'El saldo de la cuenta es 50, se requiere 100', ... }

// Usando mapeos personalizados
const error5 = handler.getErrorMessage('USR_SUSPENDED');
console.log(error5); 
// { message: 'Account is suspended', ... }

// 4. Agregar mapeos dinámicamente
handler.addErrorMappings({
  'CUSTOM_001': 'user.account.expired'
});

// 5. Cambiar idioma de la instancia
handler.setLanguage(langEnum.es);
const error6 = handler.getErrorMessage('CUSTOM_001', { date: '2025-12-31' });
console.log(error6); 
// { message: 'Cuenta expirada', messageDev: 'La suscripción del usuario expiró el 2025-12-31', ... }

🔧 Express/Fastify Middleware Example

import { ErrorHandler, dbEnum, langEnum } from '@hemia/error-handler';
import { Request, Response, NextFunction } from 'express';

const errorHandler = new ErrorHandler({
  dbType: dbEnum.postgres,
  lang: langEnum.es,
  customLocales: {
    'es': {
      'INTERNAL_ERROR': {
        message: 'Error interno del servidor',
        messageDev: 'An unexpected error occurred',
        status: 500
      }
    }
  }
});

// Middleware de manejo de errores
export function errorMiddleware(
  err: any,
  req: Request,
  res: Response,
  next: NextFunction
) {
  const lang = req.headers['accept-language']?.includes('es') 
    ? langEnum.es 
    : langEnum.en;

  const errorCode = err.code || 'INTERNAL_ERROR';
  const errorMessage = errorHandler.getErrorMessage(errorCode, lang);

  res.status(errorMessage.status || 500).json({
    success: false,
    error: {
      message: errorMessage.message,
      code: errorMessage.code,
      ...(process.env.NODE_ENV === 'development' && {
        messageDev: errorMessage.messageDev
      })
    }
  });
}

📝 Tipos TypeScript

interface ErrorMessage {
  message: string;
  messageDev?: string;
  code?: string;
  status?: number;
  params?: { [key: string]: string | number };
}

interface ErrorHandlerOptions {
  dbType?: dbEnum;
  lang?: langEnum;
  customLocales?: { [lang: string]: any }; // Soporta estructuras anidadas
  customErrorMappings?: { [key: string]: string };
}

enum dbEnum {
  mysql = 'mysql',
  postgres = 'postgres',
  mongo = 'mongo'
}

enum langEnum {
  en = 'en',
  es = 'es'
}

🔑 Interpolación de Parámetros

La librería soporta interpolación de parámetros usando la sintaxis {{param}}:

// En el locale
{
  'field_min_length': {
    message: "El mínimo es {{length}} caracteres",
    messageDev: "Minimum length is {{length}}"
  }
}

// Uso
const error = handler.getErrorMessage('field_min_length', { length: 5 });
console.log(error.message); // "El mínimo es 5 caracteres"

Múltiples parámetros

{
  'date_range_error': {
    message: "La fecha debe estar entre {{start}} y {{end}}",
    messageDev: "Date must be between {{start}} and {{end}}"
  }
}

const error = handler.getErrorMessage('date_range_error', {
  start: '2025-01-01',
  end: '2025-12-31'
});
// message: "La fecha debe estar entre 2025-01-01 y 2025-12-31"

🎨 Prioridad de Búsqueda de Errores

El sistema busca errores en el siguiente orden:

  1. Mapeos personalizados (customErrorMappings)
  2. Errores de BD (si dbType está definido)
  3. Errores comunes (definidos internamente)
  4. Fallback (devuelve el código como mensaje)

📄 Licencia

ISC


🤝 Contribuciones

Para contribuir al proyecto, por favor contacta al equipo de Hemia