Handle errors like it's 2022 🔮

Overview

Codecov Build Node Twitter Medium

Handle errors like it's 2022 🔮

Error handling framework that is minimalist yet featureful.

Features

Example

Create the error types and handler.

// `error.js`
import modernErrors from 'modern-errors'

export const { errorHandler, InputError, AuthError, DatabaseError } =
  modernErrors()

Wrap the main function with the error handler.

import { errorHandler } from './error.js'

export const main = async function (filePath) {
  try {
    return await readContents(filePath)
  } catch (error) {
    throw errorHandler(error)
  }
}

Throw/re-throw errors.

import { InputError } from './error.js'

const readContents = async function (filePath) {
  try {
    return await readFile(filePath)
  } catch (cause) {
    throw new InputError(`Could not read ${filePath}`, { cause })
  }
}

Install

npm install modern-errors

This package is an ES module and must be loaded using an import or import() statement, not require().

API

modernErrors(options?)

options object
Return value: object

Creates the error types and handler.

Return value

Any error type

Type: ErrorType

Any error type can be retrieved from the return value. The name must end with Error. For example: InputError, AuthError, etc.

errorHandler

Type: (anyException) => Error

Error handler that should wrap each main function.

Options

bugsUrl

Type: string | URL

URL where users should report internal errors/bugs.

onCreate

Type: (error, parameters) => void

Called on any new ErrorType('message', parameters). Can be used to customize error parameters or set error type properties. By default, any parameters are set as error properties.

Usage

Setup

Create error types and handler

Retrieving the error types automatically creates them.

// error.js
import modernErrors from 'modern-errors'

// The error types are examples: any name ending with "Error" can be specified
export const { errorHandler, InputError, AuthError, DatabaseError } =
  modernErrors()

Error handler

Each main function should be wrapped with the errorHandler().

import { errorHandler } from './error.js'

export const main = async function (filePath) {
  try {
    return await readContents(filePath)
  } catch (error) {
    // `errorHandler()` returns `error`, so `throw` must be used
    throw errorHandler(error)
  }
}

Throw errors

Simple errors

import { InputError } from './error.js'

const validateFilePath = function (filePath) {
  if (filePath === '') {
    throw new InputError('Missing file path.')
  }
}

Invalid errors

Invalid errors are normalized by errorHandler(). This includes errors that are not an Error instance or that have wrong/missing properties.

import { errorHandler } from './error.js'

export const main = function (filePath) {
  try {
    throw 'Missing file path.'
  } catch (error) {
    throw errorHandler(error) // Normalized to an `Error` instance
  }
}

Re-throw errors

Errors are re-thrown using the standard cause parameter. This allows wrapping the error message, properties, or type.

import { InputError } from './error.js'

const readContents = async function (filePath) {
  try {
    return await readFile(filePath)
  } catch (cause) {
    throw new InputError(`Could not read ${filePath}`, { cause })
  }
}

The errorHandler() merges all error cause into a single error, including their message, stack, name, AggregateError.errors and any additional property. This ensures:

Wrap error message

The outer error message is appended.

try {
  await readFile(filePath)
} catch (cause) {
  throw new InputError(`Could not read ${filePath}`, { cause })
  // InputError: File does not exist.
  // Could not read /example/path
}

If the outer error message ends with :, it is prepended instead.

throw new InputError(`Could not read ${filePath}:`, { cause })
// InputError: Could not read /example/path: File does not exist.

: can optionally be followed a newline.

throw new InputError(`Could not read ${filePath}:\n`, { cause })
// InputError: Could not read /example/path:
// File does not exist.

Error types

Test error type

Once errorHandler() has been applied, the error type can be checked by its name (as opposed to instanceof). Libraries should document their possible error names, but do not need to export their error types.

if (error.name === 'InputError') {
  // ...
} else if (error.name === 'InternalError') {
  // ...
}

Set error type

When re-throwing errors, the outer error type overrides the inner one.

try {
  throw new AuthError('Could not authenticate.')
} catch (cause) {
  throw new InputError('Could not read the file.', { cause })
  // Now an InputError
}

However, the inner error type is kept if the outer one is Error or AggregateError.

try {
  throw new AuthError('Could not authenticate.')
} catch (cause) {
  throw new Error('Could not read the file.', { cause })
  // Still an AuthError
}

Internal errors

Internal errors/bugs can be distinguished from user errors by handling any possible errors in try {} catch {} and re-throwing them with a specific error type. The errorHandler() assigns the InternalError type to any error with an unknown type.

const getUserId = function (user) {
  return user.id
}

getUserId(null) // InternalError: Cannot read properties of null (reading 'id')

Bug reports

If the bugsUrl option is used,

modernErrors({ bugsUrl: 'https://github.com/my-name/my-project/issues' })

any internal error will include the following message.

Please report this bug at: https://github.com/my-name/my-project/issues

Error properties

Set error properties

Unless the onCreate() option is defined, any parameter is set as an error property.

const error = new InputError('Could not read the file.', { filePath: '/path' })
console.log(error.filePath) // '/path'

Wrap error properties

Pass an empty message in order to set error properties without wrapping the message.

try {
  await readFile(filePath)
} catch (cause) {
  throw new Error('', { cause, filePath: '/path' })
}

Customize error parameters

The onCreate() option can be used to validate and transform error parameters.

modernErrors({
  onCreate(error, parameters) {
    const { filePath } = parameters

    if (typeof filePath !== 'string') {
      throw new Error('filePath must be a string.')
    }

    const hasFilePath = filePath !== undefined
    Object.assign(error, { filePath, hasFilePath })
  },
})
const error = new InputError('Could not read the file.', {
  filePath: '/path',
  unknownParam: true,
})
console.log(error.filePath) // '/path'
console.log(error.hasFilePath) // true
console.log(error.unknownParam) // undefined

Type-specific logic

The onCreate() option can trigger error type-specific logic.

modernErrors({
  onCreate(error, parameters) {
    onCreateError[error.name](error, parameters)
  },
})

const onCreateError = {
  InputError(error, parameters) {
    // ...
  },
  AuthError(error, parameters) {
    // ...
  },
  // ...
}

Error type properties

By default, error types are very similar except for their name. The onCreate() option can be used to set properties on all instances of a given error type.

modernErrors({
  onCreate(error, parameters) {
    Object.assign(error, parameters, ERROR_PROPS[error.name])
  },
})

const ERROR_PROPS = {
  InputError: { isUser: true },
  AuthError: { isUser: true },
  DatabaseError: { isUser: false },
}
const error = new InputError('Could not read the file.')
console.log(error.isUser) // true

Miscellaneous

Source maps

When using a build step (Babel, TypeScript, etc.), the error stack traces refer to the built files/lines instead of the source. This can be fixed by using source maps:

Support

For any question, don't hesitate to submit an issue on GitHub.

Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.

Contributing

This project was made with ❤️ . The simplest way to give back is by starring and sharing it online.

If the documentation is unclear or has a typo, please click on the page's Edit button (pencil icon) and suggest a correction.

If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!

You might also like...

🍣 CLI to handle Private Git Submodules in your Vercel Project

🍣 CLI to handle Private Git Submodules in your Vercel Project

vercel-submodules: The CLI to handle Private Git Submodules in your Vercel Project This project is community-driven and not affiliated with Vercel in

Jan 1, 2023

Angular JWT refresh token with Interceptor, handle token expiration in Angular 14 - Refresh token before expiration example

Angular JWT refresh token with Interceptor, handle token expiration in Angular 14 - Refresh token before expiration example

Angular 14 JWT Refresh Token example with Http Interceptor Implementing Angular 14 Refresh Token before Expiration with Http Interceptor and JWT. You

Nov 30, 2022

A simple handle tap and hold action for Svelte/SvelteKit.

Svelte Tap Hold Minimalistic tap and hold component for Svelte/SvelteKit, see demo here. Installation // Using Yarn to install yarn add --dev svelte-t

Dec 8, 2022

An itty library to handle common time-related things for your API needs.

An itty library to handle common time-related things for your API needs.

Tiny (~500 bytes) time math library for making date handling and TTLs within your APIs beautiful. Features Tiny @ ~500 bytes gzipped total, and tree-s

Jan 2, 2023

ish.ninja is a free online platform to allocate a unique ish.ninja sub handle name for a BlueSky account.

ish.ninja ish.ninja is a free online platform to allocate a unique ish.ninja sub handle name for a BlueSky account. It is built using Next.js, Xata, T

May 9, 2023

Auto-Fix Hundreds of Grammarly Errors With This Script

Auto-Fix Hundreds of Grammarly Errors With This Script

This script automatically applies your Grammarly suggestions. Use case: Large document with 100+ errors How to use: Go to Grammarly Web app Go to Edit

Jan 3, 2023

Beautiful errors for Remix, both in browser and console

Beautiful errors for Remix, both in browser and console

Rekindled Beautiful errors for Remix, both in browser and console. This project is inspired by php's ignition. I am personally in love with the idea o

Nov 22, 2022

In Your Face shows you Doom 'Ouch Faces' that correlate to the number of errors in your code!

In Your Face shows you Doom 'Ouch Faces' that correlate to the number of errors in your code!

In Your Face Watch how I made this extension on YouTube here In Your Face is a VS Code extension that shows you Doom 'Ouch Faces' that correlate to th

Dec 25, 2022

Notes may contain grammatical errors and some wont make sense and will only make sense to me

Notes may contain grammatical errors and some wont make sense and will only make sense to me

This is my own notes containing all the information and knowledge I've gained during my studying sessions. The notes are all topics that relates to technology such as computers, software or programming.

Dec 15, 2022
Comments
  • TypeScript + CommonJS support

    TypeScript + CommonJS support

    Guidelines

    • [X] Please search other issues to make sure this bug has not already been reported.
    • [X] If this is related to a typo or the documentation being unclear, please click on the relevant page's Edit button (pencil icon) and suggest a correction instead.

    Describe the bug

    I am unable to import this library into my codebase. I think it is because the published version is not compiled to module system I can use (?).

    It's quite possible there is something on my side that is causing the issue, or some configuration I could change to get it to work, but we already have > 80 other dependencies in our API that are not having any issues importing. (It's an express API)

    Thanks in advance for any help, I'm quite excited to give this library a try!

    Steps to reproduce

    1. Import and use the library
    import ModernError from "modern-errors";
    
    const BaseError = ModernError.subclass("BaseError");
    throw new BaseError("test");
    
    1. Start app with ts-node-dev
    2. See following stack trace:
    Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/jack/workspace/my-project/api/node_modules/modern-errors/build/src/main.js from /Users/jack/workspace/my-project/api/src/index.ts not supported.
    Instead change the require of main.js in /Users/jack/workspace/my-project/api/src/index.ts to a dynamic import() which is available in all CommonJS modules.
        at require.extensions..jsx.require.extensions..js (/private/var/folders/8n/dqgv9b4j797cqd34zb62ythw0000gn/T/ts-node-dev-hook-0371657800851346.js:114:20)
        at Object.nodeDevHook [as .js] (/Users/jack/workspace/my-project/api/node_modules/ts-node-dev/lib/hook.js:63:13)
        at Object.<anonymous> (/Users/jack/workspace/my-project/api/src/index.ts:68:41)
        at Module._compile (/Users/jack/workspace/my-project/api/node_modules/source-map-support/source-map-support.js:547:25)
        at Module.m._compile (/private/var/folders/8n/dqgv9b4j797cqd34zb62ythw0000gn/T/ts-node-dev-hook-0371657800851346.js:69:33)
        at require.extensions..jsx.require.extensions..js (/private/var/folders/8n/dqgv9b4j797cqd34zb62ythw0000gn/T/ts-node-dev-hook-0371657800851346.js:114:20)
        at require.extensions.<computed> (/private/var/folders/8n/dqgv9b4j797cqd34zb62ythw0000gn/T/ts-node-dev-hook-0371657800851346.js:71:20)
        at Object.nodeDevHook [as .ts] (/Users/jack/workspace/my-project/api/node_modules/ts-node-dev/lib/hook.js:63:13)
        at Object.<anonymous> (/Users/jack/workspace/my-project/api/node_modules/ts-node-dev/lib/wrap.js:104:1)
        at Module._compile (/Users/jack/workspace/my-project/api/node_modules/source-map-support/source-map-support.js:547:25)
        at Object.require.extensions..jsx.require.extensions..js (/private/var/folders/8n/dqgv9b4j797cqd34zb62ythw0000gn/T/ts-node-dev-hook-0371657800851346.js:95:24)
    

    Configuration

    tsconfig.json

    {
      "compilerOptions": {
        "lib": ["es2021"],
        "target": "es2019",
        "module": "commonjs",
        "moduleResolution": "node",
        "esModuleInterop": true,
        "strict": true,
        "rootDir": "./",
        "outDir": ".build",
        "allowJs": true,
        "sourceMap": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "typeRoots": ["node_modules/@types", "generated"],
      },
      "exclude": ["node_modules"]
    }
    

    Environment

     System:
       OS: macOS 13.0.1
       CPU: (10) arm64 Apple M1 Pro
       Memory: 158.23 MB / 16.00 GB
       Shell: 5.8.1 - /bin/zsh
     Binaries:
       Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node
       Yarn: 1.22.17 - /opt/homebrew/bin/yarn
       npm: 8.18.0 - ~/.nvm/versions/node/v16.14.0/bin/npm
     Browsers:
       Brave Browser: 100.1.37.113
       Chrome: 108.0.5359.124
       Firefox: 107.0.1
       Safari: 16.1
    

    Pull request (optional)

    • [ ] I can submit a pull request.
    question 
    opened by Jackman3005 6
  • Bump vm2 from 3.9.10 to 3.9.11

    Bump vm2 from 3.9.10 to 3.9.11

    Bumps vm2 from 3.9.10 to 3.9.11.

    Release notes

    Sourced from vm2's releases.

    3.9.11

    New Features

    https://github.com/patriksimek/vm2/commit/58478a58c6f4af3c54faf4117ed5ab72d2cc8cd5: Add option require.strict to allow to load required modules in non strict mode.

    Fixes

    https://github.com/patriksimek/vm2/commit/d9a7f3cc995d3d861e1380eafb886cb3c5e2b873: Security fix.

    Changelog

    Sourced from vm2's changelog.

    v3.9.11 (2022-08-28)

    [new] Add option require.strict to allow to load required modules in non strict mode.
    [fix] Security fix.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • Bump decode-uri-component from 0.2.0 to 0.2.2

    Bump decode-uri-component from 0.2.0 to 0.2.2

    Bumps decode-uri-component from 0.2.0 to 0.2.2.

    Release notes

    Sourced from decode-uri-component's releases.

    v0.2.2

    • Prevent overwriting previously decoded tokens 980e0bf

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.1...v0.2.2

    v0.2.1

    • Switch to GitHub workflows 76abc93
    • Fix issue where decode throws - fixes #6 746ca5d
    • Update license (#1) 486d7e2
    • Tidelift tasks a650457
    • Meta tweaks 66e1c28

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(5.5.0)
  • 5.5.0(Dec 17, 2022)

  • 5.4.0(Dec 12, 2022)

  • 5.3.1(Nov 30, 2022)

  • 5.3.0(Nov 25, 2022)

  • 5.2.0(Nov 23, 2022)

  • 5.1.1(Nov 21, 2022)

  • 5.1.0(Nov 19, 2022)

  • 5.0.0(Nov 19, 2022)

    Breaking changes

    Top-level error class

    The default export is now the top-level error class ModernError.

    Also, the base error class is now documented as BaseError instead of AnyError.

    Before:

    import modernErrors from 'modern-errors'
    
    export const AnyError = modernErrors(plugins, options)
    

    After:

    import ModernError from 'modern-errors'
    
    export const BaseError = ModernError.subclass('BaseError', {
      ...options,
      plugins,
    })
    

    Error normalization

    Creating an UnknownError class is now optional, although still recommended. To normalize unknown errors, UnknownError must now be explicitly passed as a second argument to BaseError.normalize().

    Before:

    export const main = function () {
      try {
        // ...
      } catch (error) {
        throw BaseError.normalize(error)
      }
    }
    

    After:

    export const main = function () {
      try {
        // ...
      } catch (error) {
        throw BaseError.normalize(error, UnknownError)
      }
    }
    

    When UnknownError is not passed as a second argument, BaseError.normalize() now converts unknown errors to BaseError instances instead.

    Before:

    const error = new Error('example')
    assert(BaseError.normalize(error) instanceof UnknownError)
    

    After:

    const error = new Error('example')
    assert(BaseError.normalize(error) instanceof BaseError)
    assert(!(BaseError.normalize(error) instanceof UnknownError))
    assert(BaseError.normalize(error, UnknownError) instanceof UnknownError)
    

    Wrap error options

    When wrapping errors, the outer and inner error's options are now always merged.

    Before:

    try {
      throw new AuthError('...', innerOptions)
    } catch (cause) {
      // Options are now `outerOptions`. `innerOptions` are discarded.
      throw new InputError('...', { ...outerOptions, cause })
    }
    

    After:

    try {
      throw new AuthError('...', innerOptions)
    } catch (cause) {
      // `outerOptions` are merged with `innerOptions`
      throw new InputError('...', { ...outerOptions, cause })
    }
    

    Wrap error class

    When wrapping errors, the inner error's class is now kept if the outer error's class is a parent (including BaseError).

    export const ParentError = BaseError.subclass('ParentError')
    export const ChildError = ParentError.subclass('ChildError')
    

    Before:

    try {
      throw new ChildError('...')
    } catch (cause) {
      // Now a ParentError
      throw new ParentError('...', { cause })
    }
    

    After:

    try {
      throw new ChildError('...')
    } catch (cause) {
      // Still a ChildError, because that is a subclass of ParentError
      throw new ParentError('...', { cause })
    }
    

    Aggregate errors

    Aggregate errors must now be explicitly normalized by BaseError.normalize() instead of being automatically normalized on creation.

    Features

    Global custom logic

    Global custom logic can now be specified by passing the custom option to the BaseError. Previously, only class-specific custom logic could be specified.

    Class-specific plugins

    Plugins can now be specific to an error class (and its subclasses) by using the plugins option. Previously plugins had to be applied to all error classes.

    Optional wrapping

    The BaseError can now be instantiated without wrapping an error. The cause option is now optional.

    Missing stack trace

    The stack trace produced when wrapping an error that does not have one has been improved.

    Plugins

    The following changes only impact authors of custom plugins.

    info.ErrorClass

    Static methods (including ErrorClass.normalize()) can now be called on any error class, not only on BaseError. As a consequence, info.AnyError has been renamed to info.ErrorClass.

    info.ErrorClasses

    info.ErrorClasses is now an array instead of an object. This array might contain error classes with duplicate names.

    info.errorInfo

    info.errorInfo(error) now returns the error's ErrorClass and ErrorClasses.

    Source code(tar.gz)
    Source code(zip)
  • 4.1.1(Nov 8, 2022)

  • 4.1.0(Nov 7, 2022)

  • 4.0.0(Nov 6, 2022)

    Major features

    Plugins

    Features can now be extended using plugins.

    import modernErrors from 'modern-errors'
    
    import modernErrorsBugs from 'modern-errors-bugs'
    import modernErrorsCli from 'modern-errors-cli'
    
    export const AnyError = modernErrors([modernErrorsBugs, modernErrorsCli])
    

    CLI plugin

    The modern-errors-cli plugin handles CLI errors.

    Process errors

    The modern-errors-process plugin handles process errors.

    Clean stack traces

    The modern-errors-stack plugin automatically cleans up stack traces.

    HTTP responses

    The modern-errors-http plugin converts errors to plain objects to use in an HTTP response.

    Error logging (Winston)

    The modern-errors-winston plugin logs errors with Winston.

    Subclasses

    Error subclasses can now be created using ErrorClass.subclass() to share custom logic and options between classes.

    const SharedError = AnyError.subclass('SharedError', {
      custom: class extends AnyError {
        // ...
      },
    })
    
    export const InputError = SharedError.subclass('InputError')
    export const AuthError = SharedError.subclass('AuthError')
    

    Improved options

    Options can now be applied to any error.

    export const AnyError = modernErrors(plugins, options)
    

    Or to any error of a specific class.

    export const InputError = AnyError.subclass('InputError', options)
    

    Or to multiple classes.

    export const SharedError = AnyError.subclass('SharedError', options)
    
    export const InputError = SharedError.subclass('InputError')
    export const AuthError = SharedError.subclass('AuthError')
    

    Or to a specific error.

    throw new InputError('...', options)
    

    Or to a specific plugin method call, passing only that plugin's options.

    AnyError[methodName](...args, options[pluginName])
    
    error[methodName](...args, options[pluginName])
    

    Aggregate errors

    The errors option can now be used to aggregate multiple errors into one, similarly to new AggregateError(errors).

    Breaking changes

    Creating error classes

    The main function now returns the base error class AnyError.

    AnyError.subclass(name) must be used to create each error class. The first one must now be named UnknownError.

    Before:

    export const {
      // Custom error classes
      InputError,
      AuthError,
      DatabaseError,
      // Error handler
      errorHandler,
    } = modernErrors(['InputError', 'AuthError', 'DatabaseError'])
    

    After:

    // Base error class
    export const AnyError = modernErrors()
    
    export const UnknownError = AnyError.subclass('UnknownError')
    export const InputError = AnyError.subclass('InputError')
    export const AuthError = AnyError.subclass('AuthError')
    export const DatabaseError = AnyError.subclass('DatabaseError')
    

    Error handler

    errorHandler() has been renamed to AnyError.normalize().

    Before:

    const { errorHandler } = modernErrors(errorNames)
    
    const normalizedError = errorHandler(error)
    

    After:

    const AnyError = modernErrors()
    
    const normalizedError = AnyError.normalize(error)
    

    Custom classes

    Error classes can now be fully customized using the custom option: constructors, methods, etc. This replaces the previous onCreate option.

    Before:

    modernErrors({
      onCreate(error, options) {
        const { filePath } = options
    
        if (typeof filePath !== 'string') {
          throw new TypeError('filePath must be a string.')
        }
    
        error.filePath = filePath
      },
    })
    

    After:

    export const InputError = AnyError.subclass('InputError', {
      custom: class extends AnyError {
        constructor(message, options = {}) {
          super(message, options)
    
          const { filePath } = options
    
          if (typeof filePath !== 'string') {
            throw new TypeError('filePath must be a string.')
          }
    
          this.filePath = filePath
        }
      },
    })
    

    Error properties

    Error properties must now be set using props.{propName} instead of {propName}.

    Before:

    throw new InputError('...', { filePath: '/path' })
    

    After:

    throw new InputError('...', { props: { filePath: '/path' } })
    

    Bug reports

    The bugsUrl option has been renamed to bugs. It cannot be a function anymore. It also requires adding the modern-errors-bugs plugin.

    A few bug fixes related to using the bugs option twice have also been fixed.

    Before:

    throw new InputError('...', {
      bugsUrl: 'https://github.com/my-name/my-project/issues',
    })
    

    After:

    throw new InputError('...', {
      bugs: 'https://github.com/my-name/my-project/issues',
    })
    

    Serialization/parsing

    parse() has been renamed to AnyError.parse(). AnyError.parse() and error.toJSON() also require adding the modern-errors-serialize plugin.

    Serialization and parsing now recurse deeply over objects and arrays.

    Before:

    const { parse } = modernErrors(errorNames)
    
    const errorObject = JSON.parse(errorString)
    const error = parse(errorObject)
    

    After:

    import modernErrorsSerialize from 'modern-errors-serialize'
    
    const AnyError = modernErrors([modernErrorsSerialize])
    
    const errorObject = JSON.parse(errorString)
    const error = AnyError.parse(errorObject)
    

    Error wrapping

    To wrap an error without changing its class, AnyError must now be used instead of Error. When wrapping an error, its cause and bugs are now merged right away, instead of when AnyError.normalize() is called.

    Before:

    throw new Error('Could not read the file.', { cause })
    

    After:

    throw new AnyError('Could not read the file.', { cause })
    

    Checking error classes

    We now recommend using instanceof instead of error.name to check error classes.

    Before:

    if (error.name === 'InputError') {
      // ...
    }
    

    After:

    if (error instanceof InputError) {
      // ...
    }
    

    AnyError can now be used to check for any errors from a specific library.

    if (error instanceof AnyError) {
      // ...
    }
    

    TypeScript types

    TypeScript support has been greatly improved and is now fully tested. Most types have changed: if you were using them, please check the new documentation here.

    Exporting error classes

    Error classes should now be exported to be re-used across modules.

    License

    Switch to MIT license.

    Source code(tar.gz)
    Source code(zip)
  • 3.1.1(Aug 22, 2022)

  • 3.1.0(Aug 21, 2022)

  • 3.0.0(Aug 21, 2022)

  • 2.0.2(Aug 21, 2022)

  • 2.0.1(Aug 20, 2022)

  • 2.0.0(Aug 20, 2022)

  • 1.5.0(Aug 20, 2022)

  • 1.4.1(Aug 17, 2022)

  • 1.4.0(Aug 16, 2022)

  • 1.3.0(Jul 24, 2022)

  • 1.2.0(Jul 16, 2022)

  • 1.1.2(Jun 20, 2022)

  • 1.1.1(Jun 20, 2022)

    • Upgrade merge-error-cause 1.1.4 -> 1.1.5 (c31d89c)
    • Upgrade merge-error-cause 1.1.3 -> 1.1.4 (5db0993)
    • Upgrade error-cause-polyfill 1.0.0 -> 1.0.1 (5673c6b)
    • Update README (319f10c)
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Jun 19, 2022)

  • 1.0.2(Jun 17, 2022)

  • 1.0.1(Jun 16, 2022)

    • Add logo (5e37eb3)
    • Upgrade merge-error-cause 1.1.2 -> 1.1.3 (1acf68d)
    • Upgrade error-type 1.1.8 -> 1.1.9 (fca7f8d)
    • Update README (ec6cb84)
    • Update README (9e87bd9)
    • Update README (84582dd)
    • Update README (f78adc9)
    • Update README (65b1d95)
    • Update README (5704fd5)
    • Update README (f97d591)
    • Add emoji (93434b5)
    • Update keywords (1f9bbd7)
    • Update README (cf05196)
    • Add types documentation (71a75cd)
    • Update README (50013d7)
    • Upgrade merge-error-cause 1.1.1 -> 1.1.2 (1cf159d)
    • Upgrade is-plain-obj 4.0.0 -> 4.1.0 (f9d92df)
    • Update README (ac98205)
    • Update README (db4ba87)
    • Update README (8ebfa12)
    • Update README (2599c4b)
    • Update README (c66f5f1)
    • Update README (5e84b83)
    • Update README (0b9455a)
    • Update README (c6afcbd)
    • Update README (23a2c26)
    • Update README (41fb467)
    • Update README (dbe5ed2)
    • Update README (654090b)
    • Update README (14f0775)
    • Update README (dbe81fc)
    • Update README (2f9731d)
    • Update README (ca55a90)
    • Update README (c4f8ad2)
    • Update README (ae6106f)
    • Update README (687bc12)
    • Update README (0129156)
    • Update README (90e9e7a)
    • Update README (6bb4dae)
    • Improve README (a5d6518)
    • Improve tests (b3e4848)
    • Improve type tests (4a2e401)
    • Improve types (39d98ed)
    • Upgrade error-type 1.1.7 -> 1.1.8 (568ac2c)
    • Improve API (dc1b71a)
    • Upgrade merge-error-cause 1.1.0 -> 1.1.1 (d8fa07a)
    • Upgrade error-type 1.1.6 -> 1.1.7 (ca3bd97)
    • Improve types (c578f3e)
    • Upgrade error-type 1.1.5 -> 1.1.6 (b6ab48d)
    • Upgrade error-type 1.1.4 -> 1.1.5 (7f6d900)
    • Refactoring (051a0d4)
    • Improve types (61b74b9)
    • Improve types (73c966e)
    • Upgrade error-type 1.1.3 -> 1.1.4 (3580be0)
    • Upgrade error-type 1.1.2 -> 1.1.3 (31ba56a)
    • Start fixing types (0820cc8)
    • Add test (70ab921)
    • Use a Proxy (51cece6)
    • Add comment (536c443)
    • Rename onError to errorHandler (7eb6687)
    • Add comment (d1c9220)
    • Remove support for child error types (58c8803)
    • Use is-plain-obj (19598b8)
    • Upgrade merge-error-cause 1.0.0 -> 1.1.0 (6ee21c8)
    • Upgrade error-type 1.1.1 -> 1.1.2 (1831396)
    • License 2021 -> 2022 (cf55bf2)
    • Upgrade error-type 1.1.0 -> 1.1.1 (57aad36)
    • Upgrade error-type 1.0.1 -> 1.1.0 (d5e4c89)
    • Allow bugsUrl to be a URL (2b145cd)
    • Add tests (29db173)
    • Add tests (fb6419b)
    • Add tests (d57ced9)
    • Add test (8e80a57)
    • Simplify tests (04081a8)
    • Add more tests (6947f69)
    • Add more tests (003edad)
    • Fix tags (c9f86be)
    • Initial commit (474f05f)
    Source code(tar.gz)
    Source code(zip)
Owner
ehmicky
Node.js back-end developer
ehmicky
It's a repository to studies. Its idea is to learn about Nx and its plugins.

StudyingNx This project was generated using Nx. ?? Smart, Fast and Extensible Build System Adding capabilities to your workspace Nx supports many plug

Open-ish 4 May 13, 2022
Can see everything, beware of its omniscience, kneel before its greatness.

Can see everything, beware of its omniscience, kneel before its greatness. Summary Presentation Installation Removing Credits Presentation Main goal T

Duc Justin 3 Sep 30, 2022
A cross-platform AutoHotKey-like thing with TypeScript as its scripting language

suchibot A cross-platform AutoHotKey-like thing with JavaScript/TypeScript as its scripting language. Built on top of uiohook-napi and nut.js. Install

Lily Scott 79 Sep 21, 2022
A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.

Amuchina A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebW

Fabio Spampinato 9 Sep 17, 2022
Some process handle JavaScript function parameter.

Function parameter handle or paremeter error control Example 1: Just checking if all arguments were passed / defined. const required = (name) => {

Md. Nazmul Islam 4 Mar 14, 2022
A set of useful helper methods for writing functions to handle Cloudflare Pub/Sub messages (https://developers.cloudflare.com/pub-sub/)

pubsub A set of useful helper methods for writing functions to handle Cloudflare Pub/Sub messages. This includes: A isValidBrokerRequest helper for au

Cloudflare 18 Dec 4, 2022
A Discord.JS Command Handler to handle commands eaiser

TABLE OF CONTENTS Installation Setup Changing Default Prefix Creating a Command Usage of minArgs and maxArgs Syntax Errors Global Syntax Errors Per Co

AaTherf 3 Jun 8, 2022
Helper package to handle requests to a jschan api instance.

jschan-api-sdk Helper package to handle requests to a jschan api instance. How to use npm install ussaohelcim/jschan-api-sdk const { jschan } = requir

Michell 3 Jun 30, 2022
Small TS library to type and safely handle `serde` JSON serializations of Rust enums.

rustie-ts TypeScript library with helper types and functions to type-safely handle Rust's serde JSON serialization of Enums. It can also be used stand

Kelvin Steiner Santos 4 Jul 17, 2022
This is just a script I put together to check and notify me via email (MailGun) when there's an earlier date before my initial appointment date. It doesn't handle rescheduling.

US-visa-appointment-notifier This is just a script I put together to check and notify me via email (MailGun) when there's an earlier date before my in

Theophilus Omoregbee 13 Jan 4, 2023