"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateHttpErrorClass = exports.HttpError = exports.generateHttpErrorUri = void 0;
const RepresentationMetadata_1 = require("../../http/representation/RepresentationMetadata");
const TermUtil_1 = require("../TermUtil");
const Vocabularies_1 = require("../Vocabularies");
const ErrorUtil_1 = require("./ErrorUtil");
/**
 * Returns a URI that is unique for the given status code.
 */
function generateHttpErrorUri(statusCode) {
    return (0, TermUtil_1.toNamedTerm)(`${Vocabularies_1.SOLID_ERROR.namespace}H${statusCode}`);
}
exports.generateHttpErrorUri = generateHttpErrorUri;
/**
 * A class for all errors that could be thrown by Solid.
 * All errors inheriting from this should fix the status code thereby hiding the HTTP internals from other components.
 */
class HttpError extends Error {
    statusCode;
    cause;
    errorCode;
    metadata;
    /**
     * Creates a new HTTP error. Subclasses should call this with their fixed status code.
     * @param statusCode - HTTP status code needed for the HTTP response.
     * @param name - Error name. Useful for logging and stack tracing.
     * @param message - Error message.
     * @param options - Optional options.
     */
    constructor(statusCode, name, message, options = {}) {
        super(message);
        this.statusCode = statusCode;
        this.name = name;
        this.cause = options.cause;
        this.errorCode = options.errorCode ?? `H${statusCode}`;
        this.metadata = options.metadata ?? new RepresentationMetadata_1.RepresentationMetadata();
        this.generateMetadata();
    }
    static isInstance(error) {
        return (0, ErrorUtil_1.isError)(error) &&
            typeof error.statusCode === 'number' &&
            Boolean(error.metadata);
    }
    /**
     * Initializes the error metadata.
     */
    generateMetadata() {
        this.metadata.add(Vocabularies_1.SOLID_ERROR.terms.errorResponse, generateHttpErrorUri(this.statusCode));
        this.metadata.add(Vocabularies_1.HTTP.terms.statusCodeNumber, (0, TermUtil_1.toLiteral)(this.statusCode, Vocabularies_1.XSD.terms.integer));
    }
}
exports.HttpError = HttpError;
/**
 * Generates a new HttpError class with the given status code and name.
 * In general, status codes are used to uniquely identify error types,
 * so there should be no 2 classes with the same value there.
 *
 * To make sure Components.js can work with these newly generated classes,
 * the generated class should be called `BaseHttpError` as that name is an entry in `.componentsignore`.
 * The actual class should then extend `BaseHttpError` and have a correct constructor,
 * so the Components.js generator can generate the correct components JSON-LD file during build.
 */
function generateHttpErrorClass(statusCode, name) {
    return class SpecificHttpError extends HttpError {
        static statusCode = statusCode;
        static uri = generateHttpErrorUri(statusCode);
        constructor(message, options) {
            super(statusCode, name, message, options);
        }
        static isInstance(error) {
            return HttpError.isInstance(error) && error.statusCode === statusCode;
        }
    };
}
exports.generateHttpErrorClass = generateHttpErrorClass;
//# sourceMappingURL=HttpError.js.map