<commit_before>import LocalForage from 'localforage';
import MediaProxy from '../../valueObjects/MediaProxy';
import { Base64 } from 'js-base64';
import { BRANCH } from '../constants';

export default class API {
  constructor(token, url, branch) {
    this.token = token;
    this.url = url;
    this.branch = branch;
    this.repoURL = '';
  }

  requestHeaders(headers = {}) {
    return {
      Authorization: `Bearer ${this.token}`,
      'Content-Type': 'application/json',
      ...headers
    };
  }

  parseJsonResponse(response) {
    return response.json().then((json) => {
      if (!response.ok) {
        return Promise.reject(json);
      }

      return json;
    });
  }

  urlFor(path, options) {
    const params = [];
    if (options.params) {
      for (const key in options.params) {
        params.push(`${key}=${encodeURIComponent(options.params[key])}`);
      }
    }
    if (params.length) {
      path += `?${params.join('&')}`;
    }
    return this.url + path;
  }

  request(path, options = {}) {
    const headers = this.requestHeaders(options.headers || {});
    const url = this.urlFor(path, options);
    return fetch(url, { ...options, headers: headers }).then((response) => {
      if (response.headers.get('Content-Type').match(/json/) && !options.raw) {
        return this.parseJsonResponse(response);
      }

      return response.text();
    });
  }

  checkMetadataRef() {
    return this.request(`${this.repoURL}/git/refs/meta/_netlify_cms?${Date.now()}`, {
      cache: 'no-store',
    })
    .then(response => response.object)
    .catch(error => {
      // Meta ref doesn't exist
      const readme = {
        raw: '# Netlify CMS\n\nThis tree is used by the Netlify CMS to store metadata information for specific files and branches.'
      };

      return this.uploadBlob(readme)
      .then(item => this.request(`${this.repoURL}/git/trees`, {
        method: 'POST',
        body: JSON.stringify({ tree: [{ path: 'README.md', mode: '100644', type: 'blob', sha: item.sha }] })
      }))
      .then(tree => this.commit('First Commit', tree))
      .then(response => this.createRef('meta', '_netlify_cms', response.sha))
      .then(response => response.object);
    });
  }

  storeMetadata(key, data) {
    return this.checkMetadataRef()
    .then((branchData) => {
      const fileTree = {
        [`${key}.json`]: {
          path: `${key}.json`,
          raw: JSON.stringify(data),
          file: true
        }
      };

      return this.uploadBlob(fileTree[`${key}.json`])
      .then(item => this.updateTree(branchData.sha, '/', fileTree))
      .then(changeTree => this.commit(`Updating “${key}” metadata`, changeTree))
      .then(response => this.patchRef('meta', '_netlify_cms', response.sha));
    });
  }

  retrieveMetadata(key, data) {
    const cache = LocalForage.getItem(`gh.meta.${key}`);
    return cache.then((cached) => {
      if (cached && cached.expires > Date.now()) { return cached.data; }

      return this.request(`${this.repoURL}/files/${key}.json?ref=refs/meta/_netlify_cms`, {
        headers: { Accept: 'application/vnd.github.VERSION.raw' },
        cache: 'no-store',
      }).then((result) => {
        LocalForage.setItem(`gh.meta.${key}`, {
          expires: Date.now() + 300000, // In 5 minutes
          data: result,
        });
        return result;
      });
    });
  }

  readFile(path, sha) {
    const cache = sha ? LocalForage.getItem(`gh.${sha}`) : Promise.resolve(null);
    return cache.then((cached) => {
      if (cached) { return cached; }

      return this.request(`${this.repoURL}/files/${path}`, {
        headers: { Accept: 'application/vnd.github.VERSION.raw' },
        params: { ref: this.branch },
        cache: false,
        raw: true
      }).then((result) => {
        if (sha) {
          LocalForage.setItem(`gh.${sha}`, result);
        }

        return result;
      });
    });
  }

  listFiles(path) {
    return this.request(`${this.repoURL}/files/${path}`, {
      params: { ref: this.branch }
    });
  }

  persistFiles(entry, mediaFiles, options) {
    let filename, part, parts, subtree;
    const fileTree = {};<commit_msg>Fix content type for file requests<commit_after>import LocalForage from 'localforage';
import MediaProxy from '../../valueObjects/MediaProxy';
import { Base64 } from 'js-base64';
import { BRANCH } from '../constants';

export default class API {
  constructor(token, url, branch) {
    this.token = token;
    this.url = url;
    this.branch = branch;
    this.repoURL = '';
  }

  requestHeaders(headers = {}) {
    return {
      Authorization: `Bearer ${this.token}`,
      'Content-Type': 'application/json',
      ...headers
    };
  }

  parseJsonResponse(response) {
    return response.json().then((json) => {
      if (!response.ok) {
        return Promise.reject(json);
      }

      return json;
    });
  }

  urlFor(path, options) {
    const params = [];
    if (options.params) {
      for (const key in options.params) {
        params.push(`${key}=${encodeURIComponent(options.params[key])}`);
      }
    }
    if (params.length) {
      path += `?${params.join('&')}`;
    }
    return this.url + path;
  }

  request(path, options = {}) {
    const headers = this.requestHeaders(options.headers || {});
    const url = this.urlFor(path, options);
    return fetch(url, { ...options, headers: headers }).then((response) => {
      if (response.headers.get('Content-Type').match(/json/) && !options.raw) {
        return this.parseJsonResponse(response);
      }

      return response.text();
    });
  }

  checkMetadataRef() {
    return this.request(`${this.repoURL}/git/refs/meta/_netlify_cms?${Date.now()}`, {
      cache: 'no-store',
    })
    .then(response => response.object)
    .catch(error => {
      // Meta ref doesn't exist
      const readme = {
        raw: '# Netlify CMS\n\nThis tree is used by the Netlify CMS to store metadata information for specific files and branches.'
      };

      return this.uploadBlob(readme)
      .then(item => this.request(`${this.repoURL}/git/trees`, {
        method: 'POST',
        body: JSON.stringify({ tree: [{ path: 'README.md', mode: '100644', type: 'blob', sha: item.sha }] })
      }))
      .then(tree => this.commit('First Commit', tree))
      .then(response => this.createRef('meta', '_netlify_cms', response.sha))
      .then(response => response.object);
    });
  }

  storeMetadata(key, data) {
    return this.checkMetadataRef()
    .then((branchData) => {
      const fileTree = {
        [`${key}.json`]: {
          path: `${key}.json`,
          raw: JSON.stringify(data),
          file: true
        }
      };

      return this.uploadBlob(fileTree[`${key}.json`])
      .then(item => this.updateTree(branchData.sha, '/', fileTree))
      .then(changeTree => this.commit(`Updating “${key}” metadata`, changeTree))
      .then(response => this.patchRef('meta', '_netlify_cms', response.sha));
    });
  }

  retrieveMetadata(key, data) {
    const cache = LocalForage.getItem(`gh.meta.${key}`);
    return cache.then((cached) => {
      if (cached && cached.expires > Date.now()) { return cached.data; }

      return this.request(`${this.repoURL}/files/${key}.json?ref=refs/meta/_netlify_cms`, {
        headers: { 'Content-Type': 'application/vnd.netlify.raw' },
        cache: 'no-store',
      }).then((result) => {
        LocalForage.setItem(`gh.meta.${key}`, {
          expires: Date.now() + 300000, // In 5 minutes
          data: result,
        });
        return result;
      });
    });
  }

  readFile(path, sha) {
    const cache = sha ? LocalForage.getItem(`gh.${sha}`) : Promise.resolve(null);
    return cache.then((cached) => {
      if (cached) { return cached; }

      return this.request(`${this.repoURL}/files/${path}`, {
        headers: { 'Content-Type': 'application/vnd.netlify.raw' },
        params: { ref: this.branch },
        cache: false,
        raw: true
      }).then((result) => {
        if (sha) {
          LocalForage.setItem(`gh.${sha}`, result);
        }

        return result;
      });
    });
  }

  listFiles(path) {
    return this.request(`${this.repoURL}/files/${path}`, {
      params: { ref: this.branch }
    });
  }

  persistFiles(entry, mediaFiles, options) {
    let filename, part, parts, subtree;
    const fileTree = {};
{'fraction_non_alphanumeric': 0.178070701018574, 'fraction_numerical': 0.004074295985620132, 'mean_word_length': 2.5244932432432434, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, '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': '1761391', 'n_tokens_mistral': 2682, 'n_tokens_neox': 2631, 'n_words': 517}