graphql-sse
Version:
Zero-dependency, HTTP/1 safe, simple, GraphQL over Server-Sent Events Protocol server and client
2 lines (1 loc) • 9.51 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlSse={})}(this,(function(e){"use strict";function t(e){return"object"==typeof e&&null!==e}const r="x-graphql-event-stream-token";function n(e){if("next"!==e&&"complete"!==e)throw new Error(`Invalid stream event "${e}"`);return e}function o(e,t){if(t)try{t=JSON.parse(t)}catch{throw new Error("Invalid stream data")}if("next"===e&&!t)throw new Error('Stream data must be an object for "next" events');return t||null}var a;!function(e){e[e.NewLine=10]="NewLine",e[e.CarriageReturn=13]="CarriageReturn",e[e.Space=32]="Space",e[e.Colon=58]="Colon"}(a||(a={}));class i extends Error{constructor(e){let r,n;var o;t(o=e)&&"boolean"==typeof o.ok&&"number"==typeof o.status&&"string"==typeof o.statusText?(n=e,r="Server responded with "+e.status+": "+e.statusText):r=e instanceof Error?e.message:String(e),super(r),this.name=this.constructor.name,this.response=n}}async function s(e){const{signal:t,url:r,credentials:s,headers:l,body:c,referrer:d,referrerPolicy:u,fetchFn:f,onMessage:h}=e,w={},y={};let v;try{v=await f(r,{signal:t,method:c?"POST":"GET",credentials:s,referrer:d,referrerPolicy:u,headers:{...l,accept:"text/event-stream"},body:c})}catch(e){throw new i(e)}if(!v.ok)throw new i(v);if(!v.body)throw new Error("Missing response body");let p,b=null;return(async()=>{var e;try{const t=function(){let e,t,r,i=!1,s={event:"",data:""},l=[];const c=new TextDecoder;return function(d){if(void 0===e)e=d,t=0,r=-1;else{const t=new Uint8Array(e.length+d.length);t.set(e),t.set(d,e.length),e=t}const u=e.length;let f=0;for(;t<u;){i&&(e[t]===a.NewLine&&(f=++t),i=!1);let d=-1;for(;t<u&&-1===d;++t)switch(e[t]){case a.Colon:-1===r&&(r=t-f);break;case a.CarriageReturn:i=!0;case a.NewLine:d=t}if(-1===d)break;if(f===d){if(s.event||s.data){if(!s.event)throw new Error("Missing message event");const e=n(s.event),t=o(e,s.data);l.push({event:e,data:t}),s={event:"",data:""}}}else if(r>0){const t=e.subarray(f,d),n=c.decode(t.subarray(0,r)),o=r+(t[r+1]===a.Space?2:1),i=c.decode(t.subarray(o));switch(n){case"event":s.event=i;break;case"data":s.data=s.data?s.data+"\n"+i:i}}f=t,r=-1}if(f===u){e=void 0;const t=[...l];return l=[],t}0!==f&&(e=e.subarray(f),t-=f)}}();for await(const r of function(e){if("function"==typeof Object(e)[Symbol.asyncIterator])return e;return async function*(){const t=e.getReader();let r;do{r=await t.read(),void 0!==r.value&&(yield r.value)}while(!r.done)}()}(v.body)){if("string"==typeof r)throw b=new Error(`Unexpected string chunk "${r}"`);let n;try{n=t(r)}catch(e){throw b=e}if(n)for(const t of n){try{null==h||h(t)}catch(e){throw b=e}const r=t.data&&"id"in t.data?t.data.id:"";switch(r in y||(y[r]=[]),t.event){case"next":r?y[r].push(t.data.payload):y[r].push(t.data);break;case"complete":y[r].push("complete");break;default:throw b=new Error(`Unexpected message event "${t.event}"`)}null===(e=w[r])||void 0===e||e.proceed()}}if(Object.keys(w).length)throw new Error("Connection closed while having active streams")}catch(e){b=!b&&Object.keys(w).length?new i(e):e,null==p||p(b)}finally{Object.values(w).forEach((({proceed:e})=>e()))}})(),{url:r,headers:l,waitForThrow:()=>new Promise(((e,t)=>{if(b)return t(b);p=t})),async*getResults(e){var t;const{signal:r,operationId:n=""}=null!=e?e:{};try{for(;;){for(;null===(t=y[n])||void 0===t?void 0:t.length;){const e=y[n].shift();if("complete"===e)return;yield e}if(b)throw b;if(null==r?void 0:r.aborted)throw new Error("Getting results aborted by the client");await new Promise((e=>{const t=()=>{null==r||r.removeEventListener("abort",t),delete w[n],e()};null==r||r.addEventListener("abort",t),w[n]={proceed:t}}))}}finally{delete y[n]}}}}e.NetworkError=i,e.TOKEN_HEADER_KEY=r,e.TOKEN_QUERY_KEY="token",e.createClient=function(e){const{singleConnection:t=!1,lazy:n=!0,lazyCloseTimeout:o=0,onNonLazyError:a=console.error,generateID:l=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},retryAttempts:c=5,retry:d=async function(e){let t=1e3;for(let r=0;r<e;r++)t*=2;await new Promise((e=>setTimeout(e,t+Math.floor(2700*Math.random()+300))))},credentials:u="same-origin",referrer:f,referrerPolicy:h,onMessage:w,on:y}=e,v=e.fetchFn||fetch,p=e.abortControllerImpl||AbortController,b=(()=>{let e=!1;const t=[];return{get disposed(){return e},onDispose:r=>e?(setTimeout((()=>r()),0),()=>{}):(t.push(r),()=>{t.splice(t.indexOf(r),1)}),dispose(){if(!e){e=!0;for(const e of[...t])e()}}}})();let g,x,m=0,E=null,C=0;async function S(){try{if(b.disposed)throw new Error("Client has been disposed");return await(null!=x?x:x=(async()=>{var t,n,o;if(E){if(await d(C),g.signal.aborted)throw new Error("Connection aborted by the client");C++}null===(t=null==y?void 0:y.connecting)||void 0===t||t.call(y,!!E),g=new p;const a=b.onDispose((()=>g.abort()));g.signal.addEventListener("abort",(()=>{a(),x=void 0}));const l=e,c="function"==typeof l.url?await l.url(void 0):l.url;if(g.signal.aborted)throw new Error("Connection aborted by the client");const m="function"==typeof l.headers?await l.headers(void 0):null!==(n=l.headers)&&void 0!==n?n:{};if(g.signal.aborted)throw new Error("Connection aborted by the client");let S;try{S=await v(c,{signal:g.signal,method:"PUT",credentials:u,referrer:f,referrerPolicy:h,headers:m})}catch(e){throw new i(e)}if(201!==S.status)throw new i(S);const T=await S.text();m[r]=T;const O=await s({signal:g.signal,headers:m,credentials:u,referrer:f,referrerPolicy:h,url:c,fetchFn:v,onMessage:e=>{var t;null===(t=null==y?void 0:y.message)||void 0===t||t.call(y,e),null==w||w(e)}});return null===(o=null==y?void 0:y.connected)||void 0===o||o.call(y,!!E),O.waitForThrow().catch((()=>x=void 0)),O})())}catch(e){throw x=void 0,e}}function T(r,a,T){if(!t){const t=new p,n=b.onDispose((()=>{n(),t.abort()}));return(async()=>{var n,o,l,p,b;let g=null,x=0;for(;;)try{if(g){if(await d(x),t.signal.aborted)throw new Error("Connection aborted by the client");x++}null===(n=null==y?void 0:y.connecting)||void 0===n||n.call(y,!!g),null===(o=null==T?void 0:T.connecting)||void 0===o||o.call(T,!!g);const i=e,c="function"==typeof i.url?await i.url(r):i.url;if(t.signal.aborted)throw new Error("Connection aborted by the client");const m="function"==typeof i.headers?await i.headers(r):null!==(l=i.headers)&&void 0!==l?l:{};if(t.signal.aborted)throw new Error("Connection aborted by the client");const{getResults:E}=await s({signal:t.signal,headers:{...m,"content-type":"application/json; charset=utf-8"},credentials:u,referrer:f,referrerPolicy:h,url:c,body:JSON.stringify(r),fetchFn:v,onMessage:e=>{var t,r;null===(t=null==y?void 0:y.message)||void 0===t||t.call(y,e),null===(r=null==T?void 0:T.message)||void 0===r||r.call(T,e),null==w||w(e)}});null===(p=null==y?void 0:y.connected)||void 0===p||p.call(y,!!g),null===(b=null==T?void 0:T.connected)||void 0===b||b.call(T,!!g);for await(const e of E())g=null,x=0,a.next(e);return t.abort()}catch(e){if(t.signal.aborted)return;if(!(e instanceof i))throw e;if(!c||x>=c)throw e;g=e}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>t.abort()}m++;const O=new p,P=b.onDispose((()=>{P(),O.abort()}));return(async()=>{const e=l();r={...r,extensions:{...r.extensions,operationId:e}};let t=null;for(;;){t=null;try{const{url:n,headers:o,getResults:s}=await S();let l;try{l=await v(n,{signal:O.signal,method:"POST",credentials:u,referrer:f,referrerPolicy:h,headers:{...o,"content-type":"application/json; charset=utf-8"},body:JSON.stringify(r)})}catch(e){throw new i(e)}if(202!==l.status)throw new i(l);t=async()=>{let t;try{const r=new p,a=b.onDispose((()=>{a(),r.abort()}));t=await v(n+"?operationId="+e,{signal:r.signal,method:"DELETE",credentials:u,referrer:f,referrerPolicy:h,headers:o})}catch(e){throw new i(e)}if(200!==t.status)throw new i(t)};for await(const t of s({signal:O.signal,operationId:e}))E=null,C=0,a.next(t);return t=null,O.abort()}catch(e){if(O.signal.aborted)return await(null==t?void 0:t());if(!(e instanceof i))throw O.abort(),e;if(n&&(x=void 0),!c||C>=c)throw O.abort(),e;E=e}finally{O.signal.aborted&&0==--m&&(isFinite(o)&&o>0?setTimeout((()=>{m||g.abort()}),o):g.abort())}}})().then((()=>a.complete())).catch((e=>a.error(e))),()=>O.abort()}return t&&!n&&(async()=>{for(m++;;)try{const{waitForThrow:e}=await S();await e()}catch(e){if(b.disposed)return;if(!(e instanceof i))return null==a?void 0:a(e);if(x=void 0,!c||C>=c)return null==a?void 0:a(e);E=e}})(),{subscribe:T,iterate(e,t){const r=[],n={done:!1,error:null,resolve:()=>{}},o=T(e,{next(e){r.push(e),n.resolve()},error(e){n.done=!0,n.error=e,n.resolve()},complete(){n.done=!0,n.resolve()}},t),a=async function*(){for(;;){for(r.length||await new Promise((e=>n.resolve=e));r.length;)yield r.shift();if(n.error)throw n.error;if(n.done)return}}();return a.throw=async e=>(n.done||(n.done=!0,n.error=e,n.resolve()),{done:!0,value:void 0}),a.return=async()=>(o(),{done:!0,value:void 0}),a},dispose(){b.dispose()}}},e.isAsyncGenerator=function(e){return t(e)&&"function"==typeof Object(e)[Symbol.asyncIterator]&&"function"==typeof e.return&&"function"==typeof e.throw&&"function"==typeof e.next},e.isAsyncIterable=function(e){return"function"==typeof Object(e)[Symbol.asyncIterator]},e.parseStreamData=o,e.print=function(e){let t=`event: ${e.event}\ndata:`;return e.data&&(t+=" ",t+=JSON.stringify(e.data)),t+="\n\n",t},e.validateStreamEvent=n}));