<commit_before>/**
 * @providesModule Orchard
 * @flow
 */

import { append, keys } from 'ramda'
import qs from 'qs'

type ErrorResponse = {
  [string]: string[],
}

export class Orchard {
  static harvest (endpoint: string, params: Object = {}): Promise<any> {
    const query = params
      ? `?${qs.stringify(params, { arrayFormat: 'brackets' })}`
      : ''
    const r = new Request(
      `${window.galaHostname || ''}/${
        window.i18n.locale
      }/${endpoint}.json${query}`,
      { credentials: 'same-origin' }
    )
    return fetch(r).then(handleResponse)
  }

  static graft (endpoint: string, params: Object): Promise<any> {
    const body = JSON.stringify(params)
    const r = new Request(`/${window.i18n.locale}/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'POST',
      body,
      headers: new Headers({
        Accept: 'application/json',
        'Content-Type': 'application/json',
      }),
    })
    return fetch(r).then(handleResponse)
  }

  // Train a fruit tree to grow into a desired figure.
  static espalier (endpoint: string, params: ?Object): Promise<any> {
    const body = JSON.stringify(params)
    const r = new Request(`/${window.i18n.locale}/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'PUT',
      body,
      headers: new Headers({
        Accept: 'application/json',
        'Content-Type': 'application/json',
      }),
    })
    return fetch(r).then(handleResponse)
  }

  static prune (endpoint: string): Promise<Response> {
    const r = new Request(`/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'DELETE',
      headers: new Headers({ Accept: 'application/json' }),
    })
    return fetch(r)
  }
}

function handleResponse (response: Response): Promise<any> {
  if (response.ok) {
    return response.json().catch(() => Promise.resolve(true))
  } else {
    return response.json().then((errorResponse: ErrorResponse) => {
      const errorFieldNames = keys(errorResponse)

      const errorMessages = errorFieldNames
        .reduce((all: string[], fieldName: string) => {
          const fieldErrors = errorResponse[fieldName]

          if (fieldErrors != null && Array.isArray(fieldErrors)) {
            return append(
              fieldErrors
                .map(<commit_msg>fix: include csrf token header in ajax calls<commit_after>/**
 * @providesModule Orchard
 * @flow
 */

import { append, keys } from 'ramda'
import qs from 'qs'

type ErrorResponse = {
  [string]: string[],
}

export class Orchard {
  static harvest (endpoint: string, params: Object = {}): Promise<any> {
    const query = params
      ? `?${qs.stringify(params, { arrayFormat: 'brackets' })}`
      : ''
    const r = new Request(
      `${window.galaHostname || ''}/${
        window.i18n.locale
      }/${endpoint}.json${query}`,
      { credentials: 'same-origin' }
    )
    return fetch(r).then(handleResponse)
  }

  static graft (endpoint: string, params: Object): Promise<any> {
    const body = JSON.stringify(params)
    const r = new Request(`/${window.i18n.locale}/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'POST',
      body,
      headers: new Headers({
        Accept: 'application/json',
        'Content-Type': 'application/json',
        ...csrfHeader(),
      }),
    })
    return fetch(r).then(handleResponse)
  }

  // Train a fruit tree to grow into a desired figure.
  static espalier (endpoint: string, params: ?Object): Promise<any> {
    const body = JSON.stringify(params)
    const r = new Request(`/${window.i18n.locale}/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'PUT',
      body,
      headers: new Headers({
        Accept: 'application/json',
        'Content-Type': 'application/json',
        ...csrfHeader(),
      }),
    })
    return fetch(r).then(handleResponse)
  }

  static prune (endpoint: string): Promise<Response> {
    const r = new Request(`/${endpoint}.json`, {
      credentials: 'same-origin',
      method: 'DELETE',
      headers: new Headers({ Accept: 'application/json', ...csrfHeader() }),
    })
    return fetch(r)
  }
}

function csrfHeader (): { [string]: string } {
  const token = getMetaContent('csrf-token')

  if (token == null) return {}
  return { 'X-CSRF-Token': token }
}

function getMetaContent (key: string): ?string {
  const meta = document.querySelector(`meta[name="${key}"]`)
  return meta && meta.getAttribute('content')
}

function handleResponse (response: Response): Promise<any> {
  if (response.ok) {
    return response.json().catch(() => Promise.resolve(true))
  } else {
    return response.json().then((errorResponse: ErrorResponse) => {
      const errorFieldNames = keys(errorResponse)

      const errorMessages = errorFieldNames
        .reduce((all: string[], fieldName: string) => {
          const fieldErrors = errorResponse[fieldName]

          if (fieldErrors != null && Array.isArray(fieldErrors)) {
            return append(
              fieldErrors
                .map(
{'fraction_non_alphanumeric': 0.1543957134352054, 'fraction_numerical': 0.0023814248858900575, 'mean_word_length': 2.8443935926773456, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 0, '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': '4017962', 'n_tokens_mistral': 1494, 'n_tokens_neox': 1490, 'n_words': 364}