codekie/openapi-examples-validator

View on GitHub
src/application-error.js

Summary

Maintainability
A
0 mins
Test Coverage
const
    merge = require('lodash.merge'),
    { ENOENT } = require('errno').code;

// TYPEDEFINITIONS

/**
 * @typedef {{}} CustomError
 * @augments Error
 */

/**
 * ApplicationErrorOptions
 * @typedef {{
 *      [instancePath]: string,
 *      [examplePath]: string,
 *      [exampleFilePath]: string,
 *      [keyword]: string,
 *      [message]: string,
 *      [mapFilePath]: string,
 *      [params]: {
 *          [path]: string,
 *          [missingProperty]: string,
 *          [type]: string
 *      },
 *      [schemaPath]: string
 * }} ApplicationErrorOptions
 */

// CONSTANTS

const ErrorType = {
    jsENOENT: ENOENT.code,
    jsonPathNotFound: 'JsonPathNotFound',
    errorAndErrorsMutuallyExclusive: 'ErrorErrorsMutuallyExclusive',
    parseError: 'ParseError',
    validation: 'Validation'
};

// CLASSES

/**
 * Unified application-error
 */
class ApplicationError {
    /**
     * Factory-function, which is able to consume validation-errors and JS-errors. If a validation error is passed, all
     * properties will be adopted.
     * @param {Error|CustomError}   err     Javascript-, validation- or custom-error, to create the application-error
     *                                      from
     * @returns {ApplicationError} Unified application-error instance
     */
    static create(err) {
        const { code, message, path, cause } = err,               // Certain properties of Javascript-errors
            type = code || err.type || ErrorType.validation,    // If `code` is available then it's a Javascript-error
            options = { message };
        if (ErrorType.validation === type || ErrorType.errorAndErrorsMutuallyExclusive === type) {
            // For certain, created error-types, copy all properties
            merge(options, err);
        } else {
            // Copy certain properties of Javascript-error (but only if available)
            path && merge(options, { params: { path } });
            cause && merge(options, cause);
        }
        return new ApplicationError(type, options);
    }

    /**
     * Constructor
     * @param {string}                  type        Type of error (see statics)
     * @param {ApplicationErrorOptions} [options]   Optional properties
     */
    constructor(type, options = {}) {
        Object.assign(this, {
            type,
            ...options
        });
    }
}

// PUBLIC API

module.exports = {
    ApplicationError,
    ErrorType
};