From 6a560585493ca49d5d56133503db84cc31b3380d Mon Sep 17 00:00:00 2001 From: Cobey Potter Date: Tue, 6 Aug 2024 00:58:13 -0400 Subject: [PATCH] add in full cause to thrown errors removes auth_token from reporting --- examples/hooks.html | 4 ++-- lib/useButter.js | 40 ++++++++++++++++++++++++++++++++++------ tests/basic.html | 8 ++++---- tests/hooks.html | 4 ++-- tests/lib/butter.min.js | 2 +- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/examples/hooks.html b/examples/hooks.html index 69c60fa..5b38f5a 100644 --- a/examples/hooks.html +++ b/examples/hooks.html @@ -58,7 +58,7 @@ } ) .catch( - (error) => console.error("post: ", error) + (error) => console.error("post: ", err.message, err.cause) ); @@ -67,7 +67,7 @@ (res) => console.log(res) ) .catch( - (error) => console.error("page: ", error) + (error) => console.error("page: ", err.message, err.cause) ) }); diff --git a/lib/useButter.js b/lib/useButter.js index db308dd..4ecf50e 100644 --- a/lib/useButter.js +++ b/lib/useButter.js @@ -123,18 +123,38 @@ export default function useButter(type, butterConfig) { detail: errorDetail } = await errorPayload.response.json(); + const mappedParams = Object.fromEntries( + Object.entries(errorPayload.params) + .filter(([key]) => key !== 'auth_token') + ) + + const url = new URL(errorPayload.response.url) + + // Remove auth_token from URL search params + url.searchParams.delete('auth_token'); + + const cause = { + data: errorDetail, + headers: errorPayload.response.headers, + status: errorPayload.response.status, + statusText: errorPayload.response.statusText, + config: errorPayload.config, + params: mappedParams, + type, + url + } + useOnError( errorDetail, - { - config: errorPayload.config, - params: errorPayload.params, - type - } + cause ); return Promise.reject( new Error( - errorDetail + `${ errorDetail } (${ errorPayload.response.status })`, + { + cause + } ) ); } else { @@ -154,6 +174,14 @@ export default function useButter(type, butterConfig) { cleanup(); + console.error( + "reportableError", + reportableError, + new Error( + reportableError + ) + ) + return Promise.reject( new Error( reportableError diff --git a/tests/basic.html b/tests/basic.html index 1d03e38..664c7df 100644 --- a/tests/basic.html +++ b/tests/basic.html @@ -43,11 +43,11 @@ // add the catch to ensure you do not receive a "uncaught (in promise) warning" .catch( (err) => { - console.error(err) + console.error(err.message, err.cause) } ); - butter.content.cancelRequest() + // butter.content.cancelRequest() butter.post.list({ page: 1, @@ -80,11 +80,11 @@ // add the catch to ensure you do not receive a "uncaught (in promise) warning" .catch( (err) => { - console.error(err) + console.error(err.message, err.cause) } ); - butter.post.cancelRequest() + //butter.post.cancelRequest() }); diff --git a/tests/hooks.html b/tests/hooks.html index ac8b839..648fa3e 100644 --- a/tests/hooks.html +++ b/tests/hooks.html @@ -58,7 +58,7 @@ } ) .catch( - (error) => console.error("post: ", error) + (error) => console.error("post: ", err.message, err.cause) ); @@ -67,7 +67,7 @@ (res) => console.log(res) ) .catch( - (error) => console.error("page: ", error) + (error) => console.error("page: ", err.message, err.cause) ) }); diff --git a/tests/lib/butter.min.js b/tests/lib/butter.min.js index e8f3cd4..f123da8 100644 --- a/tests/lib/butter.min.js +++ b/tests/lib/butter.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Butter=t():e.Butter=t()}(this,()=>(()=>{"use strict";var n={d:(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},e={};n.d(e,{default:()=>function(e,t={}){if(e)return this instanceof r?r:new r(e,t);throw"ButterCMS API token not set"}});const C="2.0.0",o={author:"authors",category:"categories",content:"content",feed:"feeds",page:"pages",post:"posts",tag:"tags"};function P(e,t){const{onError:r,onRequest:n,onResponse:o,...s}=t.config,{auth_token:a,test:c,preview:i,...u}=t.params;r&&r(e,{options:s,params:u,type:t.type})}function T(e,t,r){t={auth_token:t};return r.testMode&&(t.test=1,t.preview=1),{...e,...t}}function s(R,v){t=R;const y=`https://api.buttercms.com/v2/${o[t]}/`,e=R.replace(R[0],R[0].toUpperCase()),{applyRequestUrlForErrorMessages:q,cancelRequest:w,cleanup:E,determineFetchError:b,signal:j}=function(t){let o=new AbortController,r="";function s(e){return r+": "+e}function a(){o=null}return{applyRequestUrlForErrorMessages:function(e){r=t+` (${e})`},cancelRequest:async function(){await o.abort(s("Request cancelled"))},cleanup:a,controller:o,determineFetchError:function(e,t){var r=o&&o.signal.reason&&o.signal.aborted,n="TimeoutError"===e.name;return r?o.signal.reason:n?s(`Request timed out after ${t}ms.`):(a(),e)},signal:o.signal}}(e);var t;async function r(e=y,t={}){const{apiToken:r,...n}=v,o=new Headers({"Content-Type":"application/json","X-Butter-Client":"JS/"+C});"undefined"==typeof window&&o.append("Accept-Encoding","gzip"),q(e);var{config:t,headers:s,params:a}=await async function(e,t,r){const{onError:n,onRequest:o,onResponse:s,...a}=r.config;var c,i;return o?({headers:e,options:c,params:i}=await o(e,{cancelRequest:r.cancelRequest,headers:r.headers,options:a,params:r.params,type:r.type}),{config:{...c,onError:n,onRequest:o,onResponse:s},headers:e,params:T(i,t,c)}):{...r,params:T(r.params,t,a)}}(e,r,{cancelRequest:w,config:n,headers:o,params:t,type:R});try{const v=AbortSignal.timeout(t.timeout),C=await fetch(e+"?"+new URLSearchParams(a),{cache:t.cache,method:"GET",headers:s,signal:AbortSignal.any([j,v])});if(E(),200!==C.status)throw{response:C,config:t,params:a};{var c=C;var i={config:t,params:a,type:R,requestHeaders:o};const{onError:u,onRequest:p,onResponse:l,...f}=i.config,{auth_token:d,test:m,preview:g,...h}=i.params;if(l){const u=c.clone();await l(u,{options:f,params:h,type:i.type})}return await{data:await c.json(),headers:Object.fromEntries(c.headers.entries()),status:c.status,statusText:c.statusText,config:{url:c.url,method:"get",headers:Object.fromEntries(i.requestHeaders.entries()),transformRequest:p?[p]:[],transformResponse:l?[l]:[],timeout:i.config.timeout}};return await void 0}}catch(e){if(e.response){const C=(await e.response.json())["detail"];return P(C,{config:e.config,params:e.params,type:R}),Promise.reject(new Error(C))}{const C=b(e,t.timeout);return P(C,{config:t,params:a,type:R}),E(),Promise.reject(new Error(C))}}}return{cancelRequest:w,list:async function(e={}){return r(y,e)},retrieve:async function(e,t){return r(y+e+"/",t)},search:async function(e="",t={}){return t.query=e,r(y+"search/",t)}}}const u={Author:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=s("author",e);return{cancelRequest:e,list:t,retrieve:r}},Category:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=s("category",e);return{cancelRequest:e,list:t,retrieve:r}},Content:function(e={}){var{cancelRequest:e,retrieve:t}=s("content",e);return{cancelRequest:e,retrieve:t}},Feed:function(e={}){var{cancelRequest:e,retrieve:t}=s("feed",e);return{cancelRequest:e,retrieve:t}},Page:function(e={}){const{cancelRequest:t,retrieve:n,search:r}=s("page",e);return{cancelRequest:t,list:async(e,t)=>n(e,t),retrieve:async(e,t,r)=>n(e+"/"+t,r),search:r}},Post:function(e={}){var{cancelRequest:e,list:t,retrieve:r,search:n}=s("post",e);return{cancelRequest:e,list:t,retrieve:r,search:n}},Tag:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=s("tag",e);return{cancelRequest:e,list:t,retrieve:r}}};function r(e,t){var r,n,{cache:t="default",onError:o=null,onRequest:s=null,onResponse:a=null,testMode:c=!1,timeout:i=3e3}=t;return{version:C,...(r=u,n={apiToken:e,cache:t,onError:o,onRequest:s,onResponse:a,testMode:c,timeout:i},Object.keys(r).reduce((e,t)=>({...e,[t.toLocaleLowerCase()]:r[t](n)}),{}))}}return e.default})()); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Butter=t():e.Butter=t()}(this,()=>(()=>{"use strict";var n={d:(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},e={};n.d(e,{default:()=>function(e,t={}){if(e)return this instanceof r?r:new r(e,t);throw"ButterCMS API token not set"}});const T="2.0.0",s={author:"authors",category:"categories",content:"content",feed:"feeds",page:"pages",post:"posts",tag:"tags"};function k(e,t){const{onError:r,onRequest:n,onResponse:s,...o}=t.config,{auth_token:a,test:c,preview:i,...u}=t.params;r&&r(e,{options:o,params:u,type:t.type})}function P(e,t,r){t={auth_token:t};return r.testMode&&(t.test=1,t.preview=1),{...e,...t}}function o(R,v){t=R;const y=`https://api.buttercms.com/v2/${s[t]}/`,e=R.replace(R[0],R[0].toUpperCase()),{applyRequestUrlForErrorMessages:q,cancelRequest:w,cleanup:E,determineFetchError:b,signal:j}=function(t){let s=new AbortController,r="";function o(e){return r+": "+e}function a(){s=null}return{applyRequestUrlForErrorMessages:function(e){r=t+` (${e})`},cancelRequest:async function(){await s.abort(o("Request cancelled"))},cleanup:a,controller:s,determineFetchError:function(e,t){var r=s&&s.signal.reason&&s.signal.aborted,n="TimeoutError"===e.name;return r?s.signal.reason:n?o(`Request timed out after ${t}ms.`):(a(),e)},signal:s.signal}}(e);var t;async function r(t=y,r={}){const{apiToken:e,...n}=v,s=new Headers({"Content-Type":"application/json","X-Butter-Client":"JS/"+T});"undefined"==typeof window&&s.append("Accept-Encoding","gzip"),q(t);var{config:r,headers:o,params:a}=await async function(e,t,r){const{onError:n,onRequest:s,onResponse:o,...a}=r.config;var c,i;return s?({headers:e,options:c,params:i}=await s(e,{cancelRequest:r.cancelRequest,headers:r.headers,options:a,params:r.params,type:r.type}),{config:{...c,onError:n,onRequest:s,onResponse:o},headers:e,params:P(i,t,c)}):{...r,params:P(r.params,t,a)}}(t,e,{cancelRequest:w,config:n,headers:s,params:r,type:R});try{const v=AbortSignal.timeout(r.timeout),T=await fetch(t+"?"+new URLSearchParams(a),{cache:r.cache,method:"GET",headers:o,signal:AbortSignal.any([j,v])});if(E(),200!==T.status)throw{response:T,config:r,params:a};{var c=T;var i={config:r,params:a,type:R,requestHeaders:s};const{onError:u,onRequest:p,onResponse:l,...f}=i.config,{auth_token:d,test:m,preview:h,...g}=i.params;if(l){const u=c.clone();await l(u,{options:f,params:g,type:i.type})}return await{data:await c.json(),headers:Object.fromEntries(c.headers.entries()),status:c.status,statusText:c.statusText,config:{url:c.url,method:"get",headers:Object.fromEntries(i.requestHeaders.entries()),transformRequest:p?[p]:[],transformResponse:l?[l]:[],timeout:i.config.timeout}};return await void 0}}catch(e){if(e.response){const T=(await e.response.json())["detail"];for(const[R,T]of e.response.headers.entries())console.log(R+": "+T);const t=Object.fromEntries(Object.entries(e.params).filter(([e])=>"auth_token"!==e)),P=new URL(e.response.url),y=(P.searchParams.delete("auth_token"),{data:T,headers:e.response.headers,status:e.response.status,statusText:e.response.statusText,config:e.config,params:t,type:R,url:P});return k(T,y),Promise.reject(new Error(`${T} (${e.response.status})`,{cause:y}))}{const T=b(e,r.timeout);return k(T,{config:r,params:a,type:R}),E(),console.error("reportableError",T,new Error(T)),Promise.reject(new Error(T))}}}return{cancelRequest:w,list:async function(e={}){return r(y,e)},retrieve:async function(e,t){return r(""+y+e+"/",t)},search:async function(e="",t={}){return t.query=e,r(y+"search/",t)}}}const u={Author:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=o("author",e);return{cancelRequest:e,list:t,retrieve:r}},Category:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=o("category",e);return{cancelRequest:e,list:t,retrieve:r}},Content:function(e={}){var{cancelRequest:e,retrieve:t}=o("content",e);return{cancelRequest:e,retrieve:t}},Feed:function(e={}){var{cancelRequest:e,retrieve:t}=o("feed",e);return{cancelRequest:e,retrieve:t}},Page:function(e={}){const{cancelRequest:t,retrieve:n,search:r}=o("page",e);return{cancelRequest:t,list:async(e,t)=>n(e,t),retrieve:async(e,t,r)=>n(e+"/"+t,r),search:r}},Post:function(e={}){var{cancelRequest:e,list:t,retrieve:r,search:n}=o("post",e);return{cancelRequest:e,list:t,retrieve:r,search:n}},Tag:function(e={}){var{cancelRequest:e,list:t,retrieve:r}=o("tag",e);return{cancelRequest:e,list:t,retrieve:r}}};function r(e,t){var r,n,{cache:t="default",onError:s=null,onRequest:o=null,onResponse:a=null,testMode:c=!1,timeout:i=3e3}=t;return{version:T,...(r=u,n={apiToken:e,cache:t,onError:s,onRequest:o,onResponse:a,testMode:c,timeout:i},Object.keys(r).reduce((e,t)=>({...e,[t.toLocaleLowerCase()]:r[t](n)}),{}))}}return e.default})()); \ No newline at end of file