<commit_before>import axios from 'axios'
import { camel, deserialise, error, kebab, query, serialise, snake } from './util'

const kitsu = 'https://kitsu.io/api/edge'
const jsonAPI = 'application/vnd.api+json'
const jsonAPIHeader = { 'Accept': jsonAPI, 'Content-Type': jsonAPI }

/**
 * A simple framework agnostic JSON-API client JSON API
 *
 * @name Kitsu
 * @param {Object} options Options
 * @param {string} options.baseURL Set the API endpoint (default `https://kitsu.io/api/edge`)
 * @param {Object} options.headers Additional headers to send with requests
 * @param {boolean} options.camelCaseTypes If true, the `type` value will be camelCased, e.g `library-entries` and `library_entries` become `libraryEntries`  (default `true`)
 * @param {string} options.resourceCase `kebab`, `snake` or `none`. If `kebab`, `/libraryEntries` will become `/library-entries`. If `snake`, `/libraryEntries` will become `/library_entries`, If `none`, `/libraryEntries` will be unchanged (default `kebab`)
 * @param {boolean} options.pluralize If `true`, `/user` will become `/users` in the URL request and `type` will be pluralized in post, patch and delete requests - `user` -> `users` (default `true`)
 * @param {number} options.timeout Set the request timeout in milliseconds (default `30000`)
 *
 * @example
 * // If using Kitsu.io's API
 * const api = new Kitsu()
 *
 * @example
 * // If using another API server
 * const api = new Kitsu({
 *   baseURL: 'https://api.example.org/2'
 * })
 *
 * @example
 * // Set a `user-agent` and an `authorization` token
 * const api = new Kitsu({
 *   headers: {
 *     'User-Agent': 'MyApp/1.0.0 (github.com/username/repo)',
 *     Authorization: 'Bearer 1234567890'
 *   }
 * })
 */
export default class Kitsu {
  constructor (options = {}) {
    if (options.camelCaseTypes === false) this.camel = s => s
    else this.camel = camel

    if (options.resourceCase === 'none') this.resCase = s => s
    else if (options.resourceCase === 'snake') this.resCase = snake
    else this.resCase = kebab

    if (options.pluralize === false) this.plural = s => s
    else this.plural = require('pluralize')

    /**
     * Get the current headers or add additional headers
     *
     * @memberof Kitsu
     * @returns {Object} All the current headers
     *
     * @example
     * // Receive all the headers
     * api.headers
     *
     * @example
     * // Receive a specific header
     * api.headers['User-Agent']
     *
     * @example
     * // Add or update a header
     * api.headers['Authorization'] = 'Bearer <PASSWORD>'
     */
    this.headers = Object.assign({}, options.headers, jsonAPIHeader)

    axios.defaults.baseURL = options.baseURL || kitsu
    axios.defaults.timeout = options.timeout || 30000
  }

  /**
   * Check if the client is authenticated (oAuth2/Authorization header)
   *
   * @memberof Kitsu
   * @returns {boolean}
   *
   * @example
   * if (api.isAuth) console.log('Authenticated')
   * else console.log('Not authenticated')
   */
  get isAuth () {
    return Boolean(this.headers.Authorization)
  }

  /**
   * Fetch resources
   * Aliases: `fetch`
   *
   * @memberof Kitsu
   * @param {string} model Model to fetch data from
   * @param {Object} params JSON-API request queries
   * @param {Object} params.page jsonapi.org/format/#fetching-pagination
   * @param {number} params.page.limit Number of resources to return in request (Max `20` for Kitsu.io except on `libraryEntries` which has a max of `500`)
   * @param {number} params.page.offset Number of resources to offset the dataset by
   * @param {Object} params.fields Return a sparse fieldset with only the included attributes/relationships jsonapi.org/format/#fetching-sparse-fieldsets
   * @param {Object} params.filter Filter dataset by attribute values jsonapi.org/format/#fetching-filtering
   * @param {string} params.sort Sort dataset by one or more comma separated attributes (prepend `-` for descending order) jsonapi.org/format/#fetching-sorting
   * @param {string} params.include Include relationship data jsonapi.org/format/#fetching-includes
   * @param {Object} headers Additional headers to send with request
   * @returns {Object} JSON-parsed response
   *
   * @example
   * // Get a specific user's name & birthday
   * api.get('users', {
   *   fields: {
   *     users: 'name,birthday'
   *   },
   *   filter: {
   *     name: 'wopian'
   *   }
   * })
   *
   * @example
   * // Get a collection of anime resources and their categories
   * api.get('anime', {
   *   include: 'categories'
   * })
   *
   * @example
   * // Get a single resource and its relationships by ID (method one)
   * api.get('anime', {
   *   include: 'categories',
   *   filter: { id: '2' }
   * })
   *
   * @example
   * // Get a single resource and its relationships by ID (method two)
   * api.get('anime/2', {
   *   include: 'categories'
   * })
   *
   * @example
   * // Get a resource's relationship data only
   * api.get('anime/2/categories')
   */
  async get (model, params = {}, headers = {}) {
    try {
      const url = this.plural(this.resCase(model))
      const { data } = await axios.get(url, {
        params,
        paramsSerializer: p => query(p),
        headers: Object.assign(this.headers, headers, jsonAPIHeader)
      })

      return deserialise(data)<commit_msg>fix: prevent pluralising {baseURL}/resources/1 as {baseURL}/resource/1S<commit_after>import axios from 'axios'
import { camel, deserialise, error, kebab, query, serialise, snake } from './util'

const kitsu = 'https://kitsu.io/api/edge'
const jsonAPI = 'application/vnd.api+json'
const jsonAPIHeader = { 'Accept': jsonAPI, 'Content-Type': jsonAPI }

/**
 * A simple framework agnostic JSON-API client JSON API
 *
 * @name Kitsu
 * @param {Object} options Options
 * @param {string} options.baseURL Set the API endpoint (default `https://kitsu.io/api/edge`)
 * @param {Object} options.headers Additional headers to send with requests
 * @param {boolean} options.camelCaseTypes If true, the `type` value will be camelCased, e.g `library-entries` and `library_entries` become `libraryEntries`  (default `true`)
 * @param {string} options.resourceCase `kebab`, `snake` or `none`. If `kebab`, `/libraryEntries` will become `/library-entries`. If `snake`, `/libraryEntries` will become `/library_entries`, If `none`, `/libraryEntries` will be unchanged (default `kebab`)
 * @param {boolean} options.pluralize If `true`, `/user` will become `/users` in the URL request and `type` will be pluralized in post, patch and delete requests - `user` -> `users` (default `true`)
 * @param {number} options.timeout Set the request timeout in milliseconds (default `30000`)
 *
 * @example
 * // If using Kitsu.io's API
 * const api = new Kitsu()
 *
 * @example
 * // If using another API server
 * const api = new Kitsu({
 *   baseURL: 'https://api.example.org/2'
 * })
 *
 * @example
 * // Set a `user-agent` and an `authorization` token
 * const api = new Kitsu({
 *   headers: {
 *     'User-Agent': 'MyApp/1.0.0 (github.com/username/repo)',
 *     Authorization: 'Bearer 1234567890'
 *   }
 * })
 */
export default class Kitsu {
  constructor (options = {}) {
    if (options.camelCaseTypes === false) this.camel = s => s
    else this.camel = camel

    if (options.resourceCase === 'none') this.resCase = s => s
    else if (options.resourceCase === 'snake') this.resCase = snake
    else this.resCase = kebab

    if (options.pluralize === false) this.plural = s => s
    else this.plural = require('pluralize')

    /**
     * Get the current headers or add additional headers
     *
     * @memberof Kitsu
     * @returns {Object} All the current headers
     *
     * @example
     * // Receive all the headers
     * api.headers
     *
     * @example
     * // Receive a specific header
     * api.headers['User-Agent']
     *
     * @example
     * // Add or update a header
     * api.headers['Authorization'] = 'Bearer 1234567890'
     */
    this.headers = Object.assign({}, options.headers, jsonAPIHeader)

    axios.defaults.baseURL = options.baseURL || kitsu
    axios.defaults.timeout = options.timeout || 30000
  }

  /**
   * Check if the client is authenticated (oAuth2/Authorization header)
   *
   * @memberof Kitsu
   * @returns {boolean}
   *
   * @example
   * if (api.isAuth) console.log('Authenticated')
   * else console.log('Not authenticated')
   */
  get isAuth () {
    return Boolean(this.headers.Authorization)
  }

  /**
   * Fetch resources
   * Aliases: `fetch`
   *
   * @memberof Kitsu
   * @param {string} model Model to fetch data from
   * @param {Object} params JSON-API request queries
   * @param {Object} params.page jsonapi.org/format/#fetching-pagination
   * @param {number} params.page.limit Number of resources to return in request (Max `20` for Kitsu.io except on `libraryEntries` which has a max of `500`)
   * @param {number} params.page.offset Number of resources to offset the dataset by
   * @param {Object} params.fields Return a sparse fieldset with only the included attributes/relationships jsonapi.org/format/#fetching-sparse-fieldsets
   * @param {Object} params.filter Filter dataset by attribute values jsonapi.org/format/#fetching-filtering
   * @param {string} params.sort Sort dataset by one or more comma separated attributes (prepend `-` for descending order) jsonapi.org/format/#fetching-sorting
   * @param {string} params.include Include relationship data jsonapi.org/format/#fetching-includes
   * @param {Object} headers Additional headers to send with request
   * @returns {Object} JSON-parsed response
   *
   * @example
   * // Get a specific user's name & birthday
   * api.get('users', {
   *   fields: {
   *     users: 'name,birthday'
   *   },
   *   filter: {
   *     name: 'wopian'
   *   }
   * })
   *
   * @example
   * // Get a collection of anime resources and their categories
   * api.get('anime', {
   *   include: 'categories'
   * })
   *
   * @example
   * // Get a single resource and its relationships by ID (method one)
   * api.get('anime', {
   *   include: 'categories',
   *   filter: { id: '2' }
   * })
   *
   * @example
   * // Get a single resource and its relationships by ID (method two)
   * api.get('anime/2', {
   *   include: 'categories'
   * })
   *
   * @example
   * // Get a resource's relationship data only
   * api.get('anime/2/categories')
   */
  async get (model, params = {}, headers = {}) {
    try {
      let [ res, id ] = model.split`/`
      const url = this.plural(this.resCase(res)) + (id ? '/' + id : '')
      const { data } = await axios.get(url, {
        params,
        paramsSerializer: p => query(p),
        headers: Object.assign(this.headers, headers, jsonAPIHeader)
      })

      return deserialise(data)
{'fraction_non_alphanumeric': 0.13457249070631971, 'fraction_numerical': 0.00724907063197026, 'mean_word_length': 3.0699697428139183, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 14, 'https://': 6, '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': '4064643', 'n_tokens_mistral': 3428, 'n_tokens_neox': 3305, 'n_words': 1010}