diff --git a/README.md b/README.md index f79f12c..add4823 100644 --- a/README.md +++ b/README.md @@ -665,6 +665,9 @@ wretch().post({ json: 'body' }, { credentials: "same-origin" }) wretch().json({ json: 'body'}).options({ credentials: "same-origin" }).post() ``` +**NOTE:** For methods having a body argument if the value is an `Object` it is assumed that it is a JSON payload and apply the same behaviour +as calling `.json(body)`, unless the `Content-Type` header has been set to something else beforehand. + | [get](#getoptions) | [delete](#deleteoptions) | [put](#putbody-options) | [patch](#patchbody-options) | [post](#postbody-options) | [head](#headoptions) | [opts](#optsoptions) | |-----|-----|-----|-----|-----|-----|-----| diff --git a/dist/bundle/wretch.esm.js b/dist/bundle/wretch.esm.js index 593a641..0a01d94 100644 --- a/dist/bundle/wretch.esm.js +++ b/dist/bundle/wretch.esm.js @@ -1,2 +1,2 @@ -var r=function(){return(r=Object.assign||function(r){for(var t,e=1,n=arguments.length;e0)&&(e(o.reverse()[0]),n.clearMeasures&&n.clearMeasures(t),i.callbacks.delete(t),i.callbacks.size<1&&(i.observer.disconnect(),n.clearResourceTimings&&n.clearResourceTimings()),!0)},i={callbacks:new Map,observer:null,observe:function(r,t){if(r&&t){var e=n.polyfill("performance",{doThrow:!1});(function(r,t){return!i.observer&&r&&t&&(i.observer=new t((function(t){i.callbacks.forEach((function(e,n){o(t,n,e,r)}))})),r.clearResourceTimings&&r.clearResourceTimings()),i.observer})(e,n.polyfill("PerformanceObserver",{doThrow:!1}))&&(o(e,r,t,e)||(i.callbacks.size<1&&i.observer.observe({entryTypes:["resource","measure"]}),i.callbacks.set(r,t)))}}},s=function(r){this.error=r},u=function(){function o(r,t,e,n,o,i){void 0===e&&(e=new Map),void 0===n&&(n=[]),void 0===o&&(o=[]),void 0===i&&(i=[]),this._url=r,this._options=t,this._catchers=e,this._resolvers=n,this._middlewares=o,this._deferredChain=i}return o.factory=function(r,t){return void 0===r&&(r=""),void 0===t&&(t={}),new o(r,t)},o.prototype.selfFactory=function(e){var n=void 0===e?{}:e,i=n.url,s=void 0===i?this._url:i,u=n.options,a=void 0===u?this._options:u,c=n.catchers,f=void 0===c?this._catchers:c,l=n.resolvers,p=void 0===l?this._resolvers:l,h=n.middlewares,d=void 0===h?this._middlewares:h,y=n.deferredChain,v=void 0===y?this._deferredChain:y;return new o(s,r({},a),new Map(f),t(p),t(d),t(v))},o.prototype.defaults=function(r,t){return void 0===t&&(t=!1),n.defaults=t?e(n.defaults,r):r,this},o.prototype.errorType=function(r){return n.errorType=r,this},o.prototype.polyfills=function(t){return n.polyfills=r(r({},n.polyfills),t),this},o.prototype.url=function(r,t){if(void 0===t&&(t=!1),t)return this.selfFactory({url:r});var e=this._url.split("?");return this.selfFactory({url:e.length>1?e[0]+r+"?"+e[1]:this._url+r})},o.prototype.options=function(r,t){return void 0===t&&(t=!0),this.selfFactory({options:t?e(this._options,r):r})},o.prototype.query=function(r,t){return void 0===t&&(t=!1),this.selfFactory({url:a(this._url,r,t)})},o.prototype.headers=function(r){return this.selfFactory({options:e(this._options,{headers:r||{}})})},o.prototype.accept=function(r){return this.headers({Accept:r})},o.prototype.content=function(r){return this.headers({"Content-Type":r})},o.prototype.auth=function(r){return this.headers({Authorization:r})},o.prototype.catcher=function(r,t){var e=new Map(this._catchers);return e.set(r,t),this.selfFactory({catchers:e})},o.prototype.signal=function(t){return this.selfFactory({options:r(r({},this._options),{signal:t.signal})})},o.prototype.resolve=function(r,e){return void 0===e&&(e=!1),this.selfFactory({resolvers:e?[r]:t(this._resolvers,[r])})},o.prototype.defer=function(r,e){return void 0===e&&(e=!1),this.selfFactory({deferredChain:e?[r]:t(this._deferredChain,[r])})},o.prototype.middlewares=function(r,e){return void 0===e&&(e=!1),this.selfFactory({middlewares:e?r:t(this._middlewares,r)})},o.prototype.method=function(t,o,u){void 0===o&&(o={}),void 0===u&&(u=null);var a=u?"object"==typeof u?this.json(u):this.body(u):this;return function(r){var t=r._url,o=r._catchers,u=r._resolvers,a=r._middlewares,c=r._options,f=new Map(o),l=e(n.defaults,c),p=n.polyfill("AbortController",{doThrow:!1,instance:!0});!l.signal&&p&&(l.signal=p.signal);var h={ref:null,clear:function(){h.ref&&(clearTimeout(h.ref),h.ref=null)}},d=function(r){return function(t){return 0===r.length?t:1===r.length?r[0](t):r.reduceRight((function(e,n,o){return o===r.length-2?n(e(t)):n(e)}))}}(a)(n.polyfill("fetch"))(t,l),y=d.catch((function(r){throw new s(r)})).then((function(r){return h.clear(),r.ok?r:r[n.errorType||"text"]().then((function(t){var e=new Error(t);throw e[n.errorType||"text"]=t,e.status=r.status,e.response=r,e}))})),v=function(t){return t.catch((function(t){h.clear();var e=t instanceof s?t.error:t;if(t instanceof s&&f.has("__fromFetch"))return f.get("__fromFetch")(e,r);if(f.has(e.status))return f.get(e.status)(e,r);if(f.has(e.name))return f.get(e.name)(e,r);throw e}))},m=function(r){return function(t){return v(r?y.then((function(t){return t&&t[r]()})).then((function(r){return t?t(r):r})):y.then((function(r){return t?t(r):r})))}},b={res:m(null),json:m("json"),blob:m("blob"),formData:m("formData"),arrayBuffer:m("arrayBuffer"),text:m("text"),perfs:function(r){return d.then((function(t){return i.observe(t.url,r)})),b},setTimeout:function(r,t){return void 0===t&&(t=p),h.clear(),h.ref=setTimeout((function(){return t.abort()}),r),b},controller:function(){return[p,b]},error:function(r,t){return f.set(r,t),b},badRequest:function(r){return b.error(400,r)},unauthorized:function(r){return b.error(401,r)},forbidden:function(r){return b.error(403,r)},notFound:function(r){return b.error(404,r)},timeout:function(r){return b.error(408,r)},internalError:function(r){return b.error(500,r)},fetchError:function(r){return b.error("__fromFetch",r)},onAbort:function(r){return b.error("AbortError",r)}};return u.reduce((function(t,e){return e(t,r)}),b)}((a=a.options(r(r({},o),{method:t})))._deferredChain.reduce((function(r,t){return t(r,r._url,r._options)}),a))},o.prototype.get=function(r){return this.method("GET",r)},o.prototype.delete=function(r){return this.method("DELETE",r)},o.prototype.put=function(r,t){return this.method("PUT",t,r)},o.prototype.post=function(r,t){return this.method("POST",t,r)},o.prototype.patch=function(r,t){return this.method("PATCH",t,r)},o.prototype.head=function(r){return this.method("HEAD",r)},o.prototype.opts=function(r){return this.method("OPTIONS",r)},o.prototype.replay=function(r){return this.method(this._options.method,r)},o.prototype.body=function(t){return this.selfFactory({options:r(r({},this._options),{body:t})})},o.prototype.json=function(r){return this.content("application/json").body(JSON.stringify(r))},o.prototype.formData=function(r,e){return void 0===e&&(e=!1),this.body(function r(e,o,i,s){void 0===o&&(o=!1);void 0===i&&(i=n.polyfill("FormData",{instance:!0}));void 0===s&&(s=[]);return Object.entries(e).forEach((function(e){var n=e[0],u=e[1],a=s.reduce((function(r,t){return r?r+"["+t+"]":t}),null);if(a=a?a+"["+n+"]":n,u instanceof Array)for(var c=0,f=u;c0)&&(e(o.reverse()[0]),n.clearMeasures&&n.clearMeasures(t),i.callbacks.delete(t),i.callbacks.size<1&&(i.observer.disconnect(),n.clearResourceTimings&&n.clearResourceTimings()),!0)},i={callbacks:new Map,observer:null,observe:function(r,t){if(r&&t){var e=n.polyfill("performance",{doThrow:!1});(function(r,t){return!i.observer&&r&&t&&(i.observer=new t((function(t){i.callbacks.forEach((function(e,n){o(t,n,e,r)}))})),r.clearResourceTimings&&r.clearResourceTimings()),i.observer})(e,n.polyfill("PerformanceObserver",{doThrow:!1}))&&(o(e,r,t,e)||(i.callbacks.size<1&&i.observer.observe({entryTypes:["resource","measure"]}),i.callbacks.set(r,t)))}}},s=function(r){this.error=r},u=function(){function o(r,t,e,n,o,i){void 0===e&&(e=new Map),void 0===n&&(n=[]),void 0===o&&(o=[]),void 0===i&&(i=[]),this._url=r,this._options=t,this._catchers=e,this._resolvers=n,this._middlewares=o,this._deferredChain=i}return o.factory=function(r,t){return void 0===r&&(r=""),void 0===t&&(t={}),new o(r,t)},o.prototype.selfFactory=function(e){var n=void 0===e?{}:e,i=n.url,s=void 0===i?this._url:i,u=n.options,a=void 0===u?this._options:u,c=n.catchers,f=void 0===c?this._catchers:c,l=n.resolvers,p=void 0===l?this._resolvers:l,h=n.middlewares,d=void 0===h?this._middlewares:h,y=n.deferredChain,v=void 0===y?this._deferredChain:y;return new o(s,r({},a),new Map(f),t(p),t(d),t(v))},o.prototype.defaults=function(r,t){return void 0===t&&(t=!1),n.defaults=t?e(n.defaults,r):r,this},o.prototype.errorType=function(r){return n.errorType=r,this},o.prototype.polyfills=function(t){return n.polyfills=r(r({},n.polyfills),t),this},o.prototype.url=function(r,t){if(void 0===t&&(t=!1),t)return this.selfFactory({url:r});var e=this._url.split("?");return this.selfFactory({url:e.length>1?e[0]+r+"?"+e[1]:this._url+r})},o.prototype.options=function(r,t){return void 0===t&&(t=!0),this.selfFactory({options:t?e(this._options,r):r})},o.prototype.query=function(r,t){return void 0===t&&(t=!1),this.selfFactory({url:a(this._url,r,t)})},o.prototype.headers=function(r){return this.selfFactory({options:e(this._options,{headers:r||{}})})},o.prototype.accept=function(r){return this.headers({Accept:r})},o.prototype.content=function(r){var t;return this.headers(((t={})["Content-Type"]=r,t))},o.prototype.auth=function(r){return this.headers({Authorization:r})},o.prototype.catcher=function(r,t){var e=new Map(this._catchers);return e.set(r,t),this.selfFactory({catchers:e})},o.prototype.signal=function(t){return this.selfFactory({options:r(r({},this._options),{signal:t.signal})})},o.prototype.resolve=function(r,e){return void 0===e&&(e=!1),this.selfFactory({resolvers:e?[r]:t(this._resolvers,[r])})},o.prototype.defer=function(r,e){return void 0===e&&(e=!1),this.selfFactory({deferredChain:e?[r]:t(this._deferredChain,[r])})},o.prototype.middlewares=function(r,e){return void 0===e&&(e=!1),this.selfFactory({middlewares:e?r:t(this._middlewares,r)})},o.prototype.method=function(t,o,u){void 0===o&&(o={}),void 0===u&&(u=null);var a=this._options.headers,c=u?"object"!=typeof u||a&&!Object.entries(a).every((function(r){var t=r[0],e=r[1];return t.toLowerCase()!=="Content-Type".toLowerCase()||"application/json"===e}))?this.body(u):this.json(u):this;return function(r){var t=r._url,o=r._catchers,u=r._resolvers,a=r._middlewares,c=r._options,f=new Map(o),l=e(n.defaults,c),p=n.polyfill("AbortController",{doThrow:!1,instance:!0});!l.signal&&p&&(l.signal=p.signal);var h={ref:null,clear:function(){h.ref&&(clearTimeout(h.ref),h.ref=null)}},d=function(r){return function(t){return 0===r.length?t:1===r.length?r[0](t):r.reduceRight((function(e,n,o){return o===r.length-2?n(e(t)):n(e)}))}}(a)(n.polyfill("fetch"))(t,l),y=d.catch((function(r){throw new s(r)})).then((function(r){return h.clear(),r.ok?r:r[n.errorType||"text"]().then((function(t){var e=new Error(t);throw e[n.errorType||"text"]=t,e.status=r.status,e.response=r,e}))})),v=function(t){return t.catch((function(t){h.clear();var e=t instanceof s?t.error:t;if(t instanceof s&&f.has("__fromFetch"))return f.get("__fromFetch")(e,r);if(f.has(e.status))return f.get(e.status)(e,r);if(f.has(e.name))return f.get(e.name)(e,r);throw e}))},m=function(r){return function(t){return v(r?y.then((function(t){return t&&t[r]()})).then((function(r){return t?t(r):r})):y.then((function(r){return t?t(r):r})))}},b={res:m(null),json:m("json"),blob:m("blob"),formData:m("formData"),arrayBuffer:m("arrayBuffer"),text:m("text"),perfs:function(r){return d.then((function(t){return i.observe(t.url,r)})),b},setTimeout:function(r,t){return void 0===t&&(t=p),h.clear(),h.ref=setTimeout((function(){return t.abort()}),r),b},controller:function(){return[p,b]},error:function(r,t){return f.set(r,t),b},badRequest:function(r){return b.error(400,r)},unauthorized:function(r){return b.error(401,r)},forbidden:function(r){return b.error(403,r)},notFound:function(r){return b.error(404,r)},timeout:function(r){return b.error(408,r)},internalError:function(r){return b.error(500,r)},fetchError:function(r){return b.error("__fromFetch",r)},onAbort:function(r){return b.error("AbortError",r)}};return u.reduce((function(t,e){return e(t,r)}),b)}((c=c.options(r(r({},o),{method:t})))._deferredChain.reduce((function(r,t){return t(r,r._url,r._options)}),c))},o.prototype.get=function(r){return this.method("GET",r)},o.prototype.delete=function(r){return this.method("DELETE",r)},o.prototype.put=function(r,t){return this.method("PUT",t,r)},o.prototype.post=function(r,t){return this.method("POST",t,r)},o.prototype.patch=function(r,t){return this.method("PATCH",t,r)},o.prototype.head=function(r){return this.method("HEAD",r)},o.prototype.opts=function(r){return this.method("OPTIONS",r)},o.prototype.replay=function(r){return this.method(this._options.method,r)},o.prototype.body=function(t){return this.selfFactory({options:r(r({},this._options),{body:t})})},o.prototype.json=function(r){return this.content("application/json").body(JSON.stringify(r))},o.prototype.formData=function(r,e){return void 0===e&&(e=!1),this.body(function r(e,o,i,s){void 0===o&&(o=!1);void 0===i&&(i=n.polyfill("FormData",{instance:!0}));void 0===s&&(s=[]);return Object.entries(e).forEach((function(e){var n=e[0],u=e[1],a=s.reduce((function(r,t){return r?r+"["+t+"]":t}),null);if(a=a?a+"["+n+"]":n,u instanceof Array)for(var c=0,f=u;c {\n if(!entries.getEntriesByName)\n return false\n const matches = entries.getEntriesByName(name)\n if(matches && matches.length > 0) {\n callback(matches.reverse()[0])\n if(_performance.clearMeasures)\n _performance.clearMeasures(name)\n perfs.callbacks.delete(name)\n\n if(perfs.callbacks.size < 1) {\n perfs.observer.disconnect()\n if(_performance.clearResourceTimings) {\n _performance.clearResourceTimings()\n }\n }\n return true\n }\n return false\n}\n\nconst lazyObserver = (_performance, _observer) => {\n if(!perfs.observer && _performance && _observer) {\n perfs.observer = new _observer(entries => {\n perfs.callbacks.forEach((callback, name) => {\n onMatch(entries, name, callback, _performance)\n })\n })\n if(_performance.clearResourceTimings)\n _performance.clearResourceTimings()\n }\n return perfs.observer\n}\n\nconst perfs = {\n callbacks: new Map(),\n observer: null,\n observe: (name, callback) => {\n if(!name || !callback)\n return\n\n const _performance = conf.polyfill(\"performance\", { doThrow: false })\n const _observer = conf.polyfill(\"PerformanceObserver\", { doThrow: false })\n\n if(!lazyObserver(_performance, _observer))\n return\n\n if(!onMatch(_performance, name, callback, _performance)) {\n if(perfs.callbacks.size < 1)\n perfs.observer.observe({ entryTypes: [\"resource\", \"measure\"] })\n perfs.callbacks.set(name, callback)\n }\n\n }\n}\n\nexport default perfs\n","import { Wretcher } from \"./wretcher\"\nimport { mix } from \"./mix\"\nimport conf from \"./config\"\nimport perfs from \"./perfs\"\nimport { middlewareHelper } from \"./middleware\"\n\nexport type WretcherError = Error & { status: number, response: WretcherResponse, text?: string, json?: any }\nexport type WretcherErrorCallback = (error: WretcherError, originalRequest: Wretcher) => any\nexport type WretcherResponse = Response & { [key: string]: any }\nexport type ResponseChain = {\n // Response types\n res: (cb?: (type: WretcherResponse) => Result) => Promise,\n json: (cb?: (type: {[key: string]: any}) => Result) => Promise,\n blob: (cb?: (type: Blob) => Result) => Promise,\n formData: (cb?: (type: FormData) => Result) => Promise,\n arrayBuffer: (cb?: (type: ArrayBuffer) => Result) => Promise,\n text: (cb?: (type: string) => Result) => Promise,\n // Extras\n perfs: (cb?: (timing: any) => void) => ResponseChain,\n setTimeout: (time: number, controller?: AbortController) => ResponseChain,\n controller: () => [any, ResponseChain],\n // Catchers\n error: (code: (number | string), cb: WretcherErrorCallback) => ResponseChain,\n badRequest: (cb: WretcherErrorCallback) => ResponseChain,\n unauthorized: (cb: WretcherErrorCallback) => ResponseChain,\n forbidden: (cb: WretcherErrorCallback) => ResponseChain,\n notFound: (cb: WretcherErrorCallback) => ResponseChain,\n timeout: (cb: WretcherErrorCallback) => ResponseChain,\n internalError: (cb: WretcherErrorCallback) => ResponseChain,\n fetchError: (cb: WretcherErrorCallback) => ResponseChain,\n onAbort: (cb: WretcherErrorCallback) => ResponseChain\n}\n\nclass WretchErrorWrapper {\n constructor(public error: any) {}\n}\n\nexport const resolver = (wretcher: Wretcher) => {\n const {\n _url: url,\n _catchers: _catchers,\n _resolvers: resolvers,\n _middlewares: middlewares,\n _options: opts\n } = wretcher\n const catchers = new Map(_catchers)\n const finalOptions = mix(conf.defaults, opts)\n const fetchController = conf.polyfill(\"AbortController\", { doThrow: false, instance: true })\n if(!finalOptions[\"signal\"] && fetchController) {\n finalOptions[\"signal\"] = fetchController.signal\n }\n // Request timeout\n const timeout = {\n ref: null,\n clear() {\n if(timeout.ref) {\n clearTimeout(timeout.ref)\n timeout.ref = null\n }\n }\n }\n // The generated fetch request\n const fetchRequest = middlewareHelper(middlewares)(conf.polyfill(\"fetch\"))(url, finalOptions)\n // Throws on an http error\n const throwingPromise: Promise = fetchRequest\n .catch(error => {\n throw new WretchErrorWrapper(error)\n })\n .then(response => {\n timeout.clear()\n if (!response.ok) {\n return response[conf.errorType || \"text\"]().then(msg => {\n // Enhances the error object\n const err = new Error(msg)\n err[conf.errorType || \"text\"] = msg\n err[\"status\"] = response.status\n err[\"response\"] = response\n throw err\n })\n }\n return response\n })\n // Wraps the Promise in order to dispatch the error to a matching catcher\n const catchersWrapper = (promise: Promise): Promise => {\n return promise.catch(err => {\n timeout.clear()\n const error = err instanceof WretchErrorWrapper ? err.error : err\n if(err instanceof WretchErrorWrapper && catchers.has(\"__fromFetch\"))\n return catchers.get(\"__fromFetch\")(error, wretcher)\n else if(catchers.has(error.status))\n return catchers.get(error.status)(error, wretcher)\n else if(catchers.has(error.name))\n return catchers.get(error.name)(error, wretcher)\n else\n throw error\n })\n }\n // Enforces the proper promise type when a body parsing method is called.\n type BodyParser = (funName: string | null) => (cb?: (type: Type) => Result) => Promise\n const bodyParser: BodyParser = (funName) => (cb) => funName ?\n // If a callback is provided, then callback with the body result otherwise return the parsed body itself.\n catchersWrapper(throwingPromise.then(_ => _ && _[funName]()).then(_ => cb ? cb(_) : _)) :\n // No body parsing method - return the response\n catchersWrapper(throwingPromise.then(_ => cb ? cb(_) : _))\n\n const responseChain: ResponseChain = {\n /**\n * Retrieves the raw result as a promise.\n */\n res: bodyParser(null),\n /**\n * Retrieves the result as a parsed JSON object.\n */\n json: bodyParser(\"json\"),\n /**\n * Retrieves the result as a Blob object.\n */\n blob: bodyParser(\"blob\"),\n /**\n * Retrieves the result as a FormData object.\n */\n formData: bodyParser(\"formData\"),\n /**\n * Retrieves the result as an ArrayBuffer object.\n */\n arrayBuffer: bodyParser(\"arrayBuffer\"),\n /**\n * Retrieves the result as a string.\n */\n text: bodyParser(\"text\"),\n /**\n * Performs a callback on the API performance timings of the request.\n *\n * Warning: Still experimental on browsers and node.js\n */\n perfs: cb => {\n fetchRequest.then(res => perfs.observe(res.url, cb))\n return responseChain\n },\n /**\n * Aborts the request after a fixed time.\n *\n * @param time Time in milliseconds\n * @param controller A custom controller\n */\n setTimeout: (time, controller = fetchController) => {\n timeout.clear()\n timeout.ref = setTimeout(() => controller.abort(), time)\n return responseChain\n },\n /**\n * Returns the automatically generated AbortController alongside the current wretch response as a pair.\n */\n controller: () => [ fetchController, responseChain ],\n /**\n * Catches an http response with a specific error code or name and performs a callback.\n */\n error(errorId, cb) {\n catchers.set(errorId, cb)\n return responseChain\n },\n /**\n * Catches a bad request (http code 400) and performs a callback.\n */\n badRequest: cb => responseChain.error(400, cb),\n /**\n * Catches an unauthorized request (http code 401) and performs a callback.\n */\n unauthorized: cb => responseChain.error(401, cb),\n /**\n * Catches a forbidden request (http code 403) and performs a callback.\n */\n forbidden: cb => responseChain.error(403, cb),\n /**\n * Catches a \"not found\" request (http code 404) and performs a callback.\n */\n notFound: cb => responseChain.error(404, cb),\n /**\n * Catches a timeout (http code 408) and performs a callback.\n */\n timeout: cb => responseChain.error(408, cb),\n /**\n * Catches an internal server error (http code 500) and performs a callback.\n */\n internalError: cb => responseChain.error(500, cb),\n /**\n * Catches errors thrown when calling the fetch function and performs a callback.\n */\n fetchError: cb => responseChain.error(\"__fromFetch\", cb),\n /**\n * Catches an AbortError and performs a callback.\n */\n onAbort: cb => responseChain.error(\"AbortError\", cb)\n }\n\n return resolvers.reduce((chain, r) => r(chain, wretcher), responseChain) as (ResponseChain & Promise)\n}\n","import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ \"Content-Type\" : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method, options = {}, body = null) {\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options?) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options?) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body?, options?) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body?, options?) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body?, options?) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options?) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options?) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options?) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(\"application/json\").body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n","import { WretcherOptions } from \"./wretcher\"\nimport { WretcherResponse } from \"./resolver\"\n\nexport type Middleware = (options?: {[key: string]: any}) => ConfiguredMiddleware\nexport type ConfiguredMiddleware = (next: FetchLike) => FetchLike\nexport type FetchLike = (url: string, opts: WretcherOptions) => Promise\n\nexport const middlewareHelper = (middlewares: ConfiguredMiddleware[]) => (fetchFunction: FetchLike): FetchLike => {\n return (\n middlewares.length === 0 ?\n fetchFunction :\n middlewares.length === 1 ?\n middlewares[0](fetchFunction) :\n middlewares.reduceRight((acc, curr, idx): any =>\n (idx === middlewares.length - 2) ? curr(acc(fetchFunction)) : curr(acc as any)\n )\n ) as FetchLike\n}\n","import { Wretcher } from \"./wretcher\"\n\nconst factory = Wretcher.factory\nfactory[\"default\"] = Wretcher.factory\n\n/**\n * Return a fresh Wretcher instance.\n */\nexport default factory\n"],"names":["mix","one","two","mergeArrays","clone","prop","hasOwnProperty","Array","config","defaults","errorType","polyfills","fetch","FormData","URLSearchParams","performance","PerformanceObserver","AbortController","polyfill","p","_a","_b","_c","doThrow","_d","instance","_i","args","res","this","self","global","Error","onMatch","entries","name","callback","_performance","getEntriesByName","matches","length","reverse","clearMeasures","perfs","callbacks","delete","size","observer","disconnect","clearResourceTimings","Map","observe","conf","_observer","forEach","lazyObserver","entryTypes","set","error","_url","_options","_catchers","_resolvers","_middlewares","_deferredChain","Wretcher","url","options","_e","catchers","_f","resolvers","_g","middlewares","_h","deferredChain","mixin","method","replace","selfFactory","split","qp","appendQueryParams","headerValues","headers","headerValue","Accept","Content-Type","Authorization","errorId","catcher","newMap","controller","signal","doResolve","clear","body","baseWretcher","json","wretcher","opts","finalOptions","fetchController","timeout","ref","clearTimeout","fetchRequest","fetchFunction","reduceRight","acc","curr","idx","middlewareHelper","throwingPromise","catch","WretchErrorWrapper","then","response","ok","msg","err","status","catchersWrapper","promise","has","get","bodyParser","funName","cb","_","responseChain","blob","formData","arrayBuffer","text","setTimeout","time","abort","badRequest","unauthorized","forbidden","notFound","internalError","fetchError","onAbort","reduce","chain","r","resolver","contents","jsObject","content","JSON","stringify","formObject","recursive","convertFormData","ancestors","Object","key","value","formKey","ancestor","value_1","item","append","includes","input","keys","map","v","encodeQueryValue","join","queryString","usp","val","toString","encodeURIComponent","factory"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"wretch.esm.js","sources":["../../src/mix.ts","../../src/config.ts","../../src/perfs.ts","../../src/resolver.ts","../../src/wretcher.ts","../../src/middleware.ts","../../src/index.umd.ts"],"sourcesContent":["export const mix = function (one: object, two: object, mergeArrays: boolean = false) {\n if(!one || !two || typeof one !== \"object\" || typeof two !== \"object\")\n return one\n\n const clone = { ...one }\n for(const prop in two) {\n if(two.hasOwnProperty(prop)) {\n if(two[prop] instanceof Array && one[prop] instanceof Array) {\n clone[prop] = mergeArrays ? [ ...one[prop], ...two[prop] ] : two[prop]\n } else if(typeof two[prop] === \"object\" && typeof one[prop] === \"object\") {\n clone[prop] = mix(one[prop], two[prop], mergeArrays)\n } else {\n clone[prop] = two[prop]\n }\n }\n }\n\n return clone\n}\n","declare const global\n\nconst config = {\n // Default options\n defaults: {},\n // Error type\n errorType: null,\n // Polyfills\n polyfills: {\n fetch: null,\n FormData: null,\n URLSearchParams: null,\n performance: null,\n PerformanceObserver: null,\n AbortController: null\n },\n polyfill(p: string, { doThrow = true, instance = false } = {}, ...args) {\n const res = this.polyfills[p] ||\n (typeof self !== \"undefined\" ? self[p] : null) ||\n (typeof global !== \"undefined\" ? global[p] : null)\n if(doThrow && !res) throw new Error(p + \" is not defined\")\n return instance && res ? new res(...args) : res\n }\n}\n\nexport default config\n","import conf from \"./config\"\n\nconst onMatch = (entries, name, callback, _performance) => {\n if(!entries.getEntriesByName)\n return false\n const matches = entries.getEntriesByName(name)\n if(matches && matches.length > 0) {\n callback(matches.reverse()[0])\n if(_performance.clearMeasures)\n _performance.clearMeasures(name)\n perfs.callbacks.delete(name)\n\n if(perfs.callbacks.size < 1) {\n perfs.observer.disconnect()\n if(_performance.clearResourceTimings) {\n _performance.clearResourceTimings()\n }\n }\n return true\n }\n return false\n}\n\nconst lazyObserver = (_performance, _observer) => {\n if(!perfs.observer && _performance && _observer) {\n perfs.observer = new _observer(entries => {\n perfs.callbacks.forEach((callback, name) => {\n onMatch(entries, name, callback, _performance)\n })\n })\n if(_performance.clearResourceTimings)\n _performance.clearResourceTimings()\n }\n return perfs.observer\n}\n\nconst perfs = {\n callbacks: new Map(),\n observer: null,\n observe: (name, callback) => {\n if(!name || !callback)\n return\n\n const _performance = conf.polyfill(\"performance\", { doThrow: false })\n const _observer = conf.polyfill(\"PerformanceObserver\", { doThrow: false })\n\n if(!lazyObserver(_performance, _observer))\n return\n\n if(!onMatch(_performance, name, callback, _performance)) {\n if(perfs.callbacks.size < 1)\n perfs.observer.observe({ entryTypes: [\"resource\", \"measure\"] })\n perfs.callbacks.set(name, callback)\n }\n\n }\n}\n\nexport default perfs\n","import { Wretcher } from \"./wretcher\"\nimport { mix } from \"./mix\"\nimport conf from \"./config\"\nimport perfs from \"./perfs\"\nimport { middlewareHelper } from \"./middleware\"\n\nexport type WretcherError = Error & { status: number, response: WretcherResponse, text?: string, json?: any }\nexport type WretcherErrorCallback = (error: WretcherError, originalRequest: Wretcher) => any\nexport type WretcherResponse = Response & { [key: string]: any }\nexport type ResponseChain = {\n // Response types\n res: (cb?: (type: WretcherResponse) => Result) => Promise,\n json: (cb?: (type: {[key: string]: any}) => Result) => Promise,\n blob: (cb?: (type: Blob) => Result) => Promise,\n formData: (cb?: (type: FormData) => Result) => Promise,\n arrayBuffer: (cb?: (type: ArrayBuffer) => Result) => Promise,\n text: (cb?: (type: string) => Result) => Promise,\n // Extras\n perfs: (cb?: (timing: any) => void) => ResponseChain,\n setTimeout: (time: number, controller?: AbortController) => ResponseChain,\n controller: () => [any, ResponseChain],\n // Catchers\n error: (code: (number | string), cb: WretcherErrorCallback) => ResponseChain,\n badRequest: (cb: WretcherErrorCallback) => ResponseChain,\n unauthorized: (cb: WretcherErrorCallback) => ResponseChain,\n forbidden: (cb: WretcherErrorCallback) => ResponseChain,\n notFound: (cb: WretcherErrorCallback) => ResponseChain,\n timeout: (cb: WretcherErrorCallback) => ResponseChain,\n internalError: (cb: WretcherErrorCallback) => ResponseChain,\n fetchError: (cb: WretcherErrorCallback) => ResponseChain,\n onAbort: (cb: WretcherErrorCallback) => ResponseChain\n}\n\nclass WretchErrorWrapper {\n constructor(public error: any) {}\n}\n\nexport const resolver = (wretcher: Wretcher) => {\n const {\n _url: url,\n _catchers: _catchers,\n _resolvers: resolvers,\n _middlewares: middlewares,\n _options: opts\n } = wretcher\n const catchers = new Map(_catchers)\n const finalOptions = mix(conf.defaults, opts)\n const fetchController = conf.polyfill(\"AbortController\", { doThrow: false, instance: true })\n if(!finalOptions[\"signal\"] && fetchController) {\n finalOptions[\"signal\"] = fetchController.signal\n }\n // Request timeout\n const timeout = {\n ref: null,\n clear() {\n if(timeout.ref) {\n clearTimeout(timeout.ref)\n timeout.ref = null\n }\n }\n }\n // The generated fetch request\n const fetchRequest = middlewareHelper(middlewares)(conf.polyfill(\"fetch\"))(url, finalOptions)\n // Throws on an http error\n const throwingPromise: Promise = fetchRequest\n .catch(error => {\n throw new WretchErrorWrapper(error)\n })\n .then(response => {\n timeout.clear()\n if (!response.ok) {\n return response[conf.errorType || \"text\"]().then(msg => {\n // Enhances the error object\n const err = new Error(msg)\n err[conf.errorType || \"text\"] = msg\n err[\"status\"] = response.status\n err[\"response\"] = response\n throw err\n })\n }\n return response\n })\n // Wraps the Promise in order to dispatch the error to a matching catcher\n const catchersWrapper = (promise: Promise): Promise => {\n return promise.catch(err => {\n timeout.clear()\n const error = err instanceof WretchErrorWrapper ? err.error : err\n if(err instanceof WretchErrorWrapper && catchers.has(\"__fromFetch\"))\n return catchers.get(\"__fromFetch\")(error, wretcher)\n else if(catchers.has(error.status))\n return catchers.get(error.status)(error, wretcher)\n else if(catchers.has(error.name))\n return catchers.get(error.name)(error, wretcher)\n else\n throw error\n })\n }\n // Enforces the proper promise type when a body parsing method is called.\n type BodyParser = (funName: string | null) => (cb?: (type: Type) => Result) => Promise\n const bodyParser: BodyParser = (funName) => (cb) => funName ?\n // If a callback is provided, then callback with the body result otherwise return the parsed body itself.\n catchersWrapper(throwingPromise.then(_ => _ && _[funName]()).then(_ => cb ? cb(_) : _)) :\n // No body parsing method - return the response\n catchersWrapper(throwingPromise.then(_ => cb ? cb(_) : _))\n\n const responseChain: ResponseChain = {\n /**\n * Retrieves the raw result as a promise.\n */\n res: bodyParser(null),\n /**\n * Retrieves the result as a parsed JSON object.\n */\n json: bodyParser(\"json\"),\n /**\n * Retrieves the result as a Blob object.\n */\n blob: bodyParser(\"blob\"),\n /**\n * Retrieves the result as a FormData object.\n */\n formData: bodyParser(\"formData\"),\n /**\n * Retrieves the result as an ArrayBuffer object.\n */\n arrayBuffer: bodyParser(\"arrayBuffer\"),\n /**\n * Retrieves the result as a string.\n */\n text: bodyParser(\"text\"),\n /**\n * Performs a callback on the API performance timings of the request.\n *\n * Warning: Still experimental on browsers and node.js\n */\n perfs: cb => {\n fetchRequest.then(res => perfs.observe(res.url, cb))\n return responseChain\n },\n /**\n * Aborts the request after a fixed time.\n *\n * @param time Time in milliseconds\n * @param controller A custom controller\n */\n setTimeout: (time, controller = fetchController) => {\n timeout.clear()\n timeout.ref = setTimeout(() => controller.abort(), time)\n return responseChain\n },\n /**\n * Returns the automatically generated AbortController alongside the current wretch response as a pair.\n */\n controller: () => [ fetchController, responseChain ],\n /**\n * Catches an http response with a specific error code or name and performs a callback.\n */\n error(errorId, cb) {\n catchers.set(errorId, cb)\n return responseChain\n },\n /**\n * Catches a bad request (http code 400) and performs a callback.\n */\n badRequest: cb => responseChain.error(400, cb),\n /**\n * Catches an unauthorized request (http code 401) and performs a callback.\n */\n unauthorized: cb => responseChain.error(401, cb),\n /**\n * Catches a forbidden request (http code 403) and performs a callback.\n */\n forbidden: cb => responseChain.error(403, cb),\n /**\n * Catches a \"not found\" request (http code 404) and performs a callback.\n */\n notFound: cb => responseChain.error(404, cb),\n /**\n * Catches a timeout (http code 408) and performs a callback.\n */\n timeout: cb => responseChain.error(408, cb),\n /**\n * Catches an internal server error (http code 500) and performs a callback.\n */\n internalError: cb => responseChain.error(500, cb),\n /**\n * Catches errors thrown when calling the fetch function and performs a callback.\n */\n fetchError: cb => responseChain.error(\"__fromFetch\", cb),\n /**\n * Catches an AbortError and performs a callback.\n */\n onAbort: cb => responseChain.error(\"AbortError\", cb)\n }\n\n return resolvers.reduce((chain, r) => r(chain, wretcher), responseChain) as (ResponseChain & Promise)\n}\n","import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\nconst JSON_MIME = \"application/json\"\nconst CONTENT_TYPE_HEADER = \"Content-Type\"\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ [CONTENT_TYPE_HEADER] : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method : string, options = {}, body = null) {\n const headers = this._options.headers\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" && (\n !headers ||\n Object.entries(headers).every(([k, v]) =>\n k.toLowerCase() !== CONTENT_TYPE_HEADER.toLowerCase() ||\n v === JSON_MIME\n )\n ) ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options? : WretcherOptions) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options? : WretcherOptions) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body? : any, options? : WretcherOptions) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body? : any, options? : WretcherOptions) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body? : any, options? : WretcherOptions) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options? : WretcherOptions) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options? : WretcherOptions) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options? : WretcherOptions) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(JSON_MIME).body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n","import { WretcherOptions } from \"./wretcher\"\nimport { WretcherResponse } from \"./resolver\"\n\nexport type Middleware = (options?: {[key: string]: any}) => ConfiguredMiddleware\nexport type ConfiguredMiddleware = (next: FetchLike) => FetchLike\nexport type FetchLike = (url: string, opts: WretcherOptions) => Promise\n\nexport const middlewareHelper = (middlewares: ConfiguredMiddleware[]) => (fetchFunction: FetchLike): FetchLike => {\n return (\n middlewares.length === 0 ?\n fetchFunction :\n middlewares.length === 1 ?\n middlewares[0](fetchFunction) :\n middlewares.reduceRight((acc, curr, idx): any =>\n (idx === middlewares.length - 2) ? curr(acc(fetchFunction)) : curr(acc as any)\n )\n ) as FetchLike\n}\n","import { Wretcher } from \"./wretcher\"\n\nconst factory = Wretcher.factory\nfactory[\"default\"] = Wretcher.factory\n\n/**\n * Return a fresh Wretcher instance.\n */\nexport default factory\n"],"names":["mix","one","two","mergeArrays","clone","prop","hasOwnProperty","Array","config","defaults","errorType","polyfills","fetch","FormData","URLSearchParams","performance","PerformanceObserver","AbortController","polyfill","p","_a","_b","_c","doThrow","_d","instance","_i","args","res","this","self","global","Error","onMatch","entries","name","callback","_performance","getEntriesByName","matches","length","reverse","clearMeasures","perfs","callbacks","delete","size","observer","disconnect","clearResourceTimings","Map","observe","conf","_observer","forEach","lazyObserver","entryTypes","set","error","_url","_options","_catchers","_resolvers","_middlewares","_deferredChain","Wretcher","url","options","_e","catchers","_f","resolvers","_g","middlewares","_h","deferredChain","mixin","method","replace","selfFactory","split","qp","appendQueryParams","headerValues","headers","headerValue","Accept","Authorization","errorId","catcher","newMap","controller","signal","doResolve","clear","body","baseWretcher","Object","every","k","v","toLowerCase","json","wretcher","opts","finalOptions","fetchController","timeout","ref","clearTimeout","fetchRequest","fetchFunction","reduceRight","acc","curr","idx","middlewareHelper","throwingPromise","catch","WretchErrorWrapper","then","response","ok","msg","err","status","catchersWrapper","promise","has","get","bodyParser","funName","cb","_","responseChain","blob","formData","arrayBuffer","text","setTimeout","time","abort","badRequest","unauthorized","forbidden","notFound","internalError","fetchError","onAbort","reduce","chain","r","resolver","contents","jsObject","content","JSON","stringify","formObject","recursive","convertFormData","ancestors","key","value","formKey","ancestor","value_1","item","append","includes","input","keys","map","encodeQueryValue","join","queryString","usp","val","toString","encodeURIComponent","factory"],"mappings":"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"} \ No newline at end of file diff --git a/dist/bundle/wretch.js b/dist/bundle/wretch.js index 7c32213..3d2fc83 100644 --- a/dist/bundle/wretch.js +++ b/dist/bundle/wretch.js @@ -1,2 +1,2 @@ -!function(r,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(r=r||self).wretch=t()}(this,(function(){"use strict";var r=function(){return(r=Object.assign||function(r){for(var t,e=1,n=arguments.length;e0)&&(e(o.reverse()[0]),n.clearMeasures&&n.clearMeasures(t),i.callbacks.delete(t),i.callbacks.size<1&&(i.observer.disconnect(),n.clearResourceTimings&&n.clearResourceTimings()),!0)},i={callbacks:new Map,observer:null,observe:function(r,t){if(r&&t){var e=n.polyfill("performance",{doThrow:!1});(function(r,t){return!i.observer&&r&&t&&(i.observer=new t((function(t){i.callbacks.forEach((function(e,n){o(t,n,e,r)}))})),r.clearResourceTimings&&r.clearResourceTimings()),i.observer})(e,n.polyfill("PerformanceObserver",{doThrow:!1}))&&(o(e,r,t,e)||(i.callbacks.size<1&&i.observer.observe({entryTypes:["resource","measure"]}),i.callbacks.set(r,t)))}}},s=function(r){this.error=r},u=function(){function o(r,t,e,n,o,i){void 0===e&&(e=new Map),void 0===n&&(n=[]),void 0===o&&(o=[]),void 0===i&&(i=[]),this._url=r,this._options=t,this._catchers=e,this._resolvers=n,this._middlewares=o,this._deferredChain=i}return o.factory=function(r,t){return void 0===r&&(r=""),void 0===t&&(t={}),new o(r,t)},o.prototype.selfFactory=function(e){var n=void 0===e?{}:e,i=n.url,s=void 0===i?this._url:i,u=n.options,c=void 0===u?this._options:u,f=n.catchers,a=void 0===f?this._catchers:f,l=n.resolvers,p=void 0===l?this._resolvers:l,h=n.middlewares,d=void 0===h?this._middlewares:h,y=n.deferredChain,v=void 0===y?this._deferredChain:y;return new o(s,r({},c),new Map(a),t(p),t(d),t(v))},o.prototype.defaults=function(r,t){return void 0===t&&(t=!1),n.defaults=t?e(n.defaults,r):r,this},o.prototype.errorType=function(r){return n.errorType=r,this},o.prototype.polyfills=function(t){return n.polyfills=r(r({},n.polyfills),t),this},o.prototype.url=function(r,t){if(void 0===t&&(t=!1),t)return this.selfFactory({url:r});var e=this._url.split("?");return this.selfFactory({url:e.length>1?e[0]+r+"?"+e[1]:this._url+r})},o.prototype.options=function(r,t){return void 0===t&&(t=!0),this.selfFactory({options:t?e(this._options,r):r})},o.prototype.query=function(r,t){return void 0===t&&(t=!1),this.selfFactory({url:c(this._url,r,t)})},o.prototype.headers=function(r){return this.selfFactory({options:e(this._options,{headers:r||{}})})},o.prototype.accept=function(r){return this.headers({Accept:r})},o.prototype.content=function(r){return this.headers({"Content-Type":r})},o.prototype.auth=function(r){return this.headers({Authorization:r})},o.prototype.catcher=function(r,t){var e=new Map(this._catchers);return e.set(r,t),this.selfFactory({catchers:e})},o.prototype.signal=function(t){return this.selfFactory({options:r(r({},this._options),{signal:t.signal})})},o.prototype.resolve=function(r,e){return void 0===e&&(e=!1),this.selfFactory({resolvers:e?[r]:t(this._resolvers,[r])})},o.prototype.defer=function(r,e){return void 0===e&&(e=!1),this.selfFactory({deferredChain:e?[r]:t(this._deferredChain,[r])})},o.prototype.middlewares=function(r,e){return void 0===e&&(e=!1),this.selfFactory({middlewares:e?r:t(this._middlewares,r)})},o.prototype.method=function(t,o,u){void 0===o&&(o={}),void 0===u&&(u=null);var c=u?"object"==typeof u?this.json(u):this.body(u):this;return function(r){var t=r._url,o=r._catchers,u=r._resolvers,c=r._middlewares,f=r._options,a=new Map(o),l=e(n.defaults,f),p=n.polyfill("AbortController",{doThrow:!1,instance:!0});!l.signal&&p&&(l.signal=p.signal);var h={ref:null,clear:function(){h.ref&&(clearTimeout(h.ref),h.ref=null)}},d=function(r){return function(t){return 0===r.length?t:1===r.length?r[0](t):r.reduceRight((function(e,n,o){return o===r.length-2?n(e(t)):n(e)}))}}(c)(n.polyfill("fetch"))(t,l),y=d.catch((function(r){throw new s(r)})).then((function(r){return h.clear(),r.ok?r:r[n.errorType||"text"]().then((function(t){var e=new Error(t);throw e[n.errorType||"text"]=t,e.status=r.status,e.response=r,e}))})),v=function(t){return t.catch((function(t){h.clear();var e=t instanceof s?t.error:t;if(t instanceof s&&a.has("__fromFetch"))return a.get("__fromFetch")(e,r);if(a.has(e.status))return a.get(e.status)(e,r);if(a.has(e.name))return a.get(e.name)(e,r);throw e}))},m=function(r){return function(t){return v(r?y.then((function(t){return t&&t[r]()})).then((function(r){return t?t(r):r})):y.then((function(r){return t?t(r):r})))}},b={res:m(null),json:m("json"),blob:m("blob"),formData:m("formData"),arrayBuffer:m("arrayBuffer"),text:m("text"),perfs:function(r){return d.then((function(t){return i.observe(t.url,r)})),b},setTimeout:function(r,t){return void 0===t&&(t=p),h.clear(),h.ref=setTimeout((function(){return t.abort()}),r),b},controller:function(){return[p,b]},error:function(r,t){return a.set(r,t),b},badRequest:function(r){return b.error(400,r)},unauthorized:function(r){return b.error(401,r)},forbidden:function(r){return b.error(403,r)},notFound:function(r){return b.error(404,r)},timeout:function(r){return b.error(408,r)},internalError:function(r){return b.error(500,r)},fetchError:function(r){return b.error("__fromFetch",r)},onAbort:function(r){return b.error("AbortError",r)}};return u.reduce((function(t,e){return e(t,r)}),b)}((c=c.options(r(r({},o),{method:t})))._deferredChain.reduce((function(r,t){return t(r,r._url,r._options)}),c))},o.prototype.get=function(r){return this.method("GET",r)},o.prototype.delete=function(r){return this.method("DELETE",r)},o.prototype.put=function(r,t){return this.method("PUT",t,r)},o.prototype.post=function(r,t){return this.method("POST",t,r)},o.prototype.patch=function(r,t){return this.method("PATCH",t,r)},o.prototype.head=function(r){return this.method("HEAD",r)},o.prototype.opts=function(r){return this.method("OPTIONS",r)},o.prototype.replay=function(r){return this.method(this._options.method,r)},o.prototype.body=function(t){return this.selfFactory({options:r(r({},this._options),{body:t})})},o.prototype.json=function(r){return this.content("application/json").body(JSON.stringify(r))},o.prototype.formData=function(r,e){return void 0===e&&(e=!1),this.body(function r(e,o,i,s){void 0===o&&(o=!1);void 0===i&&(i=n.polyfill("FormData",{instance:!0}));void 0===s&&(s=[]);return Object.entries(e).forEach((function(e){var n=e[0],u=e[1],c=s.reduce((function(r,t){return r?r+"["+t+"]":t}),null);if(c=c?c+"["+n+"]":n,u instanceof Array)for(var f=0,a=u;f0)&&(e(o.reverse()[0]),n.clearMeasures&&n.clearMeasures(t),i.callbacks.delete(t),i.callbacks.size<1&&(i.observer.disconnect(),n.clearResourceTimings&&n.clearResourceTimings()),!0)},i={callbacks:new Map,observer:null,observe:function(r,t){if(r&&t){var e=n.polyfill("performance",{doThrow:!1});(function(r,t){return!i.observer&&r&&t&&(i.observer=new t((function(t){i.callbacks.forEach((function(e,n){o(t,n,e,r)}))})),r.clearResourceTimings&&r.clearResourceTimings()),i.observer})(e,n.polyfill("PerformanceObserver",{doThrow:!1}))&&(o(e,r,t,e)||(i.callbacks.size<1&&i.observer.observe({entryTypes:["resource","measure"]}),i.callbacks.set(r,t)))}}},s=function(r){this.error=r},u=function(){function o(r,t,e,n,o,i){void 0===e&&(e=new Map),void 0===n&&(n=[]),void 0===o&&(o=[]),void 0===i&&(i=[]),this._url=r,this._options=t,this._catchers=e,this._resolvers=n,this._middlewares=o,this._deferredChain=i}return o.factory=function(r,t){return void 0===r&&(r=""),void 0===t&&(t={}),new o(r,t)},o.prototype.selfFactory=function(e){var n=void 0===e?{}:e,i=n.url,s=void 0===i?this._url:i,u=n.options,a=void 0===u?this._options:u,c=n.catchers,f=void 0===c?this._catchers:c,l=n.resolvers,p=void 0===l?this._resolvers:l,h=n.middlewares,d=void 0===h?this._middlewares:h,y=n.deferredChain,v=void 0===y?this._deferredChain:y;return new o(s,r({},a),new Map(f),t(p),t(d),t(v))},o.prototype.defaults=function(r,t){return void 0===t&&(t=!1),n.defaults=t?e(n.defaults,r):r,this},o.prototype.errorType=function(r){return n.errorType=r,this},o.prototype.polyfills=function(t){return n.polyfills=r(r({},n.polyfills),t),this},o.prototype.url=function(r,t){if(void 0===t&&(t=!1),t)return this.selfFactory({url:r});var e=this._url.split("?");return this.selfFactory({url:e.length>1?e[0]+r+"?"+e[1]:this._url+r})},o.prototype.options=function(r,t){return void 0===t&&(t=!0),this.selfFactory({options:t?e(this._options,r):r})},o.prototype.query=function(r,t){return void 0===t&&(t=!1),this.selfFactory({url:a(this._url,r,t)})},o.prototype.headers=function(r){return this.selfFactory({options:e(this._options,{headers:r||{}})})},o.prototype.accept=function(r){return this.headers({Accept:r})},o.prototype.content=function(r){var t;return this.headers(((t={})["Content-Type"]=r,t))},o.prototype.auth=function(r){return this.headers({Authorization:r})},o.prototype.catcher=function(r,t){var e=new Map(this._catchers);return e.set(r,t),this.selfFactory({catchers:e})},o.prototype.signal=function(t){return this.selfFactory({options:r(r({},this._options),{signal:t.signal})})},o.prototype.resolve=function(r,e){return void 0===e&&(e=!1),this.selfFactory({resolvers:e?[r]:t(this._resolvers,[r])})},o.prototype.defer=function(r,e){return void 0===e&&(e=!1),this.selfFactory({deferredChain:e?[r]:t(this._deferredChain,[r])})},o.prototype.middlewares=function(r,e){return void 0===e&&(e=!1),this.selfFactory({middlewares:e?r:t(this._middlewares,r)})},o.prototype.method=function(t,o,u){void 0===o&&(o={}),void 0===u&&(u=null);var a=this._options.headers,c=u?"object"!=typeof u||a&&!Object.entries(a).every((function(r){var t=r[0],e=r[1];return t.toLowerCase()!=="Content-Type".toLowerCase()||"application/json"===e}))?this.body(u):this.json(u):this;return function(r){var t=r._url,o=r._catchers,u=r._resolvers,a=r._middlewares,c=r._options,f=new Map(o),l=e(n.defaults,c),p=n.polyfill("AbortController",{doThrow:!1,instance:!0});!l.signal&&p&&(l.signal=p.signal);var h={ref:null,clear:function(){h.ref&&(clearTimeout(h.ref),h.ref=null)}},d=function(r){return function(t){return 0===r.length?t:1===r.length?r[0](t):r.reduceRight((function(e,n,o){return o===r.length-2?n(e(t)):n(e)}))}}(a)(n.polyfill("fetch"))(t,l),y=d.catch((function(r){throw new s(r)})).then((function(r){return h.clear(),r.ok?r:r[n.errorType||"text"]().then((function(t){var e=new Error(t);throw e[n.errorType||"text"]=t,e.status=r.status,e.response=r,e}))})),v=function(t){return t.catch((function(t){h.clear();var e=t instanceof s?t.error:t;if(t instanceof s&&f.has("__fromFetch"))return f.get("__fromFetch")(e,r);if(f.has(e.status))return f.get(e.status)(e,r);if(f.has(e.name))return f.get(e.name)(e,r);throw e}))},m=function(r){return function(t){return v(r?y.then((function(t){return t&&t[r]()})).then((function(r){return t?t(r):r})):y.then((function(r){return t?t(r):r})))}},b={res:m(null),json:m("json"),blob:m("blob"),formData:m("formData"),arrayBuffer:m("arrayBuffer"),text:m("text"),perfs:function(r){return d.then((function(t){return i.observe(t.url,r)})),b},setTimeout:function(r,t){return void 0===t&&(t=p),h.clear(),h.ref=setTimeout((function(){return t.abort()}),r),b},controller:function(){return[p,b]},error:function(r,t){return f.set(r,t),b},badRequest:function(r){return b.error(400,r)},unauthorized:function(r){return b.error(401,r)},forbidden:function(r){return b.error(403,r)},notFound:function(r){return b.error(404,r)},timeout:function(r){return b.error(408,r)},internalError:function(r){return b.error(500,r)},fetchError:function(r){return b.error("__fromFetch",r)},onAbort:function(r){return b.error("AbortError",r)}};return u.reduce((function(t,e){return e(t,r)}),b)}((c=c.options(r(r({},o),{method:t})))._deferredChain.reduce((function(r,t){return t(r,r._url,r._options)}),c))},o.prototype.get=function(r){return this.method("GET",r)},o.prototype.delete=function(r){return this.method("DELETE",r)},o.prototype.put=function(r,t){return this.method("PUT",t,r)},o.prototype.post=function(r,t){return this.method("POST",t,r)},o.prototype.patch=function(r,t){return this.method("PATCH",t,r)},o.prototype.head=function(r){return this.method("HEAD",r)},o.prototype.opts=function(r){return this.method("OPTIONS",r)},o.prototype.replay=function(r){return this.method(this._options.method,r)},o.prototype.body=function(t){return this.selfFactory({options:r(r({},this._options),{body:t})})},o.prototype.json=function(r){return this.content("application/json").body(JSON.stringify(r))},o.prototype.formData=function(r,e){return void 0===e&&(e=!1),this.body(function r(e,o,i,s){void 0===o&&(o=!1);void 0===i&&(i=n.polyfill("FormData",{instance:!0}));void 0===s&&(s=[]);return Object.entries(e).forEach((function(e){var n=e[0],u=e[1],a=s.reduce((function(r,t){return r?r+"["+t+"]":t}),null);if(a=a?a+"["+n+"]":n,u instanceof Array)for(var c=0,f=u;c {\n if(!entries.getEntriesByName)\n return false\n const matches = entries.getEntriesByName(name)\n if(matches && matches.length > 0) {\n callback(matches.reverse()[0])\n if(_performance.clearMeasures)\n _performance.clearMeasures(name)\n perfs.callbacks.delete(name)\n\n if(perfs.callbacks.size < 1) {\n perfs.observer.disconnect()\n if(_performance.clearResourceTimings) {\n _performance.clearResourceTimings()\n }\n }\n return true\n }\n return false\n}\n\nconst lazyObserver = (_performance, _observer) => {\n if(!perfs.observer && _performance && _observer) {\n perfs.observer = new _observer(entries => {\n perfs.callbacks.forEach((callback, name) => {\n onMatch(entries, name, callback, _performance)\n })\n })\n if(_performance.clearResourceTimings)\n _performance.clearResourceTimings()\n }\n return perfs.observer\n}\n\nconst perfs = {\n callbacks: new Map(),\n observer: null,\n observe: (name, callback) => {\n if(!name || !callback)\n return\n\n const _performance = conf.polyfill(\"performance\", { doThrow: false })\n const _observer = conf.polyfill(\"PerformanceObserver\", { doThrow: false })\n\n if(!lazyObserver(_performance, _observer))\n return\n\n if(!onMatch(_performance, name, callback, _performance)) {\n if(perfs.callbacks.size < 1)\n perfs.observer.observe({ entryTypes: [\"resource\", \"measure\"] })\n perfs.callbacks.set(name, callback)\n }\n\n }\n}\n\nexport default perfs\n","import { Wretcher } from \"./wretcher\"\nimport { mix } from \"./mix\"\nimport conf from \"./config\"\nimport perfs from \"./perfs\"\nimport { middlewareHelper } from \"./middleware\"\n\nexport type WretcherError = Error & { status: number, response: WretcherResponse, text?: string, json?: any }\nexport type WretcherErrorCallback = (error: WretcherError, originalRequest: Wretcher) => any\nexport type WretcherResponse = Response & { [key: string]: any }\nexport type ResponseChain = {\n // Response types\n res: (cb?: (type: WretcherResponse) => Result) => Promise,\n json: (cb?: (type: {[key: string]: any}) => Result) => Promise,\n blob: (cb?: (type: Blob) => Result) => Promise,\n formData: (cb?: (type: FormData) => Result) => Promise,\n arrayBuffer: (cb?: (type: ArrayBuffer) => Result) => Promise,\n text: (cb?: (type: string) => Result) => Promise,\n // Extras\n perfs: (cb?: (timing: any) => void) => ResponseChain,\n setTimeout: (time: number, controller?: AbortController) => ResponseChain,\n controller: () => [any, ResponseChain],\n // Catchers\n error: (code: (number | string), cb: WretcherErrorCallback) => ResponseChain,\n badRequest: (cb: WretcherErrorCallback) => ResponseChain,\n unauthorized: (cb: WretcherErrorCallback) => ResponseChain,\n forbidden: (cb: WretcherErrorCallback) => ResponseChain,\n notFound: (cb: WretcherErrorCallback) => ResponseChain,\n timeout: (cb: WretcherErrorCallback) => ResponseChain,\n internalError: (cb: WretcherErrorCallback) => ResponseChain,\n fetchError: (cb: WretcherErrorCallback) => ResponseChain,\n onAbort: (cb: WretcherErrorCallback) => ResponseChain\n}\n\nclass WretchErrorWrapper {\n constructor(public error: any) {}\n}\n\nexport const resolver = (wretcher: Wretcher) => {\n const {\n _url: url,\n _catchers: _catchers,\n _resolvers: resolvers,\n _middlewares: middlewares,\n _options: opts\n } = wretcher\n const catchers = new Map(_catchers)\n const finalOptions = mix(conf.defaults, opts)\n const fetchController = conf.polyfill(\"AbortController\", { doThrow: false, instance: true })\n if(!finalOptions[\"signal\"] && fetchController) {\n finalOptions[\"signal\"] = fetchController.signal\n }\n // Request timeout\n const timeout = {\n ref: null,\n clear() {\n if(timeout.ref) {\n clearTimeout(timeout.ref)\n timeout.ref = null\n }\n }\n }\n // The generated fetch request\n const fetchRequest = middlewareHelper(middlewares)(conf.polyfill(\"fetch\"))(url, finalOptions)\n // Throws on an http error\n const throwingPromise: Promise = fetchRequest\n .catch(error => {\n throw new WretchErrorWrapper(error)\n })\n .then(response => {\n timeout.clear()\n if (!response.ok) {\n return response[conf.errorType || \"text\"]().then(msg => {\n // Enhances the error object\n const err = new Error(msg)\n err[conf.errorType || \"text\"] = msg\n err[\"status\"] = response.status\n err[\"response\"] = response\n throw err\n })\n }\n return response\n })\n // Wraps the Promise in order to dispatch the error to a matching catcher\n const catchersWrapper = (promise: Promise): Promise => {\n return promise.catch(err => {\n timeout.clear()\n const error = err instanceof WretchErrorWrapper ? err.error : err\n if(err instanceof WretchErrorWrapper && catchers.has(\"__fromFetch\"))\n return catchers.get(\"__fromFetch\")(error, wretcher)\n else if(catchers.has(error.status))\n return catchers.get(error.status)(error, wretcher)\n else if(catchers.has(error.name))\n return catchers.get(error.name)(error, wretcher)\n else\n throw error\n })\n }\n // Enforces the proper promise type when a body parsing method is called.\n type BodyParser = (funName: string | null) => (cb?: (type: Type) => Result) => Promise\n const bodyParser: BodyParser = (funName) => (cb) => funName ?\n // If a callback is provided, then callback with the body result otherwise return the parsed body itself.\n catchersWrapper(throwingPromise.then(_ => _ && _[funName]()).then(_ => cb ? cb(_) : _)) :\n // No body parsing method - return the response\n catchersWrapper(throwingPromise.then(_ => cb ? cb(_) : _))\n\n const responseChain: ResponseChain = {\n /**\n * Retrieves the raw result as a promise.\n */\n res: bodyParser(null),\n /**\n * Retrieves the result as a parsed JSON object.\n */\n json: bodyParser(\"json\"),\n /**\n * Retrieves the result as a Blob object.\n */\n blob: bodyParser(\"blob\"),\n /**\n * Retrieves the result as a FormData object.\n */\n formData: bodyParser(\"formData\"),\n /**\n * Retrieves the result as an ArrayBuffer object.\n */\n arrayBuffer: bodyParser(\"arrayBuffer\"),\n /**\n * Retrieves the result as a string.\n */\n text: bodyParser(\"text\"),\n /**\n * Performs a callback on the API performance timings of the request.\n *\n * Warning: Still experimental on browsers and node.js\n */\n perfs: cb => {\n fetchRequest.then(res => perfs.observe(res.url, cb))\n return responseChain\n },\n /**\n * Aborts the request after a fixed time.\n *\n * @param time Time in milliseconds\n * @param controller A custom controller\n */\n setTimeout: (time, controller = fetchController) => {\n timeout.clear()\n timeout.ref = setTimeout(() => controller.abort(), time)\n return responseChain\n },\n /**\n * Returns the automatically generated AbortController alongside the current wretch response as a pair.\n */\n controller: () => [ fetchController, responseChain ],\n /**\n * Catches an http response with a specific error code or name and performs a callback.\n */\n error(errorId, cb) {\n catchers.set(errorId, cb)\n return responseChain\n },\n /**\n * Catches a bad request (http code 400) and performs a callback.\n */\n badRequest: cb => responseChain.error(400, cb),\n /**\n * Catches an unauthorized request (http code 401) and performs a callback.\n */\n unauthorized: cb => responseChain.error(401, cb),\n /**\n * Catches a forbidden request (http code 403) and performs a callback.\n */\n forbidden: cb => responseChain.error(403, cb),\n /**\n * Catches a \"not found\" request (http code 404) and performs a callback.\n */\n notFound: cb => responseChain.error(404, cb),\n /**\n * Catches a timeout (http code 408) and performs a callback.\n */\n timeout: cb => responseChain.error(408, cb),\n /**\n * Catches an internal server error (http code 500) and performs a callback.\n */\n internalError: cb => responseChain.error(500, cb),\n /**\n * Catches errors thrown when calling the fetch function and performs a callback.\n */\n fetchError: cb => responseChain.error(\"__fromFetch\", cb),\n /**\n * Catches an AbortError and performs a callback.\n */\n onAbort: cb => responseChain.error(\"AbortError\", cb)\n }\n\n return resolvers.reduce((chain, r) => r(chain, wretcher), responseChain) as (ResponseChain & Promise)\n}\n","import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ \"Content-Type\" : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method, options = {}, body = null) {\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options?) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options?) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body?, options?) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body?, options?) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body?, options?) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options?) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options?) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options?) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(\"application/json\").body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n","import { WretcherOptions } from \"./wretcher\"\nimport { WretcherResponse } from \"./resolver\"\n\nexport type Middleware = (options?: {[key: string]: any}) => ConfiguredMiddleware\nexport type ConfiguredMiddleware = (next: FetchLike) => FetchLike\nexport type FetchLike = (url: string, opts: WretcherOptions) => Promise\n\nexport const middlewareHelper = (middlewares: ConfiguredMiddleware[]) => (fetchFunction: FetchLike): FetchLike => {\n return (\n middlewares.length === 0 ?\n fetchFunction :\n middlewares.length === 1 ?\n middlewares[0](fetchFunction) :\n middlewares.reduceRight((acc, curr, idx): any =>\n (idx === middlewares.length - 2) ? curr(acc(fetchFunction)) : curr(acc as any)\n )\n ) as FetchLike\n}\n","import { Wretcher } from \"./wretcher\"\n\nconst factory = Wretcher.factory\nfactory[\"default\"] = Wretcher.factory\n\n/**\n * Return a fresh Wretcher instance.\n */\nexport default factory\n"],"names":["mix","one","two","mergeArrays","clone","prop","hasOwnProperty","Array","config","defaults","errorType","polyfills","fetch","FormData","URLSearchParams","performance","PerformanceObserver","AbortController","polyfill","p","_a","_b","_c","doThrow","_d","instance","_i","args","res","this","self","global","Error","onMatch","entries","name","callback","_performance","getEntriesByName","matches","length","reverse","clearMeasures","perfs","callbacks","delete","size","observer","disconnect","clearResourceTimings","Map","observe","conf","_observer","forEach","lazyObserver","entryTypes","set","error","_url","_options","_catchers","_resolvers","_middlewares","_deferredChain","Wretcher","url","options","_e","catchers","_f","resolvers","_g","middlewares","_h","deferredChain","mixin","method","replace","selfFactory","split","qp","appendQueryParams","headerValues","headers","headerValue","Accept","Content-Type","Authorization","errorId","catcher","newMap","controller","signal","doResolve","clear","body","baseWretcher","json","wretcher","opts","finalOptions","fetchController","timeout","ref","clearTimeout","fetchRequest","fetchFunction","reduceRight","acc","curr","idx","middlewareHelper","throwingPromise","catch","WretchErrorWrapper","then","response","ok","msg","err","status","catchersWrapper","promise","has","get","bodyParser","funName","cb","_","responseChain","blob","formData","arrayBuffer","text","setTimeout","time","abort","badRequest","unauthorized","forbidden","notFound","internalError","fetchError","onAbort","reduce","chain","r","resolver","contents","jsObject","content","JSON","stringify","formObject","recursive","convertFormData","ancestors","Object","key","value","formKey","ancestor","value_1","item","append","includes","input","keys","map","v","encodeQueryValue","join","queryString","usp","val","toString","encodeURIComponent","factory"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"wretch.js","sources":["../../src/mix.ts","../../src/config.ts","../../src/perfs.ts","../../src/resolver.ts","../../src/wretcher.ts","../../src/middleware.ts","../../src/index.umd.ts"],"sourcesContent":["export const mix = function (one: object, two: object, mergeArrays: boolean = false) {\n if(!one || !two || typeof one !== \"object\" || typeof two !== \"object\")\n return one\n\n const clone = { ...one }\n for(const prop in two) {\n if(two.hasOwnProperty(prop)) {\n if(two[prop] instanceof Array && one[prop] instanceof Array) {\n clone[prop] = mergeArrays ? [ ...one[prop], ...two[prop] ] : two[prop]\n } else if(typeof two[prop] === \"object\" && typeof one[prop] === \"object\") {\n clone[prop] = mix(one[prop], two[prop], mergeArrays)\n } else {\n clone[prop] = two[prop]\n }\n }\n }\n\n return clone\n}\n","declare const global\n\nconst config = {\n // Default options\n defaults: {},\n // Error type\n errorType: null,\n // Polyfills\n polyfills: {\n fetch: null,\n FormData: null,\n URLSearchParams: null,\n performance: null,\n PerformanceObserver: null,\n AbortController: null\n },\n polyfill(p: string, { doThrow = true, instance = false } = {}, ...args) {\n const res = this.polyfills[p] ||\n (typeof self !== \"undefined\" ? self[p] : null) ||\n (typeof global !== \"undefined\" ? global[p] : null)\n if(doThrow && !res) throw new Error(p + \" is not defined\")\n return instance && res ? new res(...args) : res\n }\n}\n\nexport default config\n","import conf from \"./config\"\n\nconst onMatch = (entries, name, callback, _performance) => {\n if(!entries.getEntriesByName)\n return false\n const matches = entries.getEntriesByName(name)\n if(matches && matches.length > 0) {\n callback(matches.reverse()[0])\n if(_performance.clearMeasures)\n _performance.clearMeasures(name)\n perfs.callbacks.delete(name)\n\n if(perfs.callbacks.size < 1) {\n perfs.observer.disconnect()\n if(_performance.clearResourceTimings) {\n _performance.clearResourceTimings()\n }\n }\n return true\n }\n return false\n}\n\nconst lazyObserver = (_performance, _observer) => {\n if(!perfs.observer && _performance && _observer) {\n perfs.observer = new _observer(entries => {\n perfs.callbacks.forEach((callback, name) => {\n onMatch(entries, name, callback, _performance)\n })\n })\n if(_performance.clearResourceTimings)\n _performance.clearResourceTimings()\n }\n return perfs.observer\n}\n\nconst perfs = {\n callbacks: new Map(),\n observer: null,\n observe: (name, callback) => {\n if(!name || !callback)\n return\n\n const _performance = conf.polyfill(\"performance\", { doThrow: false })\n const _observer = conf.polyfill(\"PerformanceObserver\", { doThrow: false })\n\n if(!lazyObserver(_performance, _observer))\n return\n\n if(!onMatch(_performance, name, callback, _performance)) {\n if(perfs.callbacks.size < 1)\n perfs.observer.observe({ entryTypes: [\"resource\", \"measure\"] })\n perfs.callbacks.set(name, callback)\n }\n\n }\n}\n\nexport default perfs\n","import { Wretcher } from \"./wretcher\"\nimport { mix } from \"./mix\"\nimport conf from \"./config\"\nimport perfs from \"./perfs\"\nimport { middlewareHelper } from \"./middleware\"\n\nexport type WretcherError = Error & { status: number, response: WretcherResponse, text?: string, json?: any }\nexport type WretcherErrorCallback = (error: WretcherError, originalRequest: Wretcher) => any\nexport type WretcherResponse = Response & { [key: string]: any }\nexport type ResponseChain = {\n // Response types\n res: (cb?: (type: WretcherResponse) => Result) => Promise,\n json: (cb?: (type: {[key: string]: any}) => Result) => Promise,\n blob: (cb?: (type: Blob) => Result) => Promise,\n formData: (cb?: (type: FormData) => Result) => Promise,\n arrayBuffer: (cb?: (type: ArrayBuffer) => Result) => Promise,\n text: (cb?: (type: string) => Result) => Promise,\n // Extras\n perfs: (cb?: (timing: any) => void) => ResponseChain,\n setTimeout: (time: number, controller?: AbortController) => ResponseChain,\n controller: () => [any, ResponseChain],\n // Catchers\n error: (code: (number | string), cb: WretcherErrorCallback) => ResponseChain,\n badRequest: (cb: WretcherErrorCallback) => ResponseChain,\n unauthorized: (cb: WretcherErrorCallback) => ResponseChain,\n forbidden: (cb: WretcherErrorCallback) => ResponseChain,\n notFound: (cb: WretcherErrorCallback) => ResponseChain,\n timeout: (cb: WretcherErrorCallback) => ResponseChain,\n internalError: (cb: WretcherErrorCallback) => ResponseChain,\n fetchError: (cb: WretcherErrorCallback) => ResponseChain,\n onAbort: (cb: WretcherErrorCallback) => ResponseChain\n}\n\nclass WretchErrorWrapper {\n constructor(public error: any) {}\n}\n\nexport const resolver = (wretcher: Wretcher) => {\n const {\n _url: url,\n _catchers: _catchers,\n _resolvers: resolvers,\n _middlewares: middlewares,\n _options: opts\n } = wretcher\n const catchers = new Map(_catchers)\n const finalOptions = mix(conf.defaults, opts)\n const fetchController = conf.polyfill(\"AbortController\", { doThrow: false, instance: true })\n if(!finalOptions[\"signal\"] && fetchController) {\n finalOptions[\"signal\"] = fetchController.signal\n }\n // Request timeout\n const timeout = {\n ref: null,\n clear() {\n if(timeout.ref) {\n clearTimeout(timeout.ref)\n timeout.ref = null\n }\n }\n }\n // The generated fetch request\n const fetchRequest = middlewareHelper(middlewares)(conf.polyfill(\"fetch\"))(url, finalOptions)\n // Throws on an http error\n const throwingPromise: Promise = fetchRequest\n .catch(error => {\n throw new WretchErrorWrapper(error)\n })\n .then(response => {\n timeout.clear()\n if (!response.ok) {\n return response[conf.errorType || \"text\"]().then(msg => {\n // Enhances the error object\n const err = new Error(msg)\n err[conf.errorType || \"text\"] = msg\n err[\"status\"] = response.status\n err[\"response\"] = response\n throw err\n })\n }\n return response\n })\n // Wraps the Promise in order to dispatch the error to a matching catcher\n const catchersWrapper = (promise: Promise): Promise => {\n return promise.catch(err => {\n timeout.clear()\n const error = err instanceof WretchErrorWrapper ? err.error : err\n if(err instanceof WretchErrorWrapper && catchers.has(\"__fromFetch\"))\n return catchers.get(\"__fromFetch\")(error, wretcher)\n else if(catchers.has(error.status))\n return catchers.get(error.status)(error, wretcher)\n else if(catchers.has(error.name))\n return catchers.get(error.name)(error, wretcher)\n else\n throw error\n })\n }\n // Enforces the proper promise type when a body parsing method is called.\n type BodyParser = (funName: string | null) => (cb?: (type: Type) => Result) => Promise\n const bodyParser: BodyParser = (funName) => (cb) => funName ?\n // If a callback is provided, then callback with the body result otherwise return the parsed body itself.\n catchersWrapper(throwingPromise.then(_ => _ && _[funName]()).then(_ => cb ? cb(_) : _)) :\n // No body parsing method - return the response\n catchersWrapper(throwingPromise.then(_ => cb ? cb(_) : _))\n\n const responseChain: ResponseChain = {\n /**\n * Retrieves the raw result as a promise.\n */\n res: bodyParser(null),\n /**\n * Retrieves the result as a parsed JSON object.\n */\n json: bodyParser(\"json\"),\n /**\n * Retrieves the result as a Blob object.\n */\n blob: bodyParser(\"blob\"),\n /**\n * Retrieves the result as a FormData object.\n */\n formData: bodyParser(\"formData\"),\n /**\n * Retrieves the result as an ArrayBuffer object.\n */\n arrayBuffer: bodyParser(\"arrayBuffer\"),\n /**\n * Retrieves the result as a string.\n */\n text: bodyParser(\"text\"),\n /**\n * Performs a callback on the API performance timings of the request.\n *\n * Warning: Still experimental on browsers and node.js\n */\n perfs: cb => {\n fetchRequest.then(res => perfs.observe(res.url, cb))\n return responseChain\n },\n /**\n * Aborts the request after a fixed time.\n *\n * @param time Time in milliseconds\n * @param controller A custom controller\n */\n setTimeout: (time, controller = fetchController) => {\n timeout.clear()\n timeout.ref = setTimeout(() => controller.abort(), time)\n return responseChain\n },\n /**\n * Returns the automatically generated AbortController alongside the current wretch response as a pair.\n */\n controller: () => [ fetchController, responseChain ],\n /**\n * Catches an http response with a specific error code or name and performs a callback.\n */\n error(errorId, cb) {\n catchers.set(errorId, cb)\n return responseChain\n },\n /**\n * Catches a bad request (http code 400) and performs a callback.\n */\n badRequest: cb => responseChain.error(400, cb),\n /**\n * Catches an unauthorized request (http code 401) and performs a callback.\n */\n unauthorized: cb => responseChain.error(401, cb),\n /**\n * Catches a forbidden request (http code 403) and performs a callback.\n */\n forbidden: cb => responseChain.error(403, cb),\n /**\n * Catches a \"not found\" request (http code 404) and performs a callback.\n */\n notFound: cb => responseChain.error(404, cb),\n /**\n * Catches a timeout (http code 408) and performs a callback.\n */\n timeout: cb => responseChain.error(408, cb),\n /**\n * Catches an internal server error (http code 500) and performs a callback.\n */\n internalError: cb => responseChain.error(500, cb),\n /**\n * Catches errors thrown when calling the fetch function and performs a callback.\n */\n fetchError: cb => responseChain.error(\"__fromFetch\", cb),\n /**\n * Catches an AbortError and performs a callback.\n */\n onAbort: cb => responseChain.error(\"AbortError\", cb)\n }\n\n return resolvers.reduce((chain, r) => r(chain, wretcher), responseChain) as (ResponseChain & Promise)\n}\n","import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\nconst JSON_MIME = \"application/json\"\nconst CONTENT_TYPE_HEADER = \"Content-Type\"\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ [CONTENT_TYPE_HEADER] : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method : string, options = {}, body = null) {\n const headers = this._options.headers\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" && (\n !headers ||\n Object.entries(headers).every(([k, v]) =>\n k.toLowerCase() !== CONTENT_TYPE_HEADER.toLowerCase() ||\n v === JSON_MIME\n )\n ) ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options? : WretcherOptions) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options? : WretcherOptions) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body? : any, options? : WretcherOptions) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body? : any, options? : WretcherOptions) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body? : any, options? : WretcherOptions) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options? : WretcherOptions) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options? : WretcherOptions) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options? : WretcherOptions) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(JSON_MIME).body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n","import { WretcherOptions } from \"./wretcher\"\nimport { WretcherResponse } from \"./resolver\"\n\nexport type Middleware = (options?: {[key: string]: any}) => ConfiguredMiddleware\nexport type ConfiguredMiddleware = (next: FetchLike) => FetchLike\nexport type FetchLike = (url: string, opts: WretcherOptions) => Promise\n\nexport const middlewareHelper = (middlewares: ConfiguredMiddleware[]) => (fetchFunction: FetchLike): FetchLike => {\n return (\n middlewares.length === 0 ?\n fetchFunction :\n middlewares.length === 1 ?\n middlewares[0](fetchFunction) :\n middlewares.reduceRight((acc, curr, idx): any =>\n (idx === middlewares.length - 2) ? curr(acc(fetchFunction)) : curr(acc as any)\n )\n ) as FetchLike\n}\n","import { Wretcher } from \"./wretcher\"\n\nconst factory = Wretcher.factory\nfactory[\"default\"] = Wretcher.factory\n\n/**\n * Return a fresh Wretcher instance.\n */\nexport default factory\n"],"names":["mix","one","two","mergeArrays","clone","prop","hasOwnProperty","Array","config","defaults","errorType","polyfills","fetch","FormData","URLSearchParams","performance","PerformanceObserver","AbortController","polyfill","p","_a","_b","_c","doThrow","_d","instance","_i","args","res","this","self","global","Error","onMatch","entries","name","callback","_performance","getEntriesByName","matches","length","reverse","clearMeasures","perfs","callbacks","delete","size","observer","disconnect","clearResourceTimings","Map","observe","conf","_observer","forEach","lazyObserver","entryTypes","set","error","_url","_options","_catchers","_resolvers","_middlewares","_deferredChain","Wretcher","url","options","_e","catchers","_f","resolvers","_g","middlewares","_h","deferredChain","mixin","method","replace","selfFactory","split","qp","appendQueryParams","headerValues","headers","headerValue","Accept","Authorization","errorId","catcher","newMap","controller","signal","doResolve","clear","body","baseWretcher","Object","every","k","v","toLowerCase","json","wretcher","opts","finalOptions","fetchController","timeout","ref","clearTimeout","fetchRequest","fetchFunction","reduceRight","acc","curr","idx","middlewareHelper","throwingPromise","catch","WretchErrorWrapper","then","response","ok","msg","err","status","catchersWrapper","promise","has","get","bodyParser","funName","cb","_","responseChain","blob","formData","arrayBuffer","text","setTimeout","time","abort","badRequest","unauthorized","forbidden","notFound","internalError","fetchError","onAbort","reduce","chain","r","resolver","contents","jsObject","content","JSON","stringify","formObject","recursive","convertFormData","ancestors","key","value","formKey","ancestor","value_1","item","append","includes","input","keys","map","encodeQueryValue","join","queryString","usp","val","toString","encodeURIComponent","factory"],"mappings":"ukBAAO,IAAMA,EAAM,SAAUC,EAAaC,EAAaC,GACnD,gBADmDA,OAC/CF,IAAQC,GAAsB,iBAARD,GAAmC,iBAARC,EACjD,OAAOD,EAEX,IAAMG,OAAaH,GACnB,IAAI,IAAMI,KAAQH,EACXA,EAAII,eAAeD,KACfH,EAAIG,aAAiBE,OAASN,EAAII,aAAiBE,MAClDH,EAAMC,GAAQF,IAAmBF,EAAII,GAAUH,EAAIG,IAAUH,EAAIG,GACtC,iBAAdH,EAAIG,IAA2C,iBAAdJ,EAAII,GAClDD,EAAMC,GAAQL,EAAIC,EAAII,GAAOH,EAAIG,GAAOF,GAExCC,EAAMC,GAAQH,EAAIG,IAK9B,OAAOD,GCfLI,EAAS,CAEXC,SAAU,GAEVC,UAAW,KAEXC,UAAW,CACPC,MAAO,KACPC,SAAU,KACVC,gBAAiB,KACjBC,YAAa,KACbC,oBAAqB,KACrBC,gBAAiB,MAErBC,SAAA,SAASC,EAAWC,WAAAC,kBAAEC,YAAAC,gBAAgBC,aAAAC,yBAAyBC,mBAAAA,IAAAC,oBAC3D,IAAMC,EAAMC,KAAKlB,UAAUQ,KACN,oBAATW,KAAuBA,KAAKX,GAAK,QACtB,oBAAXY,OAAyBA,OAAOZ,GAAK,MACjD,GAAGI,IAAYK,EAAK,MAAM,IAAII,MAAMb,EAAI,mBACxC,OAAOM,GAAYG,MAAUA,aAAAA,aAAOD,KAAQC,ICnB9CK,EAAU,SAACC,EAASC,EAAMC,EAAUC,GACtC,IAAIH,EAAQI,iBACR,OAAO,EACX,IAAMC,EAAUL,EAAQI,iBAAiBH,GACzC,SAAGI,GAAWA,EAAQC,OAAS,KAC3BJ,EAASG,EAAQE,UAAU,IACxBJ,EAAaK,eACZL,EAAaK,cAAcP,GAC/BQ,EAAMC,UAAUC,OAAOV,GAEpBQ,EAAMC,UAAUE,KAAO,IACtBH,EAAMI,SAASC,aACZX,EAAaY,sBACZZ,EAAaY,yBAGd,IAkBTN,EAAQ,CACVC,UAAW,IAAIM,IACfH,SAAU,KACVI,QAAS,SAAChB,EAAMC,GACZ,GAAID,GAASC,EAAb,CAGA,IAAMC,EAAee,EAAKlC,SAAS,cAAe,CAAEK,SAAS,KApBhD,SAACc,EAAcgB,GAUhC,OATIV,EAAMI,UAAYV,GAAgBgB,IAClCV,EAAMI,SAAW,IAAIM,GAAU,SAAAnB,GAC3BS,EAAMC,UAAUU,SAAQ,SAAClB,EAAUD,GAC/BF,EAAQC,EAASC,EAAMC,EAAUC,SAGtCA,EAAaY,sBACZZ,EAAaY,wBAEdN,EAAMI,UAaLQ,CAAalB,EAFEe,EAAKlC,SAAS,sBAAuB,CAAEK,SAAS,OAK/DU,EAAQI,EAAcF,EAAMC,EAAUC,KACnCM,EAAMC,UAAUE,KAAO,GACtBH,EAAMI,SAASI,QAAQ,CAAEK,WAAY,CAAC,WAAY,aACtDb,EAAMC,UAAUa,IAAItB,EAAMC,UClBlC,SAAmBsB,GAAA7B,WAAA6B,gBCbnB,WACWC,EACAC,EACAC,EACAC,EACAC,EACAC,gBAHAH,MAAiGX,kBACjGY,mBACAC,mBACAC,MALAnC,UAAA8B,EACA9B,cAAA+B,EACA/B,eAAAgC,EACAhC,gBAAAiC,EACAjC,kBAAAkC,EACAlC,oBAAAmC,EA4Qf,OA1QWC,UAAP,SAAeC,EAAUC,GAAiC,oBAA3CD,mBAAUC,MAAwC,IAAIF,EAASC,EAAKC,IAC3EF,wBAAR,SAAoB7C,OAAAC,kBAAEC,QAAA4C,yBAAiB1C,YAAA2C,6BAAyBC,aAAAC,8BACpDC,cAAAC,+BAA6BC,gBAAAC,iCAAiCC,kBAAAC,mCACtE,OAAO,IAAIV,EAASC,OAASC,GAAU,IAAIjB,IAAImB,KAAeE,KAAgBE,KAAkBE,KAQpGV,qBAAA,SAASE,EAA0BS,GAE/B,oBAF+BA,MAC/BxB,EAAK3C,SAAWmE,EAAQ5E,EAAIoD,EAAK3C,SAAU0D,GAAWA,EAC/CtC,MAUXoC,sBAAA,SAAUY,GAEN,OADAzB,EAAK1C,UAAYmE,EACVhD,MAUXoC,sBAAA,SAAUtD,GAEN,OADAyC,EAAKzC,iBAAiByC,EAAKzC,WAAcA,GAClCkB,MAQXoC,gBAAA,SAAIC,EAAaY,GACb,gBADaA,MACVA,EACC,OAAOjD,KAAKkD,YAAY,CAAEb,QAC9B,IAAMc,EAAQnD,KAAK8B,KAAKqB,MAAM,KAC9B,OAAOnD,KAAKkD,YAAY,CACpBb,IAAKc,EAAMxC,OAAS,EAChBwC,EAAM,GAAKd,EAAM,IAAMc,EAAM,GAC7BnD,KAAK8B,KAAOO,KASxBD,oBAAA,SAAQE,EAA0BS,GAC9B,oBAD8BA,MACvB/C,KAAKkD,YAAY,CAAEZ,QAASS,EAAQ5E,EAAI6B,KAAK+B,SAAUO,GAAWA,KAsB7EF,kBAAA,SAAMgB,EAAqBH,GACvB,oBADuBA,MAChBjD,KAAKkD,YAAY,CAAEb,IAAKgB,EAAkBrD,KAAK8B,KAAMsB,EAAIH,MAOpEb,oBAAA,SAAQkB,GACJ,OAAOtD,KAAKkD,YAAY,CAAEZ,QAASnE,EAAI6B,KAAK+B,SAAU,CAAEwB,QAASD,GAAgB,QAOrFlB,mBAAA,SAAOoB,GACH,OAAOxD,KAAKuD,QAAQ,CAAEE,OAASD,KAOnCpB,oBAAA,SAAQoB,SACJ,OAAOxD,KAAKuD,gBA9HQ,gBA8H0BC,OAOlDpB,iBAAA,SAAKoB,GACD,OAAOxD,KAAKuD,QAAQ,CAAEG,cAAeF,KAQzCpB,oBAAA,SAAQuB,EAA0BC,GAC9B,IAAMC,EAAS,IAAIxC,IAAIrB,KAAKgC,WAE5B,OADA6B,EAAOjC,IAAI+B,EAASC,GACb5D,KAAKkD,YAAY,CAAEV,SAAUqB,KAOxCzB,mBAAA,SAAO0B,GACH,OAAO9D,KAAKkD,YAAY,CAAEZ,eAActC,KAAK+B,WAAUgC,OAAQD,EAAWC,YAO9E3B,oBAAA,SAAQ4B,EAA8FC,GAClG,oBADkGA,MAC3FjE,KAAKkD,YAAY,CAAER,UAAWuB,EAAQ,CAAED,KAAmBhE,KAAKiC,YAAY+B,OAMvF5B,kBAAA,SAAM7B,EAA4B0D,GAC9B,oBAD8BA,MACvBjE,KAAKkD,YAAY,CACpBJ,cAAemB,EAAQ,CAAC1D,KAAiBP,KAAKmC,gBAAgB5B,OAOtE6B,wBAAA,SAAYQ,EAAqCqB,GAC7C,oBAD6CA,MACtCjE,KAAKkD,YAAY,CACpBN,YAAaqB,EAAQrB,IAAmB5C,KAAKkC,aAAiBU,MAI9DR,mBAAR,SAAeY,EAAiBV,EAAc4B,gBAAd5B,mBAAc4B,QAC1C,IAAMX,EAAUvD,KAAK+B,SAASwB,QAC1BY,EACCD,EACe,iBAATA,GACFX,IACDa,OAAO/D,QAAQkD,GAASc,OAAM,SAAC9E,OAAC+E,OAAGC,OAC/B,OAAAD,EAAEE,gBA7LM,eA6LgCA,eA9L1C,qBA+LED,KAGRvE,KAAKkE,KAAKA,GADNlE,KAAKyE,KAAKP,GAPNlE,KAWZ,OD3KgB,SAAC0E,GAEjB,IAAArC,SACAL,cACAU,eACAE,iBACA+B,aAEEnC,EAAW,IAAInB,IAAIW,GACnB4C,EAAezG,EAAIoD,EAAK3C,SAAU+F,GAClCE,EAAkBtD,EAAKlC,SAAS,kBAAmB,CAAEK,SAAS,EAAOE,UAAU,KACjFgF,EAAqB,QAAKC,IAC1BD,EAAqB,OAAIC,EAAgBd,QAG7C,IAAMe,EAAU,CACZC,IAAK,KACLd,iBACOa,EAAQC,MACPC,aAAaF,EAAQC,KACrBD,EAAQC,IAAM,QAKpBE,EEvDsB,SAACrC,GAAwC,OAAA,SAACsC,GACtE,OAC2B,IAAvBtC,EAAYjC,OACTuE,EACoB,IAAvBtC,EAAYjC,OACRiC,EAAY,GAAGsC,GACnBtC,EAAYuC,aAAY,SAACC,EAAKC,EAAMC,GAChC,OAACA,IAAQ1C,EAAYjC,OAAS,EAAK0E,EAAKD,EAAIF,IAAkBG,EAAKD,OFgDtDG,CAAiB3C,EAAjB2C,CAA8BhE,EAAKlC,SAAS,SAA5CkG,CAAsDlD,EAAKuC,GAE1EY,EAAoDP,EACrDQ,OAAM,SAAA5D,GACH,MAAM,IAAI6D,EAAmB7D,MAEhC8D,MAAK,SAAAC,GAEF,OADAd,EAAQb,QACH2B,EAASC,GAUPD,EATIA,EAASrE,EAAK1C,WAAa,UAAU8G,MAAK,SAAAG,GAE7C,IAAMC,EAAM,IAAI5F,MAAM2F,GAItB,MAHAC,EAAIxE,EAAK1C,WAAa,QAAUiH,EAChCC,EAAY,OAAIH,EAASI,OACzBD,EAAc,SAAIH,EACZG,QAMhBE,EAAkB,SAAIC,GACxB,OAAOA,EAAQT,OAAM,SAAAM,GACjBjB,EAAQb,QACR,IAAMpC,EAAQkE,aAAeL,EAAqBK,EAAIlE,MAAQkE,EAC9D,GAAGA,aAAeL,GAAsBlD,EAAS2D,IAAI,eACjD,OAAO3D,EAAS4D,IAAI,cAAb5D,CAA4BX,EAAO6C,GACzC,GAAGlC,EAAS2D,IAAItE,EAAMmE,QACvB,OAAOxD,EAAS4D,IAAIvE,EAAMmE,OAAnBxD,CAA2BX,EAAO6C,GACxC,GAAGlC,EAAS2D,IAAItE,EAAMvB,MACvB,OAAOkC,EAAS4D,IAAIvE,EAAMvB,KAAnBkC,CAAyBX,EAAO6C,GAEvC,MAAM7C,MAKZwE,EAAyB,SAAIC,GAAY,OAAA,SAAIC,GAAO,OAEtDN,EAFsDK,EAEtCd,EAAgBG,MAAK,SAAAa,GAAK,OAAAA,GAAKA,EAAEF,QAAYX,MAAK,SAAAa,GAAK,OAAAD,EAAKA,EAAGC,GAAKA,KAEpEhB,EAAgBG,MAAK,SAAAa,GAAK,OAAAD,EAAKA,EAAGC,GAAKA,QAErDC,EAA+B,CAIjC1G,IAAKsG,EAA6B,MAIlC5B,KAAM4B,EAAgB,QAItBK,KAAML,EAAiB,QAIvBM,SAAUN,EAAqB,YAI/BO,YAAaP,EAAwB,eAIrCQ,KAAMR,EAAmB,QAMzBvF,MAAO,SAAAyF,GAEH,OADAtB,EAAaU,MAAK,SAAA5F,GAAO,OAAAe,EAAMQ,QAAQvB,EAAIsC,IAAKkE,MACzCE,GAQXK,WAAY,SAACC,EAAMjD,GAGf,oBAHeA,KACfgB,EAAQb,QACRa,EAAQC,IAAM+B,YAAW,WAAM,OAAAhD,EAAWkD,UAASD,GAC5CN,GAKX3C,WAAY,WAAM,MAAA,CAAEe,EAAiB4B,IAIrC5E,eAAM8B,EAAS4C,GAEX,OADA/D,EAASZ,IAAI+B,EAAS4C,GACfE,GAKXQ,WAAY,SAAAV,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAI3CW,aAAc,SAAAX,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAI7CY,UAAW,SAAAZ,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAI1Ca,SAAU,SAAAb,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAIzCzB,QAAS,SAAAyB,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAIxCc,cAAe,SAAAd,GAAM,OAAAE,EAAc5E,MAAM,IAAK0E,IAI9Ce,WAAY,SAAAf,GAAM,OAAAE,EAAc5E,MAAM,cAAe0E,IAIrDgB,QAAS,SAAAhB,GAAM,OAAAE,EAAc5E,MAAM,aAAc0E,KAGrD,OAAO7D,EAAU8E,QAAO,SAACC,EAAOC,GAAM,OAAAA,EAAED,EAAO/C,KAAW+B,GCa/CkB,EAFPxD,EAAeA,EAAa7B,eAAaA,IAASU,aACZb,eAAeqF,QAAO,SAACpC,EAAeC,GAAS,OAAAA,EAAKD,EAAKA,EAAItD,KAAMsD,EAAIrD,YAAWoC,KAO5H/B,gBAAA,SAAIE,GACA,OAAOtC,KAAKgD,OAAO,MAAOV,IAK9BF,mBAAA,SAAOE,GACH,OAAOtC,KAAKgD,OAAO,SAAUV,IAKjCF,gBAAA,SAAI8B,EAAa5B,GACb,OAAOtC,KAAKgD,OAAO,MAAOV,EAAS4B,IAKvC9B,iBAAA,SAAK8B,EAAa5B,GACd,OAAOtC,KAAKgD,OAAO,OAAQV,EAAS4B,IAKxC9B,kBAAA,SAAM8B,EAAa5B,GACf,OAAOtC,KAAKgD,OAAO,QAASV,EAAS4B,IAKzC9B,iBAAA,SAAKE,GACD,OAAOtC,KAAKgD,OAAO,OAAQV,IAK/BF,iBAAA,SAAKE,GACD,OAAOtC,KAAKgD,OAAO,UAAWV,IAKlCF,mBAAA,SAAOE,GACH,OAAOtC,KAAKgD,OAAOhD,KAAK+B,SAASiB,OAAQV,IAO7CF,iBAAA,SAAKwF,GACD,OAAO5H,KAAKkD,YAAY,CAAEZ,eAActC,KAAK+B,WAAUmC,KAAM0D,OAMjExF,iBAAA,SAAKyF,GACD,OAAO7H,KAAK8H,QArQF,oBAqQqB5D,KAAK6D,KAAKC,UAAUH,KASvDzF,qBAAA,SAAS6F,EAAoBC,GACzB,oBADyBA,MAClBlI,KAAKkE,KA0CpB,SAASiE,EACLF,EACAC,EACAvB,EACAyB,gBAFAF,mBACAvB,EAAYpF,EAAKlC,SAAS,WAAY,CAAEO,UAAU,kBAClDwI,MA0BA,OAxBAhE,OAAO/D,QAAQ4H,GAAYxG,SAAQ,SAAClC,OAAC8I,OAAKC,OAClCC,EAAUH,EAAUZ,QAAO,SAACpC,EAAKoD,GAAa,OAC9CpD,EAASA,MAAOoD,MAAcA,IAC/B,MAEH,GADAD,EAAUA,EAAaA,MAAWF,MAASA,EACxCC,aAAiB5J,MAChB,IAAkB,QAAA+J,IAAA5I,WAAAA,KAAd,IAAM6I,OACN/B,EAASgC,OAAOJ,EAAU,KAAMG,QAEpCR,GACiB,iBAAVI,GAEDJ,aAAqBxJ,OACtBwJ,EAAUU,SAASP,GAOxB1B,EAASgC,OAAOJ,EAASD,GAJZ,OAAVA,GACCH,EAAgBG,EAAOJ,EAAWvB,IAAcyB,GAAWC,QAOhE1B,EAxEcwB,CAAgBF,EAAYC,KAQjD9F,oBAAA,SAAQyG,GACJ,OAAO7I,KACFkE,KAAsB,iBAAV2E,EAAqBA,GA0EtBZ,EA1E6CY,EA2E1DzE,OAAO0E,KAAKb,GACdc,KAAI,SAAAV,GACD,IAAMC,EAAQL,EAAWI,GACzB,OAAGC,aAAiB5J,MACT4J,EAAMS,KAAI,SAAAxE,GAAK,OAAAyE,EAAiBX,EAAK9D,MAAI0E,KAAK,KAElDD,EAAiBX,EAAKC,MAEhCW,KAAK,OAlFDnB,QAAQ,qCAyErB,IAAwBG,QAnElB5E,EAAoB,SAAChB,EAAae,EAAqBH,GACzD,IAAIiG,EAEJ,GAAiB,iBAAP9F,EACN8F,EAAc9F,MACX,CACH,IAAM+F,EAAM5H,EAAKlC,SAAS,kBAAmB,CAAEO,UAAU,IACzD,IAAI,IAAMyI,KAAOjF,EACb,GAAGA,EAAGiF,aAAgB3J,MAClB,IAAiB,QAAAa,EAAA6D,EAAGiF,GAAHxI,WAAAA,KAAb,IAAMuJ,OACND,EAAIR,OAAON,EAAKe,QAEpBD,EAAIR,OAAON,EAAKjF,EAAGiF,IAG3Ba,EAAcC,EAAIE,WAGtB,IAAMlG,EAAQd,EAAIc,MAAM,KACxB,OAAGF,GAAWE,EAAMxC,OAAS,EAClBwC,EAAM,GAAK,IAAM+F,EAErB7G,EAAM,IAAM6G,GAoCvB,SAASF,EAAiBX,EAAaC,GACnC,OAAOgB,mBAAmBjB,GAC1B,IACAiB,mBACqB,iBAAVhB,EACHP,KAAKC,UAAUM,GACnB,GAAKA,GEzWb,IAAMiB,EAAUnH,EAASmH,eACzBA,EAAiB,QAAInH,EAASmH"} \ No newline at end of file diff --git a/dist/wretcher.d.ts b/dist/wretcher.d.ts index ce6ac99..c6f09e1 100644 --- a/dist/wretcher.d.ts +++ b/dist/wretcher.d.ts @@ -124,35 +124,35 @@ export declare class Wretcher { /** * Performs a get request. */ - get(options?: any): ResponseChain & Promise; + get(options?: WretcherOptions): ResponseChain & Promise; /** * Performs a delete request. */ - delete(options?: any): ResponseChain & Promise; + delete(options?: WretcherOptions): ResponseChain & Promise; /** * Performs a put request. */ - put(body?: any, options?: any): ResponseChain & Promise; + put(body?: any, options?: WretcherOptions): ResponseChain & Promise; /** * Performs a post request. */ - post(body?: any, options?: any): ResponseChain & Promise; + post(body?: any, options?: WretcherOptions): ResponseChain & Promise; /** * Performs a patch request. */ - patch(body?: any, options?: any): ResponseChain & Promise; + patch(body?: any, options?: WretcherOptions): ResponseChain & Promise; /** * Performs a head request. */ - head(options?: any): ResponseChain & Promise; + head(options?: WretcherOptions): ResponseChain & Promise; /** * Performs an options request */ - opts(options?: any): ResponseChain & Promise; + opts(options?: WretcherOptions): ResponseChain & Promise; /** * Replay a request. */ - replay(options?: any): ResponseChain & Promise; + replay(options?: WretcherOptions): ResponseChain & Promise; /** * Sets the request body with any content. * @param contents The body contents diff --git a/dist/wretcher.js b/dist/wretcher.js index 8b8e722..1681da4 100644 --- a/dist/wretcher.js +++ b/dist/wretcher.js @@ -19,6 +19,8 @@ var __spreadArrays = (this && this.__spreadArrays) || function () { import { mix } from "./mix"; import conf from "./config"; import { resolver } from "./resolver"; +var JSON_MIME = "application/json"; +var CONTENT_TYPE_HEADER = "Content-Type"; /** * The Wretcher class used to perform easy fetch requests. * @@ -145,7 +147,8 @@ var Wretcher = /** @class */ (function () { * @param headerValue Header value */ Wretcher.prototype.content = function (headerValue) { - return this.headers({ "Content-Type": headerValue }); + var _a; + return this.headers((_a = {}, _a[CONTENT_TYPE_HEADER] = headerValue, _a)); }; /** * Shortcut to set the "Authorization" header. @@ -200,8 +203,14 @@ var Wretcher = /** @class */ (function () { Wretcher.prototype.method = function (method, options, body) { if (options === void 0) { options = {}; } if (body === void 0) { body = null; } + var headers = this._options.headers; var baseWretcher = !body ? this : - typeof body === "object" ? this.json(body) : + typeof body === "object" && (!headers || + Object.entries(headers).every(function (_a) { + var k = _a[0], v = _a[1]; + return k.toLowerCase() !== CONTENT_TYPE_HEADER.toLowerCase() || + v === JSON_MIME; + })) ? this.json(body) : this.body(body); baseWretcher = baseWretcher.options(__assign(__assign({}, options), { method: method })); var deferredWretcher = baseWretcher._deferredChain.reduce(function (acc, curr) { return curr(acc, acc._url, acc._options); }, baseWretcher); @@ -267,7 +276,7 @@ var Wretcher = /** @class */ (function () { * @param jsObject An object which will be serialized into a JSON */ Wretcher.prototype.json = function (jsObject) { - return this.content("application/json").body(JSON.stringify(jsObject)); + return this.content(JSON_MIME).body(JSON.stringify(jsObject)); }; /** * Converts the javascript object to a FormData and sets the request body. diff --git a/dist/wretcher.js.map b/dist/wretcher.js.map index 5ecf317..4cd278e 100644 --- a/dist/wretcher.js.map +++ b/dist/wretcher.js.map @@ -1 +1 @@ -{"version":3,"file":"wretcher.js","sourceRoot":"","sources":["../src/wretcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ \"Content-Type\" : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method, options = {}, body = null) {\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options?) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options?) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body?, options?) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body?, options?) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body?, options?) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options?) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options?) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options?) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(\"application/json\").body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n"]} \ No newline at end of file +{"version":3,"file":"wretcher.js","sourceRoot":"","sources":["../src/wretcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { mix } from \"./mix\"\nimport conf from \"./config\"\nimport { resolver, WretcherError, ResponseChain } from \"./resolver\"\nimport { ConfiguredMiddleware } from \"./middleware\"\n\nexport type WretcherOptions = RequestInit & {\n [key: string]: any\n}\n\nexport type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher\n\nconst JSON_MIME = \"application/json\"\nconst CONTENT_TYPE_HEADER = \"Content-Type\"\n\n/**\n * The Wretcher class used to perform easy fetch requests.\n *\n * Immutability : almost every method of this class return a fresh Wretcher object.\n */\nexport class Wretcher {\n\n protected constructor(\n public _url: string,\n public _options: WretcherOptions,\n public _catchers: Map void> = new Map(),\n public _resolvers: ((resolver: ResponseChain, originalRequest: Wretcher) => any)[] = [],\n public _middlewares: ConfiguredMiddleware[] = [],\n public _deferredChain: DeferredCallback[] = []) {}\n\n static factory(url = \"\", options: WretcherOptions = {}) { return new Wretcher(url, options) }\n private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,\n resolvers = this._resolvers, middlewares = this._middlewares, deferredChain = this._deferredChain } = {}) {\n return new Wretcher(url, {...options}, new Map(catchers), [...resolvers], [...middlewares], [...deferredChain])\n }\n\n /**\n * Sets the default fetch options used for every subsequent fetch call.\n * @param options New default options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n defaults(options: WretcherOptions, mixin = false) {\n conf.defaults = mixin ? mix(conf.defaults, options) : options\n return this\n }\n\n /**\n * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.\n *\n * Persists for every subsequent requests.\n *\n * Default is \"text\".\n */\n errorType(method: \"text\" | \"json\") {\n conf.errorType = method\n return this\n }\n\n /**\n * Sets the non-global polyfills which will be used for every subsequent calls.\n *\n * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).\n *\n * @param polyfills An object containing the polyfills.\n */\n polyfills(polyfills: Partial) {\n conf.polyfills = { ...conf.polyfills, ...polyfills }\n return this\n }\n\n /**\n * Returns a new Wretcher object with the argument url appended and the same options.\n * @param url String url\n * @param replace Boolean If true, replaces the current url instead of appending\n */\n url(url: string, replace = false) {\n if(replace)\n return this.selfFactory({ url })\n const split = this._url.split(\"?\")\n return this.selfFactory({\n url: split.length > 1 ?\n split[0] + url + \"?\" + split[1] :\n this._url + url\n })\n }\n\n /**\n * Returns a new Wretcher object with the same url and new options.\n * @param options New options\n * @param mixin If true, mixes in instead of replacing the existing options\n */\n options(options: WretcherOptions, mixin = true) {\n return this.selfFactory({ options: mixin ? mix(this._options, options) : options })\n }\n\n /**\n * Converts a javascript object to query parameters,\n * then appends this query string to the current url.\n *\n * If given a string, use the string as the query verbatim.\n *\n * ```\n * let w = wretch(\"http://example.com\") // url is http://example.com\n *\n * // Chain query calls\n * w = w.query({ a: 1, b : 2 }) // url is now http://example.com?a=1&b=2\n * w = w.query(\"foo-bar-baz-woz\") // url is now http://example.com?a=1&b=2&foo-bar-baz-woz\n *\n * // Pass true as the second argument to replace existing query parameters\n * w = w.query(\"c=3&d=4\", true) // url is now http://example.com?c=3&d=4\n * ```\n *\n * @param qp An object which will be converted, or a string which will be used verbatim.\n */\n query(qp: object | string, replace: boolean = false) {\n return this.selfFactory({ url: appendQueryParams(this._url, qp, replace) })\n }\n\n /**\n * Set request headers.\n * @param headerValues An object containing header keys and values\n */\n headers(headerValues: { [headerName: string]: string }) {\n return this.selfFactory({ options: mix(this._options, { headers: headerValues || {} }) })\n }\n\n /**\n * Shortcut to set the \"Accept\" header.\n * @param headerValue Header value\n */\n accept(headerValue: string) {\n return this.headers({ Accept : headerValue })\n }\n\n /**\n * Shortcut to set the \"Content-Type\" header.\n * @param headerValue Header value\n */\n content(headerValue: string) {\n return this.headers({ [CONTENT_TYPE_HEADER] : headerValue })\n }\n\n /**\n * Shortcut to set the \"Authorization\" header.\n * @param headerValue Header value\n */\n auth(headerValue: string) {\n return this.headers({ Authorization: headerValue })\n }\n\n /**\n * Adds a default catcher which will be called on every subsequent request error when the error code matches.\n * @param errorId Error code or name\n * @param catcher: The catcher method\n */\n catcher(errorId: number | string, catcher: (error: WretcherError, originalRequest: Wretcher) => any) {\n const newMap = new Map(this._catchers)\n newMap.set(errorId, catcher)\n return this.selfFactory({ catchers: newMap })\n }\n\n /**\n * Associates a custom signal with the request.\n * @param controller : An AbortController\n */\n signal(controller: AbortController) {\n return this.selfFactory({ options: { ...this._options, signal: controller.signal }})\n }\n\n /**\n * Program a resolver to perform response chain tasks automatically.\n * @param doResolve : Resolver callback\n */\n resolve(doResolve: (chain: ResponseChain, originalRequest: Wretcher) => ResponseChain | Promise, clear: boolean = false) {\n return this.selfFactory({ resolvers: clear ? [ doResolve ] : [ ...this._resolvers, doResolve ]})\n }\n\n /**\n * Defer wretcher methods that will be chained and called just before the request is performed.\n */\n defer(callback: DeferredCallback, clear = false) {\n return this.selfFactory({\n deferredChain: clear ? [callback] : [ ...this._deferredChain, callback ]\n })\n }\n\n /**\n * Add middlewares to intercept a request before being sent.\n */\n middlewares(middlewares: ConfiguredMiddleware[], clear = false) {\n return this.selfFactory({\n middlewares: clear ? middlewares : [ ...this._middlewares, ...middlewares ]\n })\n }\n\n private method(method : string, options = {}, body = null) {\n const headers = this._options.headers\n let baseWretcher =\n !body ? this :\n typeof body === \"object\" && (\n !headers ||\n Object.entries(headers).every(([k, v]) =>\n k.toLowerCase() !== CONTENT_TYPE_HEADER.toLowerCase() ||\n v === JSON_MIME\n )\n ) ? this.json(body) :\n this.body(body)\n baseWretcher = baseWretcher.options({ ...options, method })\n const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher)\n return resolver(deferredWretcher)\n }\n\n /**\n * Performs a get request.\n */\n get(options? : WretcherOptions) {\n return this.method(\"GET\", options)\n }\n /**\n * Performs a delete request.\n */\n delete(options? : WretcherOptions) {\n return this.method(\"DELETE\", options)\n }\n /**\n * Performs a put request.\n */\n put(body? : any, options? : WretcherOptions) {\n return this.method(\"PUT\", options, body)\n }\n /**\n * Performs a post request.\n */\n post(body? : any, options? : WretcherOptions) {\n return this.method(\"POST\", options, body)\n }\n /**\n * Performs a patch request.\n */\n patch(body? : any, options? : WretcherOptions) {\n return this.method(\"PATCH\", options, body)\n }\n /**\n * Performs a head request.\n */\n head(options? : WretcherOptions) {\n return this.method(\"HEAD\", options)\n }\n /**\n * Performs an options request\n */\n opts(options? : WretcherOptions) {\n return this.method(\"OPTIONS\", options)\n }\n /**\n * Replay a request.\n */\n replay(options? : WretcherOptions) {\n return this.method(this._options.method, options)\n }\n\n /**\n * Sets the request body with any content.\n * @param contents The body contents\n */\n body(contents: any) {\n return this.selfFactory({ options: { ...this._options, body: contents }})\n }\n /**\n * Sets the content type header, stringifies an object and sets the request body.\n * @param jsObject An object which will be serialized into a JSON\n */\n json(jsObject: object) {\n return this.content(JSON_MIME).body(JSON.stringify(jsObject))\n }\n /**\n * Converts the javascript object to a FormData and sets the request body.\n * @param formObject An object which will be converted to a FormData\n * @param recursive If `true`, will recurse through all nested objects\n * Can be set as an array of string to exclude specific keys.\n * See https://github.com/elbywan/wretch/issues/68 for more details.\n */\n formData(formObject: object, recursive: string[] | boolean = false) {\n return this.body(convertFormData(formObject, recursive))\n }\n /**\n * Converts the input to an url encoded string and sets the content-type header and body.\n * If the input argument is already a string, skips the conversion part.\n *\n * @param input An object to convert into an url encoded string or an already encoded string\n */\n formUrl(input: (object | string)) {\n return this\n .body(typeof input === \"string\" ? input : convertFormUrl(input))\n .content(\"application/x-www-form-urlencoded\")\n }\n}\n\n// Internal helpers\n\nconst appendQueryParams = (url: string, qp: object | string, replace: boolean) => {\n let queryString\n\n if(typeof qp === \"string\") {\n queryString = qp\n } else {\n const usp = conf.polyfill(\"URLSearchParams\", { instance: true })\n for(const key in qp) {\n if(qp[key] instanceof Array) {\n for(const val of qp[key])\n usp.append(key, val)\n } else {\n usp.append(key, qp[key])\n }\n }\n queryString = usp.toString()\n }\n\n const split = url.split(\"?\")\n if(replace || split.length < 2)\n return split[0] + \"?\" + queryString\n\n return url + \"&\" + queryString\n}\n\nfunction convertFormData(\n formObject: object,\n recursive: string[] | boolean = false,\n formData = conf.polyfill(\"FormData\", { instance: true }),\n ancestors = []\n) {\n Object.entries(formObject).forEach(([key, value]) => {\n let formKey = ancestors.reduce((acc, ancestor) => (\n acc ? `${acc}[${ancestor}]` : ancestor\n ), null)\n formKey = formKey ? `${formKey}[${key}]` : key\n if(value instanceof Array) {\n for(const item of value)\n formData.append(formKey + \"[]\", item)\n } else if(\n recursive &&\n typeof value === \"object\" &&\n (\n !(recursive instanceof Array) ||\n !recursive.includes(key)\n )\n ) {\n if(value !== null) {\n convertFormData(value, recursive, formData, [...ancestors, key])\n }\n } else {\n formData.append(formKey, value)\n }\n })\n\n return formData\n}\n\nfunction encodeQueryValue(key: string, value: unknown) {\n return encodeURIComponent(key) +\n \"=\" +\n encodeURIComponent(\n typeof value === \"object\" ?\n JSON.stringify(value) :\n \"\" + value\n )\n}\nfunction convertFormUrl(formObject: object) {\n return Object.keys(formObject)\n .map(key => {\n const value = formObject[key]\n if(value instanceof Array) {\n return value.map(v => encodeQueryValue(key, v)).join(\"&\")\n }\n return encodeQueryValue(key, value)\n })\n .join(\"&\")\n}\n"]} \ No newline at end of file diff --git a/src/wretcher.ts b/src/wretcher.ts index cf4cbed..894a3f9 100644 --- a/src/wretcher.ts +++ b/src/wretcher.ts @@ -9,6 +9,9 @@ export type WretcherOptions = RequestInit & { export type DeferredCallback = (wretcher: Wretcher, url: string, options: WretcherOptions) => Wretcher +const JSON_MIME = "application/json" +const CONTENT_TYPE_HEADER = "Content-Type" + /** * The Wretcher class used to perform easy fetch requests. * @@ -133,7 +136,7 @@ export class Wretcher { * @param headerValue Header value */ content(headerValue: string) { - return this.headers({ "Content-Type" : headerValue }) + return this.headers({ [CONTENT_TYPE_HEADER] : headerValue }) } /** @@ -189,10 +192,17 @@ export class Wretcher { }) } - private method(method, options = {}, body = null) { + private method(method : string, options = {}, body = null) { + const headers = this._options.headers let baseWretcher = !body ? this : - typeof body === "object" ? this.json(body) : + typeof body === "object" && ( + !headers || + Object.entries(headers).every(([k, v]) => + k.toLowerCase() !== CONTENT_TYPE_HEADER.toLowerCase() || + v === JSON_MIME + ) + ) ? this.json(body) : this.body(body) baseWretcher = baseWretcher.options({ ...options, method }) const deferredWretcher = baseWretcher._deferredChain.reduce((acc: Wretcher, curr) => curr(acc, acc._url, acc._options), baseWretcher) @@ -202,49 +212,49 @@ export class Wretcher { /** * Performs a get request. */ - get(options?) { + get(options? : WretcherOptions) { return this.method("GET", options) } /** * Performs a delete request. */ - delete(options?) { + delete(options? : WretcherOptions) { return this.method("DELETE", options) } /** * Performs a put request. */ - put(body?, options?) { + put(body? : any, options? : WretcherOptions) { return this.method("PUT", options, body) } /** * Performs a post request. */ - post(body?, options?) { + post(body? : any, options? : WretcherOptions) { return this.method("POST", options, body) } /** * Performs a patch request. */ - patch(body?, options?) { + patch(body? : any, options? : WretcherOptions) { return this.method("PATCH", options, body) } /** * Performs a head request. */ - head(options?) { + head(options? : WretcherOptions) { return this.method("HEAD", options) } /** * Performs an options request */ - opts(options?) { + opts(options? : WretcherOptions) { return this.method("OPTIONS", options) } /** * Replay a request. */ - replay(options?) { + replay(options? : WretcherOptions) { return this.method(this._options.method, options) } @@ -260,7 +270,7 @@ export class Wretcher { * @param jsObject An object which will be serialized into a JSON */ json(jsObject: object) { - return this.content("application/json").body(JSON.stringify(jsObject)) + return this.content(JSON_MIME).body(JSON.stringify(jsObject)) } /** * Converts the javascript object to a FormData and sets the request body. diff --git a/test/browser/spec/index.js b/test/browser/spec/index.js index 92fbc05..cbb8cee 100644 --- a/test/browser/spec/index.js +++ b/test/browser/spec/index.js @@ -81,6 +81,14 @@ describe("Wretch", function() { expect(roundTrip).toBe(reference) roundTrip = await wretch(`${_URL}/urlencoded/roundTrip`).formUrl(jsonObject).post().text() expect(roundTrip).toEqual(reference) + // Ensure that calling .json with the shorthand works + const roundTrip3 = await wretch(`${_URL}/json/roundTrip`).json({}).post(jsonObject).json() + expect(roundTrip3).toEqual(jsonObject) + // Ensure that it preserves any content type set previously + try { + await wretch(`${_URL}/json/roundTrip`).content("bad/content").post(jsonObject).json() + fail("should have thrown") + } catch(e) {} }) it("should send a FormData object", async function() { diff --git a/test/node/wretch.spec.ts b/test/node/wretch.spec.ts index e53513d..fa201ac 100644 --- a/test/node/wretch.spec.ts +++ b/test/node/wretch.spec.ts @@ -49,7 +49,7 @@ describe("Wretch", function () { expect(() => wretch("...").query({ a: 1, b: 2 })).toThrow("URLSearchParams is not defined") expect(() => wretch("...").formData({ a: 1, b: 2 })).toThrow("FormData is not defined") - expect(() => wretch("...").get("...")).toThrow("fetch is not defined") + expect(() => wretch("...").get()).toThrow("fetch is not defined") wretch().polyfills({ fetch: fetchPolyfill(), @@ -120,6 +120,14 @@ describe("Wretch", function () { // Using shorthand const roundTrip2 = await wretch(`${_URL}/json/roundTrip`).post(jsonObject).json() expect(roundTrip2).toEqual(jsonObject) + // Ensure that calling .json with the shorthand works + const roundTrip3 = await wretch(`${_URL}/json/roundTrip`).json({}).post(jsonObject).json() + expect(roundTrip3).toEqual(jsonObject) + // Ensure that it preserves any content type set previously + try { + await wretch(`${_URL}/json/roundTrip`).content("bad/content").post(jsonObject).json() + fail("should have thrown") + } catch(e) {} }) it("should perform an url encoded form data round trip", async function () {