{"version":3,"sources":["../index.ts","../src/api-builder.ts","../src/request.ts","../src/restEntityApi.ts"],"sourcesContent":["import ApiBuilder, { METHOD_TYPES, DefaultEntityAPIReturnTypes, EndpointsAPIReturnTypes, EntityAPIReturnTypes } from './src/api-builder';\n\nexport { apiRequest as request, toQueryString } from './src/request';\nexport { METHOD_TYPES, DefaultEntityAPIReturnTypes, EndpointsAPIReturnTypes, EntityAPIReturnTypes };\nexport default ApiBuilder;\n","import merge from 'lodash/merge';\nimport RestEntityAPI,{RestEntityAPIReturnTypes} from './restEntityApi';\nimport { AxiosRequestHeaders, RawAxiosRequestHeaders } from 'axios';\n\nconst METHOD_TYPES = {\n  POST: 'POST',\n  PUT: 'PUT',\n  DELETE: 'DELETE',\n  GET: 'GET',\n  LIST: 'GET',\n};\n\nconst API_METHODS = {\n  [METHOD_TYPES.POST]: 'create',\n  [METHOD_TYPES.PUT]: 'update',\n  [METHOD_TYPES.DELETE]: 'destroy',\n  [METHOD_TYPES.GET]: 'getById',\n  [METHOD_TYPES.LIST]: 'list',\n};\n\n/**\n *\n * @param {Object} options\n * @param {String} options.name\n * @param {Function}options.endpoint\n * @param {Object} options.endpoints\n * @param {Object} options.entities\n */\n\ninterface ApiBuilderOptions {\n  name?: string;\n  endpoint?: () => string;\n  endpoints?: {\n    [x: string]: {\n      endpoint: ()=> string;\n      type:  'list' | 'create' | 'update' | 'destroy' | 'getById' | string\n    }\n  };\n  entities?: {\n    [key: string]: {\n      name: string;\n      endpoint: ()=> string;\n  } };\n  headers?: AxiosRequestHeaders | RawAxiosRequestHeaders;\n}\n\ntype UnionToIntersection<U> =\n  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void)\n    ? I\n    : never;\n\ninterface DefaultEntityAPIReturnTypes extends RestEntityAPIReturnTypes{ }\n\n interface EndpointsAPIReturnTypes {\n  [key: string]: UnionToIntersection<RestEntityAPIReturnTypes[keyof RestEntityAPIReturnTypes]>;\n}\n interface EntityAPIReturnTypes {\n  [key: string]: RestEntityAPIReturnTypes;\n}\n\nconst ApiBuilder = (options: ApiBuilderOptions)  =>  {\n  // Destructure the options object to get entities, endpoints, name, endpoint and headers\n  const {\n    entities, endpoints, name, endpoint, headers,\n  } = options;\n  // Define a function to get API endpoints\n  const getApiEndpoints = (endpoints) =>  {\n    // Initialize an empty object for API endpoints\n    let apiEndpoints = {};\n    // Initialize an empty object for API entities\n    let apiEntities = {};\n\n    // Define a function to get methods\n    const getMethods = (properties, isEntity, headerOptions) =>\n    // Use Object.keys and reduce to iterate over each property\n      Object.keys(properties).reduce((methods, methodName) => {\n        // Destructure the property to get endpoint, type, and selection\n        const { endpoint, type, selection } = properties[methodName];\n        // Create a new RestEntityAPI instance\n        const api = RestEntityAPI({ name:methodName, endpoint, selection, headers: headerOptions });\n        // If isEntity is true, add the entire api instance to methods, otherwise add the specific API method\n\n        methods[methodName] = isEntity ? api : api[API_METHODS[type]];\n        // Return the updated methods object\n        return methods;\n      }, {});\n\n    // If the name and endpoint are provided in the options\n    if (name && endpoint) {\n      // Create a new RestEntityAPI instance for the entire entity\n      apiEntities = RestEntityAPI({ name, endpoint, headers });\n    }\n    // If entities are provided and there are entities\n    else if (entities && Object.keys(entities).length) {\n      // Call getMethods function to get the methods for each entity\n      apiEntities = getMethods(entities, true, headers);\n    }\n    // If endpoints are provided and there are endpoints\n    else if (endpoints && Object.keys(endpoints).length) {\n      // Call getMethods function to get the methods for each endpoint\n      apiEndpoints = getMethods(endpoints, false, headers);\n    }\n    // Return an object with apiEntities and apiEndpoints\n    return merge({}, { ...apiEndpoints }, { ...apiEntities });\n  };\n\n  // Call getApiEndpoints function to get the API endpoints\n  return { ...getApiEndpoints(endpoints)} as DefaultEntityAPIReturnTypes & EndpointsAPIReturnTypes & EntityAPIReturnTypes;\n};\n\nexport { METHOD_TYPES, DefaultEntityAPIReturnTypes, EndpointsAPIReturnTypes, EntityAPIReturnTypes };\nexport default ApiBuilder;\n","import axios, { Method, AxiosRequestHeaders, AxiosResponse, RawAxiosRequestHeaders} from 'axios';\n\nimport isArray from 'lodash/isArray';\nimport reduce from 'lodash/reduce';\nimport replace from 'lodash/replace';\n\n/**\n * Convert api params to query string\n *\n * @param {Object}  params  Params to convert\n * @return {String}\n */\nexport const toQueryString = (params) =>\n  // Use lodash's reduce function to iterate over each key-value pair in the params object\n  reduce(\n    params,\n    (result, value, key) => {\n      // If either the key or value is undefined, return the result as is\n      if (value === undefined || key === undefined) {\n        return result;\n      }\n      // If the value is an array and it has elements\n      if (isArray(value) && value.length > 0) {\n        // Use lodash's reduce function to iterate over each item in the value array\n        const resultString = reduce(\n          value,\n          (result, valueItem) => {\n            // Replace all occurrences of '#' with '%23' in the valueItem\n            valueItem = replace(valueItem, new RegExp('#', 'g'), '%23');\n            // Replace all occurrences of apostrophes with '%27' in the valueItem\n            valueItem = replace(valueItem, new RegExp('[\\'’]', 'g'), '%27');\n\n            // Append the key-value pair to the result string, separated by '&' if result is not empty\n            return `${result}${result === '' ? '' : '&'}${key}=${valueItem}`;\n          },\n          '',\n        );\n        // Append the resultString to the result, separated by '?' if result is empty, otherwise '&'\n        return `${result}${result === '' ? '?' : '&'}${resultString}`;\n      }\n\n      // If the value is not an array, replace all occurrences of '#' with '%23' and apostrophes with '%27' in the value\n      value = replace(value, new RegExp('#', 'g'), '%23');\n      value = replace(value, new RegExp('[\\'’]', 'g'), '%27');\n\n      // Append the key-value pair to the result, separated by '?' if result is empty, otherwise '&'\n      return `${result}${result === '' ? '?' : '&'}${key}=${value}`;\n    },\n    '',\n  );\n\n/**\n * Return headers for network request\n *\n * @param {Object}  options\n * @return {Object} headers\n */\nasync function getRequestHeaders(options: RequestOptionTypes) {\n  // Define default headers\n  const headers = {\n    'Content-Type': 'application/json',\n    // Spread operator is used to include any additional headers passed in options\n    ...options.headers,\n  };\n    // Return the headers object\n  return headers;\n}\n\n/**\n * Make a request and throw an error if response code is not in successful range.\n *\n * @param {String} url              The url of the request.\n * @param {Object} options\n * @param {String} options.method   The method for the request.\n * @param {Object} options.headers  The headers to send with the request.\n * @param {Object} options.body     The body to send with the request.\n */\n\ntype RequestOptionTypes = {\n  method?: Method;\n  headers?: AxiosRequestHeaders | RawAxiosRequestHeaders;\n  body?: any;\n  cancelToken?: any;\n  formData?: boolean;\n\n}\n\nasync function makeRequest(url: string, options: RequestOptionTypes): Promise<AxiosResponse> {\n  let response;\n  const requestHeaders = await getRequestHeaders(options);\n  const requestOptions = {\n    url,\n    method: options.method || 'GET',\n    headers: Object.entries(requestHeaders).reduce((headers, [key, value]) => {\n      headers[key] = value.toString();\n      return headers;\n    }, {}),\n    data: options.body,\n    cancelToken: options.cancelToken,\n  };\n    // If form data is supplied, do not stringify the body and\n    // remove the Content-Type header so that the browser can set it itself.\n  if (options.formData) {\n    requestOptions.headers['Content-Type'] = 'multipart/form-data';\n  }\n\n  if (options.formData) {\n    response = await fetch(url, { body: options.body, ...requestOptions });\n    if (response.status < 200 || response.status > 299) {\n      throw response;\n    }\n    const parseResponse = await response.json();\n    response = { data: parseResponse };\n  }\n  else {\n    response = await axios(requestOptions);\n  }\n\n  // Throw an error if the status code is not a successful status code.\n  if (response.status < 200 || response.status > 299) {\n    throw response;\n  }\n\n  // Otherwise, return the response.\n  return response;\n}\n\n/**\n * Make a request with the ability to refresh tokens in the event of a 401.\n *\n * @param {String} url              The url of the request.\n * @param {Object} options\n * @param {Number} retry            Retry count\n * @param {String} options.method   The method for the request.\n * @param {Object} options.headers  The headers to send with the request.\n * @param {Object} options.body     The body to send with the request.\n */\nexport async function apiRequest(url:string, options: RequestOptionTypes) {\n  try {\n    // Make request with current tokens.\n    const response = await makeRequest(url, options);\n    // Should just return if no-content response\n    if (response.status === 204) {\n      return true;\n    }\n\n    return response.data;\n  }\n  catch (error) {\n    const response = error.response || error || {};\n    const getEndpoint = (url) =>\n      url.substring(\n        url.length,\n        url.indexOf('?') > -1 ? url.indexOf('?') : undefined,\n      );\n    const endpoint = url.includes(getEndpoint(url))\n      ? getEndpoint(url)\n      : 'external endpoint';\n    /* eslint-disable-next-line no-underscore-dangle */\n    const errorMessage = `Received ${response.status} from ${error?.request?._method} request to ${endpoint}`;\n    console.log(`${errorMessage}`, {\n      url,\n      status: response.status,\n      error: response?.data?.error,\n      message: response?.data?.message,\n      method: options.method,\n      headers: options.headers,\n    });\n\n    throw error;\n  }\n}\n","import { apiRequest as request, toQueryString } from './request';\nimport { AxiosRequestHeaders, RawAxiosRequestHeaders } from 'axios';\ntype RestEntityAPIOptions = {\n  name: string;\n  endpoint: Function;\n  selection?: Object;\n  headers: AxiosRequestHeaders | RawAxiosRequestHeaders;\n}\n\ninterface CreateTypes {\n  data?: any;\n  params?: any;\n  cancelToken?: any;\n  query?: any;\n}\ninterface UpdateTypes {\n  id?: any;\n  data?: any;\n  params?: any;\n}\ninterface DestroyTypes {\n  id?: any;\n  params?: any;\n}\ninterface GetByIdTypes {\n  id?: any;\n  params?: any;\n  query?: any;\n  cancelToken?: any;\n}\ninterface ListTypes {\n  query?: any;\n  params?: any;\n  cancelToken?: any;\n}\n\n\nexport type RestEntityAPIReturnTypes  = {\n  create: (data?: CreateTypes['data'], params?: CreateTypes['params'], cancelToken?: CreateTypes['cancelToken'], query?: CreateTypes['query']) => Promise<any>;\n  update: (id?: UpdateTypes['id'], data?: UpdateTypes['data'], params?: UpdateTypes['params']) => Promise<any>;\n  destroy: (id?: DestroyTypes['id'], params?: DestroyTypes['params']) => Promise<any>;\n  getById: (id?: GetByIdTypes['id'], params?: GetByIdTypes['params'], query?: GetByIdTypes['query'], cancelToken?: GetByIdTypes['cancelToken']) => Promise<any>;\n  list:  (query?: ListTypes['query'], params?: ListTypes['params'], cancelToken?: ListTypes['cancelToken']) => Promise<any>;\n  buildEndpoint: Function;\n  toQueryString: Function;\n} & {}\n\nconst RestEntityAPI = (options:RestEntityAPIOptions): RestEntityAPIReturnTypes => {\n  const { endpoint, selection, headers } = options;\n\n  const buildEndpoint = (endpoint, params): string =>\n    (Array.isArray(params) ? endpoint(...params) : endpoint(params));\n\n  const create = async (data, params, cancelToken, query): Promise<any> =>\n    request(`${buildEndpoint(endpoint, params)}${toQueryString(query)}`, {\n      method: 'POST',\n      body: data,\n      cancelToken,\n      headers,\n      ...selection,\n    });\n\n  const update = async (id, data, params): Promise<any> =>\n    request(`${buildEndpoint(endpoint, params)}/${id}`, {\n      method: 'PUT',\n      body: data,\n      headers,\n      ...selection,\n    });\n\n  const destroy = async (id = '', params): Promise<any> =>\n    request(`${buildEndpoint(endpoint, params)}/${id}`, {\n      method: 'DELETE',\n      headers,\n      ...selection,\n    });\n\n  const getById = async (id, params, query = null, cancelToken): Promise<any> =>\n    request(\n      `${buildEndpoint(endpoint, params)}/${id}${toQueryString(query)}`,\n      { method: 'GET', cancelToken },\n    );\n\n  const list = async (query, params, cancelToken): Promise<any> =>\n    request(`${buildEndpoint(endpoint, params)}${toQueryString(query)}`, {\n      method: 'GET',\n      cancelToken,\n      headers,\n      ...selection,\n    });\n\n  return {\n    create,\n    update,\n    destroy,\n    getById,\n    list,\n    buildEndpoint,\n    toQueryString,\n  };\n};\n\nexport default RestEntityAPI;\n"],"mappings":"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","names":["reduce","isArray","result","replace","axios","url","endpoint","endpoints","endpoint","merge"]}