'use strict';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.hdbErrors = exports.AccessViolation = exports.Violation = exports.ServerError = exports.ClientError = exports.HdbError = void 0;
exports.handleHDBError = handleHDBError;
exports.isHDBError = isHDBError;
const harper_logger_ts_1 = __importDefault(require("../logging/harper_logger.js"));
const hdbErrors = __importStar(require("./commonErrors.js"));
exports.hdbErrors = hdbErrors;
const hdbTerms = __importStar(require("../hdbTerms.js"));
/**
 * Custom error class used for better error and log handling.  Caught errors that evaluate to an instanceof HdbError can
 * be handled differently - e.g. in most cases caught HdbError likely would not need to be logged since that should have
 * already been handled when the custom error was constructed.
 */
class HdbError extends Error {
    statusCode;
    http_resp_msg;
    type;
    logLevel;
    /**
     * @param {Error} errOrig -  Error to be translated into HdbError. If manually throwing an error, pass `new Error()` to ensure stack trace is maintained
     * @param {String} [httpMsg] - optional -  response message that will be returned via the API
     * @param {Number} [httpCode] - optional -  response status code that will be returned via the API
     * @param {String} [logLevel] - optional -  log level that will be used for logging of this error
     * @param {String} [logMsg] - optional - log message that, if provided, will be logged at the `logLevel` above
     */
    constructor(errOrig, httpMsg, httpCode, logLevel, logMsg) {
        super();
        //This line ensures the original stack trace is captured and does not include the 'handle' or 'constructor' methods
        Error.captureStackTrace(this, handleHDBError);
        this.statusCode = httpCode ? httpCode : hdbErrors.HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR;
        this.http_resp_msg = httpMsg
            ? httpMsg
            : hdbErrors.DEFAULT_ERROR_MSGS[httpCode]
                ? hdbErrors.DEFAULT_ERROR_MSGS[httpCode]
                : hdbErrors.DEFAULT_ERROR_MSGS[hdbErrors.HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR];
        this.message = errOrig.message ? errOrig.message : this.http_resp_msg;
        this.type = errOrig.name;
        if (logLevel)
            this.logLevel = logLevel;
        //This ensures that the error stack does not include [object Object] if the error message is not a string
        if (typeof this.message !== 'string') {
            this.stack = errOrig.stack;
        }
        if (logMsg) {
            harper_logger_ts_1.default[logLevel](logMsg);
        }
    }
}
exports.HdbError = HdbError;
class ClientError extends Error {
    statusCode;
    constructor(message, statusCode) {
        if (message instanceof Error) {
            message.statusCode = statusCode || 400;
            return message;
        }
        super(message);
        this.statusCode = statusCode || 400;
    }
}
exports.ClientError = ClientError;
class ServerError extends Error {
    statusCode;
    constructor(message, statusCode) {
        super(message);
        this.statusCode = statusCode || 500;
    }
}
exports.ServerError = ServerError;
/**
 * This handler method is used to effectively evaluate caught errors and either translates them into a custom HdbError or,
 * if it is already a HdbError, just returns the error to continue being thrown up the stack
 *
 * See above for params descriptions
 * @param e
 * @param httpMsg
 * @param httpCode
 * @param logLevel
 * @param logMsg
 * @param deleteStack
 * @returns {HdbError|*}
 */
function handleHDBError(e, httpMsg, httpCode, logLevel = hdbTerms.LOG_LEVELS.ERROR, logMsg = null, deleteStack = false) {
    if (isHDBError(e)) {
        return e;
    }
    const error = new HdbError(e, httpMsg, httpCode, logLevel, logMsg);
    // In some situations, such as validation errors, the stack does not need to be thrown/logged.
    if (deleteStack) {
        delete error.stack;
    }
    return error;
}
/**
 * Represents a general violation of validation/authorization. This is used in situations where we are performing
 * expected verification. Extends Error for TypeScript class compatibility.
 * @param {Object} user - user object that caused the access violation
 * @constructor
 */
class Violation extends Error {
    constructor(message) {
        super(message);
        this.name = this.constructor.name;
    }
}
exports.Violation = Violation;
/**
 * Represents an access violation. This is used to return a 403 or 401 response to the client.
 * @param {Object} user - user object that caused the access violation
 * @constructor
 */
class AccessViolation extends Violation {
    statusCode;
    constructor(user) {
        if (user) {
            super('Unauthorized access to resource');
            this.statusCode = 403;
        }
        else {
            super('Must login');
            this.statusCode = 401;
            // TODO: Optionally allow a Location header to redirect to
        }
    }
}
exports.AccessViolation = AccessViolation;
function isHDBError(e) {
    return e.__proto__.constructor.name === HdbError.name;
}
//# sourceMappingURL=hdbError.js.map