Support passing relative path for URL
frederikhors opened this issue · comments
I just found out another quirk this time with 7.0.0-next.33
.
But this time only when I build my bundle for production:
TypeError: Failed to construct 'URL': Invalid URL
at index.pxZNWVDZ.js:51:1995
at ce (index.pxZNWVDZ.js:51:823)
at Zi.request (index.pxZNWVDZ.js:51:4018)
at utils.CoYeZH7t.js:1:932
at Object.persister (helpers.Bc0QlLkm.js:1:25762)
An extract of index.pxZNWVDZ.js:51:1995
(let l=new URL(n.url)
is the stack trace indication):
}`)}function S(e,n,i=""){return n!=null&&n!==""?e+n+i:""}function z(e){return S(" ",e.replace(/\n/g,`
`))}function je(e){var n;return(n=e==null?void 0:e.some(i=>i.includes(`
`)))!==null&&n!==void 0?n:!1}const $i=e=>{var t;let n;const i=e.definitions.filter(Je);return i.length===1&&(n=(t=i[0].name)==null?void 0:t.value),n},Qi=e=>{let n=!1;const i=e.definitions.filter(Je);return i.length===1&&(n=i[0].operation===fe.MUTATION),n},ue=(e,n)=>{const i=typeof e=="string"?e:wi(e);let t=!1,a;if(n)return{expression:i,isMutation:t,operationName:a};const d=En(()=>typeof e=="string"?hi(e):e);return d instanceof Error?{expression:i,isMutation:t,operationName:a}:(a=$i(d),t=Qi(d),{expression:i,operationName:a,isMutation:t})},Oe=JSON,ce=async e=>{const n={...e,method:e.request._tag==="Single"?e.request.document.isMutation?"POST":Re(e.method??"post"):e.request.hasMutations?"POST":Re(e.method??"post"),fetchOptions:{...e.fetchOptions,errorPolicy:e.fetchOptions.errorPolicy??"none"}},t=await Ji(n.method)(n);if(!t.ok)return new M({status:t.status,headers:t.headers},{query:e.request._tag==="Single"?e.request.document.expression:e.request.query,variables:e.request.variables});const a=await Wi(t,e.fetchOptions.jsonSerializer??Oe);if(a instanceof Error)throw a;const d={status:t.status,headers:t.headers};if(_n(a)&&n.fetchOptions.errorPolicy==="none"){const l=a._tag==="Batch"?{...a.executionResults,...d}:{...a.executionResult,...d};return new M(l,{query:e.request._tag==="Single"?e.request.document.expression:e.request.query,variables:e.request.variables})}if(a._tag==="Single")return{...d,...Ge(n)(a.executionResult)};if(a._tag==="Batch")return{...d,data:a.executionResults.map(Ge(n))}},Ge=e=>n=>({extensions:n.extensions,data:n.data,errors:e.fetchOptions.errorPolicy==="all"?n.errors:void 0}),Wi=async(e,n)=>{const i=e.headers.get(ve),t=await e.text();return i&&On(i)?Me(n.parse(t)):Me(t)},Ji=e=>async n=>{const i=new Headers(n.headers);let t=null,a;i.has(Ye)||i.set(Ye,[We,pe].join(", ")),e==="POST"?(a=(n.fetchOptions.jsonSerializer??Oe).stringify(Xi(n)),typeof a=="string"&&!i.has(ve)&&i.set(ve,pe)):t=zi(n);const d={method:e,headers:i,body:a,...n.fetchOptions};let l=new URL(n.url),k=d;if(n.middleware){const r=await Promise.resolve(n.middleware({...d,url:n.url,operationName:n.request._tag==="Single"?n.request.document.operationName:void 0,variables:n.request.variables})),{url:u,...c}=r;l=new URL(u),k=c}return t&&t.forEach((r,u)=>{l.searchParams.append(u,r)}),await(n.fetch??fetch)(l,k)},Xi=e=>{if(e.request._tag==="Single"){const{variables:n,document:{expression:i,operationName:t}}=e.request;return{query:i,variables:n,operationName:t}}else{if(e.request._tag==="Batch")return $e(e.request.query,e.request.variables??[]).map(([n,i])=>({query:n,variables:i}));throw Qe(e.request)}},zi=e=>{var t;const n=e.fetchOptions.jsonSerializer??Oe,i=new URLSearchParams;if(e.request._tag==="Single")return i.append("query",xe(e.request.document.expression)),e.request.variables&&i.append("variables",n.stringify(e.request.variables)),e.request.document.operationName&&i.append("operationName",e.request.document.operationName),i;if(e.request._tag==="Batch"){const a=((t=e.request.variables)==null?void 0:t.map(k=>n.stringify(k)))??[],d=e.request.query.map(xe),l=$e(d,a).map(([k,s])=>({query:k,variables:s}));i.append("query",n.stringify(l))}else throw Qe(e.request);return i};class Zi{constructor(n,i={}){this.url=n,this.requestConfig=i,this.rawRequest=async(...t)=>{const[a,d,l]=t,k=gn(a,d,l),{headers:s,fetch:r=globalThis.fetch,method:u="POST",requestMiddleware:c,responseMiddleware:N,excludeOperationName:A,...F}=this.requestConfig,{url:y}=this;k.signal!==void 0&&(F.signal=k.signal);const K=ue(k.query,A),f=await ce({url:y,request:{_tag:"Single",document:K,variables:k.variables},headers:{...Y(oe(s)),...Y(k.requestHeaders)},fetch:r,method:u,fetchOptions:F,middleware:c});if(N&&N(f),f instanceof Error)throw f;return f}}async request(n,...i){const[t,a]=i,d=ea(n,t,a),{headers:l,fetch:k=globalThis.fetch,method:s="POST",requestMiddleware:r,
If it only happens after you bundle then I think it's an issue in your project. What is the value of n.url
? And, what is supplying the global URL
?
Is the same URL I use with version v7.0.0-next.12
.
graphql-request version is the only thing I change.
It might be a breaking change in graphql-request
rather than a bug.
Does your target runtime (browser?) have a global URL
class? What is the URL value? Have you manually run that value through the global URL
class constructor?
browser?
Yes
Does your target runtime have a global
URL
class?
Nope, all default.
I'm using it like this with both versions:
export const client = new GraphQLClient("/graphql", {
fetch: createPersistedQueryFetch(fetch) // from from https://github.com/jasonkuhrt/graphql-request/issues/269
});
Interesting, /graphql
is not a valid URL. You are relying on the browser supplying the current host URL prefix. This approach is only valid in browsers. I'm not sure this feature should be supported, but I'll consider it. Let me know what you think for your use-case.
It works if I use window.location.origin
since I'm using it in browser only.
I think being explicit here is less confusing and makes for a better API, because we can validate that a valid URL is passed catching more user errors.
Upon release, I'll try to remember to mention this breaking change!