<commit_before>import { GraphQLError } from 'graphql';
import { LogStep, LogAction, LogMessage, LogFunction } from './logging';

export class ApolloError extends Error {
  public extensions;
  constructor(
    message: string,
    code?: string,
    properties?: Record<string, any>,
  ) {
    super(message);

    if (properties) {
      Object.keys(properties).forEach(key => {
        this[key] = properties[key];
      });
    }

    //extensions are flattened to be included in the root of GraphQLError's, so
    //don't add properties to extensions
    this.extensions = { code };
  }
}

export function enrichError(error: GraphQLError, debug: boolean = false) {
  const expanded: GraphQLError = {
    message: error.message,
    path: error.path,
    locations: error.locations,
    ...error,
    extensions: {
      ...error.extensions,
      code:
        (error.extensions && error.extensions.code) || 'INTERNAL_SERVER_ERROR',
      exception: {
        ...(error.extensions && error.extensions.exception),
        ...(error.originalError as any),
      },
    },
  };

  //ensure that extensions is not taken from the originalError
  //graphql-js ensures that the originalError's extensions are hoisted
  //https://github.com/graphql/graphql-js/blob/0bb47b2/src/error/GraphQLError.js#L138
  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) {
    //remove from printing an empty object
    delete expanded.extensions.exception;
  }

  return expanded;
}

export function toApolloError(
  error: Error,
  code: string = 'INTERNAL_SERVER_ERROR',
): Error & { extensions: Record<string, any> } {
  let err: GraphQLError = error;
  if (err.extensions) {
    err.extensions.code = code;
  } else {
    err.extensions = { code };
  }
  return err as Error & { extensions: Record<string, any> };
}

export interface ErrorOptions {
  code?: string;
  errorClass?: typeof ApolloError;
}

export function fromGraphQLError(error: GraphQLError, options?: ErrorOptions) {
  const copy: GraphQLError =
    options && options.errorClass
      ? new options.errorClass(error.message)
      : new ApolloError(error.message);

  //copy enumerable keys
  Object.keys(error).forEach(key => {
    copy[key] = error[key];
  });

  //extensions are non enumerable, so copy them directly
  copy.extensions = {
    ...copy.extensions,
    ...error.extensions,
  };

  //Fallback on default for code
  if (!copy.extensions.code) {
    copy.extensions.code = (options && options.code) || 'INTERNAL_SERVER_ERROR';
  }

  //copy the original error, while keeping all values non-enumerable, so they
  //are not printed unless directly referenced
  Object.defineProperty(copy, 'originalError', { value: {} });
  Reflect.ownKeys(error).forEach(key => {
    Object.defineProperty(copy.originalError, key, { value: error[key] });
  });

  return copy;
}

export class SyntaxError extends ApolloError {
  // TODO make the name nonenumerable
  // name = 'SyntaxError';
  constructor(message: string) {
    super(message, 'GRAPHQL_PARSE_FAILED');
  }<commit_msg>apollo-server-core: use getOwnPropertyNames to stay es5<commit_after>import { GraphQLError } from 'graphql';
import { LogStep, LogAction, LogMessage, LogFunction } from './logging';

export class ApolloError extends Error {
  public extensions;
  constructor(
    message: string,
    code?: string,
    properties?: Record<string, any>,
  ) {
    super(message);

    if (properties) {
      Object.keys(properties).forEach(key => {
        this[key] = properties[key];
      });
    }

    //extensions are flattened to be included in the root of GraphQLError's, so
    //don't add properties to extensions
    this.extensions = { code };
  }
}

export function enrichError(error: GraphQLError, debug: boolean = false) {
  const expanded: GraphQLError = {
    message: error.message,
    path: error.path,
    locations: error.locations,
    ...error,
    extensions: {
      ...error.extensions,
      code:
        (error.extensions && error.extensions.code) || 'INTERNAL_SERVER_ERROR',
      exception: {
        ...(error.extensions && error.extensions.exception),
        ...(error.originalError as any),
      },
    },
  };

  //ensure that extensions is not taken from the originalError
  //graphql-js ensures that the originalError's extensions are hoisted
  //https://github.com/graphql/graphql-js/blob/0bb47b2/src/error/GraphQLError.js#L138
  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) {
    //remove from printing an empty object
    delete expanded.extensions.exception;
  }

  return expanded;
}

export function toApolloError(
  error: Error,
  code: string = 'INTERNAL_SERVER_ERROR',
): Error & { extensions: Record<string, any> } {
  let err: GraphQLError = error;
  if (err.extensions) {
    err.extensions.code = code;
  } else {
    err.extensions = { code };
  }
  return err as Error & { extensions: Record<string, any> };
}

export interface ErrorOptions {
  code?: string;
  errorClass?: typeof ApolloError;
}

export function fromGraphQLError(error: GraphQLError, options?: ErrorOptions) {
  const copy: GraphQLError =
    options && options.errorClass
      ? new options.errorClass(error.message)
      : new ApolloError(error.message);

  //copy enumerable keys
  Object.keys(error).forEach(key => {
    copy[key] = error[key];
  });

  //extensions are non enumerable, so copy them directly
  copy.extensions = {
    ...copy.extensions,
    ...error.extensions,
  };

  //Fallback on default for code
  if (!copy.extensions.code) {
    copy.extensions.code = (options && options.code) || 'INTERNAL_SERVER_ERROR';
  }

  //copy the original error, while keeping all values non-enumerable, so they
  //are not printed unless directly referenced
  Object.defineProperty(copy, 'originalError', { value: {} });
  Object.getOwnPropertyNames(error).forEach(key => {
    Object.defineProperty(copy.originalError, key, { value: error[key] });
  });

  return copy;
}

export class SyntaxError extends ApolloError {
  // TODO make the name nonenumerable
  // name = 'SyntaxError';
  constructor(message: string) {
    super(message, 'GRAPHQL_PARSE_FAILED');
  }
{'fraction_non_alphanumeric': 0.12773776275172719, 'fraction_numerical': 0.0024988975452006467, 'mean_word_length': 3.3227445997458704, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6070266', 'n_tokens_mistral': 2063, 'n_tokens_neox': 1985, 'n_words': 497}