Skip to content
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

Support passing relative path for URL #745

Closed
frederikhors opened this issue Mar 31, 2024 · 7 comments
Closed

Support passing relative path for URL #745

frederikhors opened this issue Mar 31, 2024 · 7 comments

Comments

@frederikhors
Copy link

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,
@jasonkuhrt
Copy link
Member

jasonkuhrt commented Mar 31, 2024

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?

@frederikhors
Copy link
Author

Is the same URL I use with version v7.0.0-next.12.

graphql-request version is the only thing I change.

@jasonkuhrt
Copy link
Member

jasonkuhrt commented Mar 31, 2024

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?

@frederikhors
Copy link
Author

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
});

@jasonkuhrt
Copy link
Member

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.

@jasonkuhrt jasonkuhrt changed the title Failed to construct 'URL': Invalid URL error when building for production Support passing relative path for URL Apr 2, 2024
@frederikhors
Copy link
Author

It works if I use window.location.origin since I'm using it in browser only.

@jasonkuhrt
Copy link
Member

jasonkuhrt commented Apr 2, 2024

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants