fetchja 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import x from"pluralize";function n(t){if(Array.isArray(t))return t.map(n);let e={id:t.id,type:t.type};for(let r in t.attributes)e[r]=t.attributes[r];for(let r in t.relationships)t.relationships[r].data&&(e[r]=t.relationships[r].data);return e}function g(t){let e={};for(let r of t)e[r.type]||(e[r.type]={}),e[r.type][r.id]=n(r);return e}function h(t){let e={};if(t.data&&(e.data=n(t.data)),t.meta&&(e.meta=t.meta),t.included){let r=g(t.included),s=i=>r[i.type][i.id];for(let i of e.data)for(let o in i){let a=i[o];typeof a=="object"&&(i[o]=Array.isArray(a)?a.map(s):s(a))}}return e}function c(t){if(t.response){let{data:e}=t.response;e?.errors&&(t.errors=e.errors)}throw t}function k(t,e,r){return typeof t=="object"&&t!==null?(r.relationships||(r.relationships={}),r.relationships[e]={data:t.id?{id:t.id,type:t.type||e}:t,links:t.links,meta:t.meta}):(r.attributes||(r.attributes={}),r.attributes[e]=t),r}function f(t,e,r={camelCaseTypes:s=>s,pluralTypes:s=>s}){try{if(e===null||Array.isArray(e)&&!e.length)return{data:e};let s={type:r.pluralTypes(r.camelCaseTypes(t))};e.id&&(s.id=String(e.id));for(let i in e)["id","type"].includes(i)||k(e[i],i,s);return JSON.stringify({data:s})}catch(s){c(s)}}function y(t,e={},r=""){let s=Array.isArray(e);for(let i in e){let o=e[i],a=r?`${r}[${s?"":i}]`:i;o instanceof Object?y(t,o,a):t.append(a,o)}}function m(t={}){let e=new URLSearchParams;return y(e,t),e}function d(t,e={resourceCase:r=>r,pluralize:r=>r}){let r=t.split("/"),s=r.pop(),i=r.join("/");return[s,`${i}/${e.pluralize(e.resourceCase(s))}`]}function u(t){return t.toLowerCase().replace(/[-_](.)/g,(e,r)=>r.toUpperCase()).replace(/^(.)/,e=>e.toLowerCase())}function C(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/_/g,"-").toLowerCase()}function b(t){return t.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/-/g,"_").toLowerCase()}var l="application/vnd.api+json",p=class{constructor(e={headers:{}}){this.baseURL=e.baseURL,this.headers={Accept:l,"Content-Type":l,...e.headers},this.queryFormatter=typeof e.queryFormatter=="function"?e.queryFormatter:s=>m(s),this.camelCaseTypes=e.camelCaseTypes===!1?s=>s:u;let r={camel:u,kebab:C,snake:b,default:s=>s};this.resourceCase=r[e.resourceCase]||r.default,this.pluralize=e.pluralize===!1?s=>s:x,this.onResponseError=s=>s,this.fetch=this.get,this.update=this.patch,this.create=this.post,this.remove=this.delete}#e(e){return d(e,{resourceCase:this.resourceCase,pluralize:this.pluralize})}async request(e={method:"GET",headers:{}}){let r=new URL(e.url,this.baseURL||e.baseURL);e.params&&(r.search=this.queryFormatter(e.params));let s=new Headers({...this.headers,...e.headers});e.body&&(e.body=f(e.type,e.body,{camelCaseTypes:this.camelCaseTypes,pluralTypes:this.pluralize}));try{let i=await fetch(r,{method:e.method,body:e.body,headers:s});if(!i.ok)throw this.onResponseError(i),new Error(i.statusText);let o={};for(let[w,z]of i.headers.entries())o[w]=z;let a=o["content-type"],T=a&&a.includes(l)?await i.json():{};return{...h(T),status:i.status,statusText:i.statusText,headers:o}}catch(i){throw i}}get(e,r={method:"GET"}){try{return r.url=e.split("/").map(s=>this.resourceCase(s)).filter(Boolean).join("/"),this.request(r)}catch(s){throw c(s)}}patch(e,r,s={method:"PATCH"}){try{let[i,o]=this.#e(e);return this.request({url:r?.id?`${o}/${r.id}`:o,body:r,type:i,...s})}catch(i){throw c(i)}}post(e,r,s={method:"POST"}){try{let[i,o]=this.#e(e);return this.request({url:o,body:r,type:i,...s})}catch(i){throw c(i)}}delete(e,r,s={method:"DELETE"}){try{let[i,o]=this.#e(e);return this.request({url:`${o}/${r}`,body:{id:r},type:i,...s})}catch(i){throw c(i)}}};export{p as default};
1
+ import q from"pluralize";function c(t){if(Array.isArray(t))return t.map(c);let e={id:t.id,type:t.type};for(let r in t.attributes)e[r]=t.attributes[r];for(let r in t.relationships)t.relationships[r].data&&(e[r]=t.relationships[r].data);return e}function z(t){let e={};for(let r of t)e[r.type]||(e[r.type]={}),e[r.type][r.id]=c(r);return e}function f(t){let e={};if(t.data&&(e.data=c(t.data)),t.meta&&(e.meta=t.meta),t.included){let r=z(t.included),i=s=>r[s.type][s.id];for(let s of e.data)for(let a in s){let o=s[a];typeof o=="object"&&(s[a]=Array.isArray(o)?o.map(i):i(o))}}return e}function n(t){if(t.response){let{data:e}=t.response;e?.errors&&(t.errors=e.errors)}throw t}function g(t,e,r){return typeof t=="object"&&t!==null?(r.relationships||(r.relationships={}),r.relationships[e]={data:t.id?{id:t.id,type:t.type||e}:t,links:t.links,meta:t.meta}):(r.attributes||(r.attributes={}),r.attributes[e]=t),r}function y(t,e,r={camelCaseTypes:i=>i,pluralTypes:i=>i}){try{if(e===null||Array.isArray(e)&&!e.length)return{data:e};let i={type:r.pluralTypes(r.camelCaseTypes(t))};e.id&&(i.id=String(e.id));for(let s in e)["id","type"].includes(s)||g(e[s],s,i);return JSON.stringify({data:i})}catch(i){n(i)}}function m(t,e={},r=""){let i=Array.isArray(e);for(let s in e){let a=e[s],o=r?`${r}[${i?"":s}]`:s;a instanceof Object?m(t,a,o):t.append(o,a)}}function d(t={}){let e=new URLSearchParams;return m(e,t),e}function C(t,e={resourceCase:r=>r,pluralize:r=>r}){let r=t.split("/"),i=r.pop(),s=r.join("/");return[i,`${s}/${e.pluralize(e.resourceCase(i))}`]}function l(t){return t.toLowerCase().replace(/[-_](.)/g,(e,r)=>r.toUpperCase()).replace(/^(.)/,e=>e.toLowerCase())}function b(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/_/g,"-").toLowerCase()}function T(t){return t.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/-/g,"_").toLowerCase()}var p="application/vnd.api+json",h=class{constructor(e={headers:{}}){this.baseURL=e.baseURL,this.headers={Accept:p,"Content-Type":p,...e.headers},this.queryFormatter=typeof e.queryFormatter=="function"?e.queryFormatter:i=>d(i),this.camelCaseTypes=e.camelCaseTypes===!1?i=>i:l;let r={camel:l,kebab:b,snake:T,default:i=>i};this.resourceCase=r[e.resourceCase]||r.default,this.pluralize=e.pluralize===!1?i=>i:q,this.onResponseError=i=>i,this.fetch=this.get,this.update=this.patch,this.create=this.post,this.remove=this.delete}#e(e){return C(e,{resourceCase:this.resourceCase,pluralize:this.pluralize})}async request(e={method:"GET",headers:{}}){let r=new URL(e.url,this.baseURL||e.baseURL);e.params&&(r.search=this.queryFormatter(e.params)),e.body&&(e.body=y(e.type,e.body,{camelCaseTypes:this.camelCaseTypes,pluralTypes:this.pluralize}));let i=()=>{let s=new Headers({...this.headers,...e.headers});return fetch(r,{method:e.method,body:e.body,headers:s})};try{let s=await i();if(s.ok){if(!s.ok)throw new Error(s.statusText)}else{s.replayRequest=i;let u=await this.onResponseError(s);u instanceof Response&&(s=u)}let a={};for(let[u,k]of s.headers.entries())a[u]=k;let o=a["content-type"],w=o&&o.includes(p)?await s.json():{};return{...f(w),status:s.status,statusText:s.statusText,headers:a}}catch(s){throw s}}get(e,r={method:"GET"}){try{return r.url=e.split("/").map(i=>this.resourceCase(i)).filter(Boolean).join("/"),this.request(r)}catch(i){throw n(i)}}patch(e,r,i={method:"PATCH"}){try{let[s,a]=this.#e(e);return this.request({url:r?.id?`${a}/${r.id}`:a,body:r,type:s,...i})}catch(s){throw n(s)}}post(e,r,i={method:"POST"}){try{let[s,a]=this.#e(e);return this.request({url:a,body:r,type:s,...i})}catch(s){throw n(s)}}delete(e,r,i={method:"DELETE"}){try{let[s,a]=this.#e(e);return this.request({url:`${a}/${r}`,body:{id:r},type:s,...i})}catch(s){throw n(s)}}};export{h as default};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js", "../src/utils/deattribute.js", "../src/utils/deserialize.js", "../src/utils/error-parser.js", "../src/utils/serialize.js", "../src/utils/query-formatter.js", "../src/utils/split-model.js", "../src/utils/camel-case.js", "../src/utils/kebab-case.js", "../src/utils/snake-case.js"],
4
- "sourcesContent": ["import pluralize from 'pluralize'\n\nimport { deserialize } from './utils/deserialize.js'\nimport { serialize } from './utils/serialize.js'\n\nimport { errorParser } from './utils/error-parser.js'\nimport { queryFormatter } from './utils/query-formatter.js'\nimport { splitModel } from './utils/split-model.js'\n\nimport { camelCase } from './utils/camel-case.js'\nimport { kebabCase } from './utils/kebab-case.js'\nimport { snakeCase } from './utils/snake-case.js'\n\nconst jsonType = 'application/vnd.api+json'\n\n/**\n * Options for Fetchja.\n * \n * @typedef {Object} FetchjaOptions\n * @property {string} baseURL The base URL for all requests.\n * @property {Object} headers The headers to include in all requests.\n * @property {Function} queryFormatter A function to format query parameters.\n * @property {string} resourceCase The case to use for resource names.\n * @property {boolean} pluralize Pluralize resource names.\n */\n\n/**\n * Fetchja is a simple wrapper around the Fetch API.\n * \n * @class Fetchja\n * @param {FetchjaOptions} [options] Options for Fetchja.\n */\nexport default class Fetchja {\n constructor (options = {\n headers: {}\n }) {\n this.baseURL = options.baseURL\n\n // Headers\n this.headers = {\n Accept: jsonType,\n 'Content-Type': jsonType,\n ...options.headers\n }\n\n // Query\n this.queryFormatter = typeof options.queryFormatter === 'function'\n ? options.queryFormatter\n : object => queryFormatter(object)\n\n // Camel Case Types\n this.camelCaseTypes = options.camelCaseTypes === false\n ? string => string\n : camelCase\n\n // Resource Case\n const cases = {\n camel: camelCase,\n kebab: kebabCase,\n snake: snakeCase,\n\n default: string => string\n }\n\n this.resourceCase = cases[options.resourceCase] || cases.default\n \n // Pluralise\n this.pluralize = options.pluralize === false\n ? string => string\n : pluralize\n \n // Interceptors\n this.onResponseError = error => error\n\n // Alias\n this.fetch = this.get\n this.update = this.patch\n this.create = this.post\n this.remove = this.delete\n }\n\n #splitModel (model) {\n return splitModel(model, {\n resourceCase: this.resourceCase,\n pluralize: this.pluralize\n })\n }\n\n async request (options = {\n method: 'GET',\n headers: {}\n }) {\n const url = new URL(options.url, this.baseURL || options.baseURL)\n\n // Params\n if (options.params) {\n url.search = this.queryFormatter(options.params)\n }\n\n // Headers\n const headers = new Headers({\n ...this.headers,\n ...options.headers\n })\n\n // Body\n if (options.body) {\n options.body = serialize(options.type, options.body, {\n camelCaseTypes: this.camelCaseTypes,\n pluralTypes: this.pluralize\n })\n }\n\n // Fetch\n try {\n const response = await fetch(url, {\n method: options.method,\n body: options.body,\n headers\n })\n\n if (!response.ok) {\n this.onResponseError(response)\n throw new Error(response.statusText)\n }\n\n // Response Headers\n const responseHeaders = {}\n\n for (const [key, value] of response.headers.entries()) {\n responseHeaders[key] = value\n }\n\n const contentType = responseHeaders['content-type']\n\n // Response Data\n const data = contentType && contentType.includes(jsonType)\n ? await response.json()\n : {}\n\n // Return\n return {\n ...deserialize(data),\n\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders\n }\n } catch (error) {\n throw error\n }\n }\n\n get (model, options = { method: 'GET' }) {\n try {\n options.url = model.split('/')\n .map(part => this.resourceCase(part))\n .filter(Boolean)\n .join('/')\n\n return this.request(options)\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n patch (model, body, options = { method: 'PATCH' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url: body?.id ? `${url}/${body.id}` : url,\n body,\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n post (model, body, options = { method: 'POST' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url,\n body,\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n delete (model, id, options = { method: 'DELETE' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url: `${url}/${id}`,\n body: { id },\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n}\n", "/**\n * Deattribute JSON:API data.\n *\n * @param {Object|Object[]} data The JSON:API data to deattribute.\n * @returns {Object} The deattributed data.\n */\nexport function deattribute (data) {\n if (Array.isArray(data)) {\n return data.map(deattribute)\n }\n\n const output = {\n id: data.id,\n type: data.type\n }\n\n for (const key in data.attributes) {\n output[key] = data.attributes[key]\n }\n\n for (const key in data.relationships) {\n if (data.relationships[key].data) {\n output[key] = data.relationships[key].data\n }\n }\n\n return output\n}", "import { deattribute } from './deattribute.js'\n\n/**\n * Group included JSON:API data by type and ID.\n *\n * @param {Object[]} included The included JSON:API data.\n * @returns {Object} The grouped included data.\n */\nfunction groupIncluded (included) {\n const groups = {}\n\n for (const item of included) {\n if (!groups[item.type]) {\n groups[item.type] = {}\n }\n\n groups[item.type][item.id] = deattribute(item)\n }\n\n return groups\n}\n\n/**\n * Deserialises a JSON-API response.\n *\n * @param {Object} response The JSON-API response.\n * @returns {Object} The deserialised response.\n */\nexport function deserialize (response) {\n const output = {}\n\n if (response.data) {\n output.data = deattribute(response.data)\n }\n\n if (response.meta) {\n output.meta = response.meta\n }\n\n if (response.included) {\n const included = groupIncluded(response.included)\n const getIncluded = item => included[item.type][item.id]\n\n for (const item of output.data) {\n for (const key in item) {\n const itemKey = item[key]\n\n if (typeof itemKey === 'object') {\n item[key] = Array.isArray(itemKey)\n ? itemKey.map(getIncluded)\n : getIncluded(itemKey)\n }\n }\n }\n }\n\n return output\n}", "/**\n * Parse the error response from the API.\n *\n * @param {Object} error The error object.\n * @throws {Error} The parsed error object.\n */\nexport function errorParser (error) {\n if (error.response) {\n const { data } = error.response\n\n if (data?.errors) {\n error.errors = data.errors\n }\n }\n\n throw error\n}\n", "import { errorParser } from './error-parser.js'\n\nfunction serializeNode (node, key, data) {\n if (typeof node === 'object' && node !== null) {\n if (!data.relationships) {\n data.relationships = {}\n }\n\n data.relationships[key] = {\n data: node.id ? { id: node.id, type: node.type || key } : node,\n links: node.links,\n meta: node.meta\n }\n } else {\n if (!data.attributes) {\n data.attributes = {}\n }\n\n data.attributes[key] = node\n }\n\n return data\n}\n\nexport function serialize (type, data, options = {\n camelCaseTypes: string => string,\n pluralTypes: string => string\n}) {\n try {\n if (data === null || (Array.isArray(data) && !data.length)) {\n return { data }\n }\n\n const output = {\n type: options.pluralTypes(options.camelCaseTypes(type))\n }\n\n if (data.id) {\n output.id = String(data.id)\n }\n\n for (const key in data) {\n if (['id', 'type'].includes(key)) {\n continue\n }\n\n serializeNode(data[key], key, output)\n }\n\n return JSON.stringify({ data: output })\n } catch (error) {\n errorParser(error)\n }\n}", "/**\n * Loop through an object and build a query string.\n * \n * @param {URLSearchParams} query The query to append to.\n * @param {Object} object The object to loop through.\n * @param {string} prefix The prefix to use.\n * @returns {void}\n * @private\n */\nfunction buildQuery (query, object = {}, prefix = '') {\n const isArray = Array.isArray(object)\n\n for (const key in object) {\n const value = object[key]\n const withPrefix = prefix ? `${prefix}[${isArray ? '' : key}]` : key\n\n value instanceof Object\n ? buildQuery(query, value, withPrefix)\n : query.append(withPrefix, value)\n }\n}\n\n/**\n * Format query parameters.\n * \n * @param {Object} parameters The parameters to format.\n * @returns {URLSearchParams} The formatted query.\n */\nexport function queryFormatter (parameters = {}) {\n const query = new URLSearchParams()\n buildQuery(query, parameters)\n\n return query\n}\n", "/**\n * Split a model name from a URL.\n *\n * @param {string} url The URL to split.\n * @param {Object} options The options to use.\n * @returns {string[]} The model and resource.\n */\nexport function splitModel (url, options = {\n resourceCase: string => string,\n pluralize: string => string\n}) {\n const parts = url.split('/')\n const model = parts.pop()\n const resource = parts.join('/')\n\n return [\n model,\n `${resource}/${options.pluralize(options.resourceCase(model))}`\n ]\n}\n", "/**\n * Convert a string from snake_case and kebab-case to camelCase.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function camelCase (input) {\n return input\n .toLowerCase()\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (char) => char.toLowerCase())\n}\n", "/**\n * Convert a string from camelCase and snake_case to kebab-case.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function kebabCase (input) {\n return input\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/_/g, '-')\n .toLowerCase()\n}\n", "/**\n * Converts a string from camelCase and kebab-case to snake_case.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function snakeCase (input) {\n return input\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/-/g, '_')\n .toLowerCase()\n}\n"],
5
- "mappings": "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",
6
- "names": ["pluralize", "deattribute", "data", "output", "key", "groupIncluded", "included", "groups", "item", "deattribute", "deserialize", "response", "output", "getIncluded", "key", "itemKey", "errorParser", "error", "data", "serializeNode", "node", "key", "data", "serialize", "type", "options", "string", "output", "error", "errorParser", "buildQuery", "query", "object", "prefix", "isArray", "key", "value", "withPrefix", "queryFormatter", "parameters", "splitModel", "url", "options", "string", "parts", "model", "resource", "camelCase", "input", "_", "char", "kebabCase", "input", "snakeCase", "input", "jsonType", "Fetchja", "options", "object", "queryFormatter", "string", "camelCase", "cases", "kebabCase", "snakeCase", "pluralize", "error", "#splitModel", "model", "splitModel", "url", "headers", "serialize", "response", "responseHeaders", "key", "value", "contentType", "data", "deserialize", "part", "errorParser", "body", "type", "id"]
4
+ "sourcesContent": ["import pluralize from 'pluralize'\n\nimport { deserialize } from './utils/deserialize.js'\nimport { serialize } from './utils/serialize.js'\n\nimport { errorParser } from './utils/error-parser.js'\nimport { queryFormatter } from './utils/query-formatter.js'\nimport { splitModel } from './utils/split-model.js'\n\nimport { camelCase } from './utils/camel-case.js'\nimport { kebabCase } from './utils/kebab-case.js'\nimport { snakeCase } from './utils/snake-case.js'\n\nconst jsonType = 'application/vnd.api+json'\n\n/**\n * Options for Fetchja.\n * \n * @typedef {Object} FetchjaOptions\n * @property {string} baseURL The base URL for all requests.\n * @property {Object} headers The headers to include in all requests.\n * @property {Function} queryFormatter A function to format query parameters.\n * @property {string} resourceCase The case to use for resource names.\n * @property {boolean} pluralize Pluralize resource names.\n */\n\n/**\n * Fetchja is a simple wrapper around the Fetch API.\n * \n * @class Fetchja\n * @param {FetchjaOptions} [options] Options for Fetchja.\n */\nexport default class Fetchja {\n constructor (options = {\n headers: {}\n }) {\n this.baseURL = options.baseURL\n\n // Headers\n this.headers = {\n Accept: jsonType,\n 'Content-Type': jsonType,\n ...options.headers\n }\n\n // Query\n this.queryFormatter = typeof options.queryFormatter === 'function'\n ? options.queryFormatter\n : object => queryFormatter(object)\n\n // Camel Case Types\n this.camelCaseTypes = options.camelCaseTypes === false\n ? string => string\n : camelCase\n\n // Resource Case\n const cases = {\n camel: camelCase,\n kebab: kebabCase,\n snake: snakeCase,\n\n default: string => string\n }\n\n this.resourceCase = cases[options.resourceCase] || cases.default\n \n // Pluralise\n this.pluralize = options.pluralize === false\n ? string => string\n : pluralize\n \n // Interceptors\n this.onResponseError = error => error\n\n // Alias\n this.fetch = this.get\n this.update = this.patch\n this.create = this.post\n this.remove = this.delete\n }\n\n #splitModel (model) {\n return splitModel(model, {\n resourceCase: this.resourceCase,\n pluralize: this.pluralize\n })\n }\n\n async request (options = {\n method: 'GET',\n headers: {}\n }) {\n const url = new URL(options.url, this.baseURL || options.baseURL)\n\n // Params\n if (options.params) {\n url.search = this.queryFormatter(options.params)\n }\n\n // Body\n if (options.body) {\n options.body = serialize(options.type, options.body, {\n camelCaseTypes: this.camelCaseTypes,\n pluralTypes: this.pluralize\n })\n }\n\n // Request\n const makeRequest = () => {\n // Headers\n const headers = new Headers({\n ...this.headers,\n ...options.headers\n })\n\n // Fetch\n return fetch(url, {\n method: options.method,\n body: options.body,\n headers\n })\n }\n\n try {\n let response = await makeRequest()\n\n if (!response.ok) {\n response.replayRequest = makeRequest\n const replayedResponse = await this.onResponseError(response)\n\n if (replayedResponse instanceof Response) {\n response = replayedResponse\n }\n } else if (!response.ok) {\n throw new Error(response.statusText)\n }\n\n // Response Headers\n const responseHeaders = {}\n\n for (const [key, value] of response.headers.entries()) {\n responseHeaders[key] = value\n }\n\n const contentType = responseHeaders['content-type']\n\n // Response Data\n const data = contentType && contentType.includes(jsonType)\n ? await response.json()\n : {}\n\n // Return\n return {\n ...deserialize(data),\n\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders\n }\n } catch (error) {\n throw error\n }\n }\n\n get (model, options = { method: 'GET' }) {\n try {\n options.url = model.split('/')\n .map(part => this.resourceCase(part))\n .filter(Boolean)\n .join('/')\n\n return this.request(options)\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n patch (model, body, options = { method: 'PATCH' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url: body?.id ? `${url}/${body.id}` : url,\n body,\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n post (model, body, options = { method: 'POST' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url,\n body,\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n\n delete (model, id, options = { method: 'DELETE' }) {\n try {\n const [type, url] = this.#splitModel(model)\n\n return this.request({\n url: `${url}/${id}`,\n body: { id },\n type,\n\n ...options\n })\n } catch (error) {\n throw errorParser(error)\n }\n }\n}\n", "/**\n * Deattribute JSON:API data.\n *\n * @param {Object|Object[]} data The JSON:API data to deattribute.\n * @returns {Object} The deattributed data.\n */\nexport function deattribute (data) {\n if (Array.isArray(data)) {\n return data.map(deattribute)\n }\n\n const output = {\n id: data.id,\n type: data.type\n }\n\n for (const key in data.attributes) {\n output[key] = data.attributes[key]\n }\n\n for (const key in data.relationships) {\n if (data.relationships[key].data) {\n output[key] = data.relationships[key].data\n }\n }\n\n return output\n}", "import { deattribute } from './deattribute.js'\n\n/**\n * Group included JSON:API data by type and ID.\n *\n * @param {Object[]} included The included JSON:API data.\n * @returns {Object} The grouped included data.\n */\nfunction groupIncluded (included) {\n const groups = {}\n\n for (const item of included) {\n if (!groups[item.type]) {\n groups[item.type] = {}\n }\n\n groups[item.type][item.id] = deattribute(item)\n }\n\n return groups\n}\n\n/**\n * Deserialises a JSON-API response.\n *\n * @param {Object} response The JSON-API response.\n * @returns {Object} The deserialised response.\n */\nexport function deserialize (response) {\n const output = {}\n\n if (response.data) {\n output.data = deattribute(response.data)\n }\n\n if (response.meta) {\n output.meta = response.meta\n }\n\n if (response.included) {\n const included = groupIncluded(response.included)\n const getIncluded = item => included[item.type][item.id]\n\n for (const item of output.data) {\n for (const key in item) {\n const itemKey = item[key]\n\n if (typeof itemKey === 'object') {\n item[key] = Array.isArray(itemKey)\n ? itemKey.map(getIncluded)\n : getIncluded(itemKey)\n }\n }\n }\n }\n\n return output\n}", "/**\n * Parse the error response from the API.\n *\n * @param {Object} error The error object.\n * @throws {Error} The parsed error object.\n */\nexport function errorParser (error) {\n if (error.response) {\n const { data } = error.response\n\n if (data?.errors) {\n error.errors = data.errors\n }\n }\n\n throw error\n}\n", "import { errorParser } from './error-parser.js'\n\nfunction serializeNode (node, key, data) {\n if (typeof node === 'object' && node !== null) {\n if (!data.relationships) {\n data.relationships = {}\n }\n\n data.relationships[key] = {\n data: node.id ? { id: node.id, type: node.type || key } : node,\n links: node.links,\n meta: node.meta\n }\n } else {\n if (!data.attributes) {\n data.attributes = {}\n }\n\n data.attributes[key] = node\n }\n\n return data\n}\n\nexport function serialize (type, data, options = {\n camelCaseTypes: string => string,\n pluralTypes: string => string\n}) {\n try {\n if (data === null || (Array.isArray(data) && !data.length)) {\n return { data }\n }\n\n const output = {\n type: options.pluralTypes(options.camelCaseTypes(type))\n }\n\n if (data.id) {\n output.id = String(data.id)\n }\n\n for (const key in data) {\n if (['id', 'type'].includes(key)) {\n continue\n }\n\n serializeNode(data[key], key, output)\n }\n\n return JSON.stringify({ data: output })\n } catch (error) {\n errorParser(error)\n }\n}", "/**\n * Loop through an object and build a query string.\n * \n * @param {URLSearchParams} query The query to append to.\n * @param {Object} object The object to loop through.\n * @param {string} prefix The prefix to use.\n * @returns {void}\n * @private\n */\nfunction buildQuery (query, object = {}, prefix = '') {\n const isArray = Array.isArray(object)\n\n for (const key in object) {\n const value = object[key]\n const withPrefix = prefix ? `${prefix}[${isArray ? '' : key}]` : key\n\n value instanceof Object\n ? buildQuery(query, value, withPrefix)\n : query.append(withPrefix, value)\n }\n}\n\n/**\n * Format query parameters.\n * \n * @param {Object} parameters The parameters to format.\n * @returns {URLSearchParams} The formatted query.\n */\nexport function queryFormatter (parameters = {}) {\n const query = new URLSearchParams()\n buildQuery(query, parameters)\n\n return query\n}\n", "/**\n * Split a model name from a URL.\n *\n * @param {string} url The URL to split.\n * @param {Object} options The options to use.\n * @returns {string[]} The model and resource.\n */\nexport function splitModel (url, options = {\n resourceCase: string => string,\n pluralize: string => string\n}) {\n const parts = url.split('/')\n const model = parts.pop()\n const resource = parts.join('/')\n\n return [\n model,\n `${resource}/${options.pluralize(options.resourceCase(model))}`\n ]\n}\n", "/**\n * Convert a string from snake_case and kebab-case to camelCase.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function camelCase (input) {\n return input\n .toLowerCase()\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (char) => char.toLowerCase())\n}\n", "/**\n * Convert a string from camelCase and snake_case to kebab-case.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function kebabCase (input) {\n return input\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/_/g, '-')\n .toLowerCase()\n}\n", "/**\n * Converts a string from camelCase and kebab-case to snake_case.\n *\n * @param {string} input The string to convert.\n * @returns {string} The converted string.\n */\nexport function snakeCase (input) {\n return input\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/-/g, '_')\n .toLowerCase()\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["pluralize", "deattribute", "data", "output", "key", "groupIncluded", "included", "groups", "item", "deattribute", "deserialize", "response", "output", "getIncluded", "key", "itemKey", "errorParser", "error", "data", "serializeNode", "node", "key", "data", "serialize", "type", "options", "string", "output", "error", "errorParser", "buildQuery", "query", "object", "prefix", "isArray", "key", "value", "withPrefix", "queryFormatter", "parameters", "splitModel", "url", "options", "string", "parts", "model", "resource", "camelCase", "input", "_", "char", "kebabCase", "input", "snakeCase", "input", "jsonType", "Fetchja", "options", "object", "queryFormatter", "string", "camelCase", "cases", "kebabCase", "snakeCase", "pluralize", "error", "#splitModel", "model", "splitModel", "url", "serialize", "makeRequest", "headers", "response", "replayedResponse", "responseHeaders", "key", "value", "contentType", "data", "deserialize", "part", "errorParser", "body", "type", "id"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fetchja",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "author": "Caio Tarifa <caio@yahoo.com>",
11
11
  "license": "ISC",
12
- "description": "The ultimate JavaScript library designed to make your JSON:API interactions seamless and intuitive.",
12
+ "description": "A super simple, modern, and lightweight library for dealing with JSON:API (Kitsu-like, but using Fetch API instead of Axios).",
13
13
  "dependencies": {
14
14
  "pluralize": "^8.0.0"
15
15
  },
package/src/index.js CHANGED
@@ -97,12 +97,6 @@ export default class Fetchja {
97
97
  url.search = this.queryFormatter(options.params)
98
98
  }
99
99
 
100
- // Headers
101
- const headers = new Headers({
102
- ...this.headers,
103
- ...options.headers
104
- })
105
-
106
100
  // Body
107
101
  if (options.body) {
108
102
  options.body = serialize(options.type, options.body, {
@@ -111,16 +105,33 @@ export default class Fetchja {
111
105
  })
112
106
  }
113
107
 
114
- // Fetch
115
- try {
116
- const response = await fetch(url, {
108
+ // Request
109
+ const makeRequest = () => {
110
+ // Headers
111
+ const headers = new Headers({
112
+ ...this.headers,
113
+ ...options.headers
114
+ })
115
+
116
+ // Fetch
117
+ return fetch(url, {
117
118
  method: options.method,
118
119
  body: options.body,
119
120
  headers
120
121
  })
122
+ }
123
+
124
+ try {
125
+ let response = await makeRequest()
121
126
 
122
127
  if (!response.ok) {
123
- this.onResponseError(response)
128
+ response.replayRequest = makeRequest
129
+ const replayedResponse = await this.onResponseError(response)
130
+
131
+ if (replayedResponse instanceof Response) {
132
+ response = replayedResponse
133
+ }
134
+ } else if (!response.ok) {
124
135
  throw new Error(response.statusText)
125
136
  }
126
137