-
-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: handle nested values in formDataBodySerializer #1609
base: main
Are you sure you want to change the base?
Conversation
Run & review this pull request in StackBlitz Codeflow. |
🦋 Changeset detectedLatest commit: c7ceb67 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@@ -1,2 +1,2 @@ | |||
'use strict';var app=require('nuxt/app'),vue=require('vue');var $=async(r,t)=>{let e=typeof t=="function"?await t(r):t;if(e)return r.scheme==="bearer"?`Bearer ${e}`:r.scheme==="basic"?`Basic ${btoa(e)}`:e},P=(r,t,e)=>{typeof e=="string"||e instanceof Blob?r.append(t,e):r.append(t,JSON.stringify(e));},U=(r,t,e)=>{typeof e=="string"?r.append(t,e):r.append(t,JSON.stringify(e));},L={bodySerializer:r=>{let t=new FormData;return Object.entries(r).forEach(([e,s])=>{s!=null&&(Array.isArray(s)?s.forEach(o=>P(t,e,o)):P(t,e,s));}),t}},R={bodySerializer:r=>JSON.stringify(r)},H={bodySerializer:r=>{let t=new URLSearchParams;return Object.entries(r).forEach(([e,s])=>{s!=null&&(Array.isArray(s)?s.forEach(o=>U(t,e,o)):U(t,e,s));}),t}},D=r=>{switch(r){case "label":return ".";case "matrix":return ";";case "simple":return ",";default:return "&"}},N=r=>{switch(r){case "form":return ",";case "pipeDelimited":return "|";case "spaceDelimited":return "%20";default:return ","}},I=r=>{switch(r){case "label":return ".";case "matrix":return ";";case "simple":return ",";default:return "&"}},S=({allowReserved:r,explode:t,name:e,style:s,value:o})=>{if(!t){let n=(r?o:o.map(u=>encodeURIComponent(u))).join(N(s));switch(s){case "label":return `.${n}`;case "matrix":return `;${e}=${n}`;case "simple":return n;default:return `${e}=${n}`}}let a=D(s),i=o.map(n=>s==="label"||s==="simple"?r?n:encodeURIComponent(n):y({allowReserved:r,name:e,value:n})).join(a);return s==="label"||s==="matrix"?a+i:i},y=({allowReserved:r,name:t,value:e})=>{if(e==null)return "";if(typeof e=="object")throw new Error("Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these.");return `${t}=${r?e:encodeURIComponent(e)}`},A=({allowReserved:r,explode:t,name:e,style:s,value:o})=>{if(o instanceof Date)return `${e}=${o.toISOString()}`;if(s!=="deepObject"&&!t){let n=[];Object.entries(o).forEach(([l,p])=>{n=[...n,l,r?p:encodeURIComponent(p)];});let u=n.join(",");switch(s){case "form":return `${e}=${u}`;case "label":return `.${u}`;case "matrix":return `;${e}=${u}`;default:return u}}let a=I(s),i=Object.entries(o).map(([n,u])=>y({allowReserved:r,name:s==="deepObject"?`${e}[${n}]`:n,value:u})).join(a);return s==="label"||s==="matrix"?a+i:i};var Q=/\{[^{}]+\}/g,V=({path:r,url:t})=>{let e=t,s=t.match(Q);if(s)for(let o of s){let a=false,i=o.substring(1,o.length-1),n="simple";i.endsWith("*")&&(a=true,i=i.substring(0,i.length-1)),i.startsWith(".")?(i=i.substring(1),n="label"):i.startsWith(";")&&(i=i.substring(1),n="matrix");let u=vue.toValue(vue.toValue(r)[i]);if(u==null)continue;if(Array.isArray(u)){e=e.replace(o,S({explode:a,name:i,style:n,value:u}));continue}if(typeof u=="object"){e=e.replace(o,A({explode:a,name:i,style:n,value:u}));continue}if(n==="matrix"){e=e.replace(o,`;${y({name:i,value:u})}`);continue}let l=encodeURIComponent(n==="label"?`.${u}`:u);e=e.replace(o,l);}return e},E=({allowReserved:r,array:t,object:e}={})=>o=>{let a=[],i=vue.toValue(o);if(i&&typeof i=="object")for(let n in i){let u=vue.toValue(i[n]);if(u!=null){if(Array.isArray(u)){a=[...a,S({allowReserved:r,explode:true,name:n,style:"form",value:u,...t})];continue}if(typeof u=="object"){a=[...a,A({allowReserved:r,explode:true,name:n,style:"deepObject",value:u,...e})];continue}a=[...a,y({allowReserved:r,name:n,value:u})];}}return a.join("&")},k=async({security:r,...t})=>{for(let e of r){let s=await $(e,t.auth);if(!s)continue;let o=e.name??"Authorization";switch(e.in){case "query":t.query||(t.query={}),vue.toValue(t.query)[o]=s;break;case "header":default:t.headers.set(o,s);break}return}},d=r=>F({baseUrl:r.baseURL??"",path:r.path,query:r.query,querySerializer:typeof r.querySerializer=="function"?r.querySerializer:E(r.querySerializer),url:r.url}),F=({baseUrl:r,path:t,query:e,querySerializer:s,url:o})=>{let a=o.startsWith("/")?o:`/${o}`,i=r+a;t&&(i=V({path:t,url:i}));let n=e?s(e):"";return n.startsWith("?")&&(n=n.substring(1)),n&&(i+=`?${n}`),i},C=(r,t)=>{let e={...r,...t};return e.baseURL?.endsWith("/")&&(e.baseURL=e.baseURL.substring(0,e.baseURL.length-1)),e.headers=T(r.headers,t.headers),e},T=(...r)=>{let t=new Headers;for(let e of r){if(!e||typeof e!="object")continue;let s=e;vue.isRef(s)&&(s=vue.unref(s));let o=s instanceof Headers?s.entries():Object.entries(s);for(let[a,i]of o)if(i===null)t.delete(a);else if(Array.isArray(i))for(let n of i)t.append(a,f(n));else if(i!==undefined){let n=f(i);t.set(a,typeof n=="object"?JSON.stringify(n):n);}}return t},w=(...r)=>r.reduce((t,e)=>{if(typeof e=="function")t.push(e);else if(Array.isArray(e))return t.concat(e);return t},[]),W=E({allowReserved:false,array:{explode:true,style:"form"},object:{explode:true,style:"deepObject"}}),J={"Content-Type":"application/json"},q=(r={})=>({...R,baseURL:"",headers:J,querySerializer:W,...r}),f=r=>{if(r===null||typeof r!="object"||r instanceof Headers)return vue.isRef(r)?vue.unref(r):r;if(Array.isArray(r))return r.map(e=>f(e));if(vue.isRef(r))return f(vue.unref(r));let t={};for(let e in r)t[e]=f(r[e]);return t};var re=(r={})=>{let t=C(q(),r),e=()=>({...t}),s=a=>(t=C(t,a),e()),o=({asyncDataOptions:a,composable:i,key:n,...u})=>{let l={...t,...u,$fetch:u.$fetch??t.$fetch??$fetch,headers:T(t.headers,u.headers),onRequest:w(t.onRequest,u.onRequest),onResponse:w(t.onResponse,u.onResponse)},{responseTransformer:p,responseValidator:g,security:j}=l;j&&(l.onRequest=[async({options:c})=>{await k({auth:l.auth,headers:c.headers,query:c.query,security:j});},...l.onRequest]),(p||g)&&(l.onResponse=[...l.onResponse,async({options:c,response:b})=>{c.responseType&&c.responseType!=="json"||(g&&await g(b._data),p&&(b._data=await p(b._data)));}]),l.body&&l.bodySerializer&&(l.body=l.bodySerializer(f(l.body))),l.body||l.headers.delete("Content-Type");let O=l.$fetch;if(i==="$fetch"){let c=d(l);return O(c,f(l))}if(i==="useFetch"){let c=d(l);return app.useFetch(c,l)}if(i==="useLazyFetch"){let c=d(l);return app.useLazyFetch(c,l)}let h=()=>{let c=d(l);return O(c,f(l))};if(i==="useAsyncData")return n?app.useAsyncData(n,h,a):app.useAsyncData(h,a);if(i==="useLazyAsyncData")return n?app.useLazyAsyncData(n,h,a):app.useLazyAsyncData(h,a)};return {buildUrl:d,connect:a=>o({...a,method:"CONNECT"}),delete:a=>o({...a,method:"DELETE"}),get:a=>o({...a,method:"GET"}),getConfig:e,head:a=>o({...a,method:"HEAD"}),options:a=>o({...a,method:"OPTIONS"}),patch:a=>o({...a,method:"PATCH"}),post:a=>o({...a,method:"POST"}),put:a=>o({...a,method:"PUT"}),request:o,setConfig:s,trace:a=>o({...a,method:"TRACE"})}};exports.createClient=re;exports.createConfig=q;exports.formDataBodySerializer=L;exports.jsonBodySerializer=R;exports.urlSearchParamsBodySerializer=H;//# sourceMappingURL=index.cjs.map | |||
'use strict';var app=require('nuxt/app'),vue=require('vue');var U=async(r,t)=>{let e=typeof t=="function"?await t(r):t;if(e)return r.scheme==="bearer"?`Bearer ${e}`:r.scheme==="basic"?`Basic ${btoa(e)}`:e},P=(r,t,e)=>{typeof e=="string"?r.append(t,e):r.append(t,JSON.stringify(e));},R=(r,t,e)=>{if(t!=null){if(typeof t=="string"||t instanceof Blob)return r.append(e??"key",t);if(typeof t!="object")return r.append(e??"key",JSON.stringify(t));if(Array.isArray(t)){t.forEach((i,a)=>{R(r,i,e?`${e}[${a}]`:`array[${a}]`);});return}for(let[i,a]of Object.entries(t))R(r,a,e?`${e}[${i}]`:i);}},L={bodySerializer:r=>{let t=new FormData;return R(t,r),t}},S={bodySerializer:r=>JSON.stringify(r)},H={bodySerializer:r=>{let t=new URLSearchParams;return Object.entries(r).forEach(([e,i])=>{i!=null&&(Array.isArray(i)?i.forEach(a=>P(t,e,a)):P(t,e,i));}),t}},D=r=>{switch(r){case "label":return ".";case "matrix":return ";";case "simple":return ",";default:return "&"}},N=r=>{switch(r){case "form":return ",";case "pipeDelimited":return "|";case "spaceDelimited":return "%20";default:return ","}},I=r=>{switch(r){case "label":return ".";case "matrix":return ";";case "simple":return ",";default:return "&"}},A=({allowReserved:r,explode:t,name:e,style:i,value:a})=>{if(!t){let s=(r?a:a.map(u=>encodeURIComponent(u))).join(N(i));switch(i){case "label":return `.${s}`;case "matrix":return `;${e}=${s}`;case "simple":return s;default:return `${e}=${s}`}}let n=D(i),o=a.map(s=>i==="label"||i==="simple"?r?s:encodeURIComponent(s):y({allowReserved:r,name:e,value:s})).join(n);return i==="label"||i==="matrix"?n+o:o},y=({allowReserved:r,name:t,value:e})=>{if(e==null)return "";if(typeof e=="object")throw new Error("Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these.");return `${t}=${r?e:encodeURIComponent(e)}`},z=({allowReserved:r,explode:t,name:e,style:i,value:a})=>{if(a instanceof Date)return `${e}=${a.toISOString()}`;if(i!=="deepObject"&&!t){let s=[];Object.entries(a).forEach(([l,p])=>{s=[...s,l,r?p:encodeURIComponent(p)];});let u=s.join(",");switch(i){case "form":return `${e}=${u}`;case "label":return `.${u}`;case "matrix":return `;${e}=${u}`;default:return u}}let n=I(i),o=Object.entries(a).map(([s,u])=>y({allowReserved:r,name:i==="deepObject"?`${e}[${s}]`:s,value:u})).join(n);return i==="label"||i==="matrix"?n+o:o};var Q=/\{[^{}]+\}/g,V=({path:r,url:t})=>{let e=t,i=t.match(Q);if(i)for(let a of i){let n=false,o=a.substring(1,a.length-1),s="simple";o.endsWith("*")&&(n=true,o=o.substring(0,o.length-1)),o.startsWith(".")?(o=o.substring(1),s="label"):o.startsWith(";")&&(o=o.substring(1),s="matrix");let u=vue.toValue(vue.toValue(r)[o]);if(u==null)continue;if(Array.isArray(u)){e=e.replace(a,A({explode:n,name:o,style:s,value:u}));continue}if(typeof u=="object"){e=e.replace(a,z({explode:n,name:o,style:s,value:u}));continue}if(s==="matrix"){e=e.replace(a,`;${y({name:o,value:u})}`);continue}let l=encodeURIComponent(s==="label"?`.${u}`:u);e=e.replace(a,l);}return e},k=({allowReserved:r,array:t,object:e}={})=>a=>{let n=[],o=vue.toValue(a);if(o&&typeof o=="object")for(let s in o){let u=vue.toValue(o[s]);if(u!=null){if(Array.isArray(u)){n=[...n,A({allowReserved:r,explode:true,name:s,style:"form",value:u,...t})];continue}if(typeof u=="object"){n=[...n,z({allowReserved:r,explode:true,name:s,style:"deepObject",value:u,...e})];continue}n=[...n,y({allowReserved:r,name:s,value:u})];}}return n.join("&")},E=async({security:r,...t})=>{for(let e of r){let i=await U(e,t.auth);if(!i)continue;let a=e.name??"Authorization";switch(e.in){case "query":t.query||(t.query={}),vue.toValue(t.query)[a]=i;break;case "header":default:t.headers.set(a,i);break}return}},d=r=>F({baseUrl:r.baseURL??"",path:r.path,query:r.query,querySerializer:typeof r.querySerializer=="function"?r.querySerializer:k(r.querySerializer),url:r.url}),F=({baseUrl:r,path:t,query:e,querySerializer:i,url:a})=>{let n=a.startsWith("/")?a:`/${a}`,o=r+n;t&&(o=V({path:t,url:o}));let s=e?i(e):"";return s.startsWith("?")&&(s=s.substring(1)),s&&(o+=`?${s}`),o},T=(r,t)=>{let e={...r,...t};return e.baseURL?.endsWith("/")&&(e.baseURL=e.baseURL.substring(0,e.baseURL.length-1)),e.headers=w(r.headers,t.headers),e},w=(...r)=>{let t=new Headers;for(let e of r){if(!e||typeof e!="object")continue;let i=e;vue.isRef(i)&&(i=vue.unref(i));let a=i instanceof Headers?i.entries():Object.entries(i);for(let[n,o]of a)if(o===null)t.delete(n);else if(Array.isArray(o))for(let s of o)t.append(n,f(s));else if(o!==undefined){let s=f(o);t.set(n,typeof s=="object"?JSON.stringify(s):s);}}return t},q=(...r)=>r.reduce((t,e)=>{if(typeof e=="function")t.push(e);else if(Array.isArray(e))return t.concat(e);return t},[]),W=k({allowReserved:false,array:{explode:true,style:"form"},object:{explode:true,style:"deepObject"}}),J={"Content-Type":"application/json"},j=(r={})=>({...S,baseURL:"",headers:J,querySerializer:W,...r}),f=r=>{if(r===null||typeof r!="object"||r instanceof Headers)return vue.isRef(r)?vue.unref(r):r;if(Array.isArray(r))return r.map(e=>f(e));if(vue.isRef(r))return f(vue.unref(r));let t={};for(let e in r)t[e]=f(r[e]);return t};var re=(r={})=>{let t=T(j(),r),e=()=>({...t}),i=n=>(t=T(t,n),e()),a=({asyncDataOptions:n,composable:o,key:s,...u})=>{let l={...t,...u,$fetch:u.$fetch??t.$fetch??$fetch,headers:w(t.headers,u.headers),onRequest:q(t.onRequest,u.onRequest),onResponse:q(t.onResponse,u.onResponse)},{responseTransformer:p,responseValidator:g,security:$}=l;$&&(l.onRequest=[async({options:c})=>{await E({auth:l.auth,headers:c.headers,query:c.query,security:$});},...l.onRequest]),(p||g)&&(l.onResponse=[...l.onResponse,async({options:c,response:b})=>{c.responseType&&c.responseType!=="json"||(g&&await g(b._data),p&&(b._data=await p(b._data)));}]),l.body&&l.bodySerializer&&(l.body=l.bodySerializer(f(l.body))),l.body||l.headers.delete("Content-Type");let O=l.$fetch;if(o==="$fetch"){let c=d(l);return O(c,f(l))}if(o==="useFetch"){let c=d(l);return app.useFetch(c,l)}if(o==="useLazyFetch"){let c=d(l);return app.useLazyFetch(c,l)}let h=()=>{let c=d(l);return O(c,f(l))};if(o==="useAsyncData")return s?app.useAsyncData(s,h,n):app.useAsyncData(h,n);if(o==="useLazyAsyncData")return s?app.useLazyAsyncData(s,h,n):app.useLazyAsyncData(h,n)};return {buildUrl:d,connect:n=>a({...n,method:"CONNECT"}),delete:n=>a({...n,method:"DELETE"}),get:n=>a({...n,method:"GET"}),getConfig:e,head:n=>a({...n,method:"HEAD"}),options:n=>a({...n,method:"OPTIONS"}),patch:n=>a({...n,method:"PATCH"}),post:n=>a({...n,method:"POST"}),put:n=>a({...n,method:"PUT"}),request:a,setConfig:i,trace:n=>a({...n,method:"TRACE"})}};exports.createClient=re;exports.createConfig=j;exports.formDataBodySerializer=L;exports.jsonBodySerializer=S;exports.urlSearchParamsBodySerializer=H;//# sourceMappingURL=index.cjs.map |
Check notice
Code scanning / CodeQL
Semicolon insertion Note test
the enclosing function
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1609 +/- ##
=======================================
Coverage 56.31% 56.31%
=======================================
Files 158 158
Lines 24818 24818
Branches 1815 1815
=======================================
Hits 13977 13977
Misses 10831 10831
Partials 10 10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
commit: |
if (typeof value === 'string' || value instanceof Blob) { | ||
data.append(key, value); | ||
} else { | ||
data.append(key, JSON.stringify(value)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to warn when stringifying a non-JSON type. I ran into issues initially when passing a FileList
to a form, expecting it to be serialized as a blob array. Instead, it came out as {}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly I think that's more on us to handle properly
Closes #1585