Skip to content

Repository files navigation

BaseError

The BaseError is a robust and flexible base class for creating structured application errors. It provides a consistent error interface with support for predefined error identifiers, message templating, error cause chaining, and contextual details.

Table of Contents

Installation

You can install BaseError via npm:

npm install baseerror

Importing

To use BaseError in your JavaScript application, first import it:

ES Modules

import BaseError from 'base-error-class';

CommonJS

const BaseError = require('base-error-class');

Usage

The BaseError is designed to be extended by domain-specific error classes. Subclasses can define a static MESSAGES map containing error identifiers and message templates.

import BaseError from 'base-error-class';

class ValidationError extends BaseError {
  static MESSAGES = new Map([
    ['INVALID_FIELD', 'The field "{field}" is required or invalid.'],
    ['OUT_OF_RANGE', 'Value {value} must be between {min} and {max}.'],
  ]);
}

try {
  throw new ValidationError('INVALID_FIELD', {
    values: {
      field: 'email',
    },
    details: {
      attempted: '',
    },
  });
} catch (error) {
  // ValidationError
  console.log(error.name);

  // INVALID_FIELD
  console.log(error.code);

  // The field "email" is required or invalid.
  console.log(error.message);

  // { attempted: '' }
  console.log(error.details);
}

Tip

For a better development experience, you can document your error identifiers with JSDoc. This allows editors such as Visual Studio Code to provide IntelliSense suggestions for predefined error identifiers while still allowing custom error messages.

For example:

import BaseError from 'base-error-class';

/**
 * @template {string} T
 * @typedef {T | (string & {})} LiteralUnion
 */

/**
 * Identifies a predefined validation error or allows a custom error message.
 *
 * @typedef {LiteralUnion<
 *   'INVALID_FIELD' |
 *   'OUT_OF_RANGE'
 * >} ValidationErrorIdentifier
 */

class ValidationError extends BaseError {
  static MESSAGES = new Map([
    ['INVALID_FIELD', 'The field "{field}" is required or invalid.'],
    ['OUT_OF_RANGE', 'Value {value} must be between {min} and {max}.'],
  ]);
}

API

new BaseError(identifier, [options])

Creates a new BaseError instance.

BaseError is intended to be extended by application-specific error classes.

Parameters

Name Type Description
identifier string A predefined error identifier from MESSAGES, or a custom error message.
options object Optional configuration for the error instance.

options

Property Type Description
values Record<string, unknown> Values used to replace {key} placeholders in a predefined message template.
details unknown Additional contextual information associated with the error.
cause Error The original error that caused this error.

Error Identifiers

When identifier exists in the subclass's MESSAGES map, the corresponding message template is resolved and the identifier is assigned to error.code.

const error = new ValidationError('INVALID_FIELD', {
  values: {
    field: 'email',
  },
});

// INVALID_FIELD
console.log(error.code);

// The field "email" is required or invalid.
console.log(error.message);

If the identifier is not defined in MESSAGES, it is treated as a custom error message and no code property is defined.

const error = new ValidationError('Something went wrong');

// Something went wrong
console.log(error.message);

// undefined
console.log(error.code);

Message Templates

Message templates can contain {key} placeholders.

class ValidationError extends BaseError {
  static MESSAGES = new Map([
    ['INVALID_RANGE', '{field} must be between {min} and {max}.'],
  ]);
}

const error = new ValidationError('INVALID_RANGE', {
  values: {
    field: 'age',
    min: 18,
    max: 65,
  },
});

// age must be between 18 and 65.
console.log(error.message);

If a placeholder does not have a corresponding value, it remains unchanged.

const error = new ValidationError('INVALID_RANGE', {
  values: {
    field: 'age',
  },
});

// age must be between {min} and {max}.
console.log(error.message);

Subclassing and Message Catalogs

Each subclass can define its own MESSAGES map.

class DatabaseError extends BaseError {
  static MESSAGES = new Map([
    [
      'CONNECTION_FAILED',
      'Could not connect to database at {host}:{port}.',
    ],
  ]);
}

Message catalogs belong to the subclass that defines them.

Error Causes

An original error can be preserved using the cause option.

const originalError = new Error('ECONNREFUSED');

const databaseError = new DatabaseError('CONNECTION_FAILED', {
  values: {
    host: 'localhost',
    port: 5432,
  },
  cause: originalError,
});

// true
console.log(databaseError.cause === originalError);

Details

Additional contextual information can be attached using details.

const error = new ValidationError('INVALID_FIELD', {
  values: {
    field: 'email',
  },
  details: {
    value: 'invalid@example',
  },
});

// { value: 'invalid@example' }
console.log(error.details);

Contributing

If you encounter any bugs or issues with BaseError, please open an issue on the GitHub repository. Pull requests are also welcome!

License

The BaseError class is released under the MIT License.

About

A lightweight base error class for Node.js offering structured application errors, message templating, error codes, cause chaining, and custom domain contexts.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages