"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasPersistedQueryError = exports.formatApolloErrors = exports.UserInputError = exports.PersistedQueryNotSupportedError = exports.PersistedQueryNotFoundError = exports.ForbiddenError = exports.AuthenticationError = exports.ValidationError = exports.SyntaxError = exports.fromGraphQLError = exports.toApolloError = exports.ApolloError = void 0;
const graphql_1 = require("graphql");
class ApolloError extends Error {
    constructor(message, code, extensions) {
        super(message);
        if (extensions) {
            Object.keys(extensions)
                .filter(keyName => keyName !== 'message' && keyName !== 'extensions')
                .forEach(key => {
                this[key] = extensions[key];
            });
        }
        if (!this.name) {
            Object.defineProperty(this, 'name', { value: 'ApolloError' });
        }
        const userProvidedExtensions = (extensions && extensions.extensions) || null;
        this.extensions = Object.assign(Object.assign(Object.assign({}, extensions), userProvidedExtensions), { code });
    }
}
exports.ApolloError = ApolloError;
function enrichError(error, debug = false) {
    const expanded = Object.create(Object.getPrototypeOf(error), {
        name: {
            value: error.name,
        },
        message: {
            value: error.message,
            enumerable: true,
            writable: true,
        },
        locations: {
            value: error.locations || undefined,
            enumerable: true,
        },
        path: {
            value: error.path || undefined,
            enumerable: true,
        },
        nodes: {
            value: error.nodes || undefined,
        },
        source: {
            value: error.source || undefined,
        },
        positions: {
            value: error.positions || undefined,
        },
        originalError: {
            value: error.originalError,
        },
    });
    expanded.extensions = Object.assign(Object.assign({}, error.extensions), { code: (error.extensions && error.extensions.code) || 'INTERNAL_SERVER_ERROR', exception: Object.assign(Object.assign({}, (error.extensions && error.extensions.exception)), error.originalError) });
    delete expanded.extensions.exception.extensions;
    if (debug && !expanded.extensions.exception.stacktrace) {
        expanded.extensions.exception.stacktrace =
            (error.originalError &&
                error.originalError.stack &&
                error.originalError.stack.split('\n')) ||
                (error.stack && error.stack.split('\n'));
    }
    if (Object.keys(expanded.extensions.exception).length === 0) {
        delete expanded.extensions.exception;
    }
    return expanded;
}
function toApolloError(error, code = 'INTERNAL_SERVER_ERROR') {
    let err = error;
    if (err.extensions) {
        err.extensions.code = code;
    }
    else {
        err.extensions = { code };
    }
    return err;
}
exports.toApolloError = toApolloError;
function fromGraphQLError(error, options) {
    const copy = options && options.errorClass
        ? new options.errorClass(error.message)
        : new ApolloError(error.message);
    Object.keys(error).forEach(key => {
        copy[key] = error[key];
    });
    copy.extensions = Object.assign(Object.assign({}, copy.extensions), error.extensions);
    if (!copy.extensions.code) {
        copy.extensions.code = (options && options.code) || 'INTERNAL_SERVER_ERROR';
    }
    Object.defineProperty(copy, 'originalError', { value: {} });
    Object.getOwnPropertyNames(error).forEach(key => {
        Object.defineProperty(copy.originalError, key, { value: error[key] });
    });
    return copy;
}
exports.fromGraphQLError = fromGraphQLError;
class SyntaxError extends ApolloError {
    constructor(message) {
        super(message, 'GRAPHQL_PARSE_FAILED');
        Object.defineProperty(this, 'name', { value: 'SyntaxError' });
    }
}
exports.SyntaxError = SyntaxError;
class ValidationError extends ApolloError {
    constructor(message) {
        super(message, 'GRAPHQL_VALIDATION_FAILED');
        Object.defineProperty(this, 'name', { value: 'ValidationError' });
    }
}
exports.ValidationError = ValidationError;
class AuthenticationError extends ApolloError {
    constructor(message) {
        super(message, 'UNAUTHENTICATED');
        Object.defineProperty(this, 'name', { value: 'AuthenticationError' });
    }
}
exports.AuthenticationError = AuthenticationError;
class ForbiddenError extends ApolloError {
    constructor(message) {
        super(message, 'FORBIDDEN');
        Object.defineProperty(this, 'name', { value: 'ForbiddenError' });
    }
}
exports.ForbiddenError = ForbiddenError;
class PersistedQueryNotFoundError extends ApolloError {
    constructor() {
        super('PersistedQueryNotFound', 'PERSISTED_QUERY_NOT_FOUND');
        Object.defineProperty(this, 'name', {
            value: 'PersistedQueryNotFoundError',
        });
    }
}
exports.PersistedQueryNotFoundError = PersistedQueryNotFoundError;
class PersistedQueryNotSupportedError extends ApolloError {
    constructor() {
        super('PersistedQueryNotSupported', 'PERSISTED_QUERY_NOT_SUPPORTED');
        Object.defineProperty(this, 'name', {
            value: 'PersistedQueryNotSupportedError',
        });
    }
}
exports.PersistedQueryNotSupportedError = PersistedQueryNotSupportedError;
class UserInputError extends ApolloError {
    constructor(message, properties) {
        super(message, 'BAD_USER_INPUT', properties);
        Object.defineProperty(this, 'name', { value: 'UserInputError' });
    }
}
exports.UserInputError = UserInputError;
function formatApolloErrors(errors, options) {
    if (!options) {
        return errors.map(error => enrichError(error));
    }
    const { formatter, debug } = options;
    const enrichedErrors = errors.map(error => enrichError(error, debug));
    const makePrintable = error => {
        if (error instanceof Error) {
            const graphQLError = error;
            return Object.assign(Object.assign(Object.assign({ message: graphQLError.message }, (graphQLError.locations && { locations: graphQLError.locations })), (graphQLError.path && { path: graphQLError.path })), (graphQLError.extensions && { extensions: graphQLError.extensions }));
        }
        return error;
    };
    if (!formatter) {
        return enrichedErrors;
    }
    return enrichedErrors.map(error => {
        try {
            return makePrintable(formatter(error));
        }
        catch (err) {
            if (debug) {
                return enrichError(err, debug);
            }
            else {
                const newError = fromGraphQLError(new graphql_1.GraphQLError('Internal server error'));
                return enrichError(newError, debug);
            }
        }
    });
}
exports.formatApolloErrors = formatApolloErrors;
function hasPersistedQueryError(errors) {
    return Array.isArray(errors)
        ? errors.some(error => error instanceof PersistedQueryNotFoundError ||
            error instanceof PersistedQueryNotSupportedError)
        : false;
}
exports.hasPersistedQueryError = hasPersistedQueryError;
//# sourceMappingURL=index.js.map