Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fauna

Package Overview
Dependencies
Maintainers
2
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fauna - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0-beta.0

dist/values/stream.d.ts

5

dist/browser/index.js

@@ -1,2 +0,5 @@

var Ce=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var Pe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)};var i=(t,e,r)=>(Pe(t,e,"read from private field"),r?r.call(t):e.get(t)),c=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},f=(t,e,r,s)=>(Pe(t,e,"write to private field"),s?s.call(t,r):e.set(t,r),r),Ne=(t,e,r,s)=>({set _(n){f(t,e,n,r)},get _(){return i(t,e,s)}}),l=(t,e,r)=>(Pe(t,e,"access private method"),r);var ke={default:new URL("https://db.fauna.com"),local:new URL("http://localhost:8443"),localhost:new URL("http://localhost:8443")};var C=class extends Error{constructor(...e){super(...e)}},d=class extends C{httpStatus;code;queryInfo;constraint_failures;constructor(e,r){super(e.error.message),Error.captureStackTrace&&Error.captureStackTrace(this,d),this.name="ServiceError",this.code=e.error.code,this.httpStatus=r;let s={txn_ts:e.txn_ts,summary:e.summary,query_tags:e.query_tags,stats:e.stats};this.queryInfo=s,this.constraint_failures=e.error.constraint_failures}},F=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,F),this.name="QueryRuntimeError"}},P=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,P),this.name="QueryCheckError"}},N=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,N),this.name="InvalidRequestError"}},ne=class extends d{abort;constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,P),this.name="AbortError",this.abort=e.error.abort}},M=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,M),this.name="AuthenticationError"}},W=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,W),this.name="AuthorizationError"}},se=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,N),this.name="ContendedTransactionError"}},k=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,k),this.name="ThrottlingError"}},v=class extends d{stats;constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,v),this.name="QueryTimeoutError",this.stats=e.stats}},j=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,j),this.name="ServiceInternalError"}},$=class extends d{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,$),this.name="ServiceTimeoutError"}},w=class extends C{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,w),this.name="ClientError"}},A=class extends C{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,A),this.name="ClientClosedError"}},x=class extends C{constructor(e,r){super(e,r),Error.captureStackTrace&&Error.captureStackTrace(this,x),this.name="NetworkError"}},_=class extends C{httpStatus;constructor(e){super(e.message),Error.captureStackTrace&&Error.captureStackTrace(this,_),this.name="ProtocolError",this.httpStatus=e.httpStatus}};var oe=class{#e;#t;constructor({url:e,fetch_keepalive:r}){this.#e=new URL("/query/1",e).toString(),this.#t=r}async request({data:e,headers:r,method:s,client_timeout_ms:n}){let o=AbortSignal.timeout===void 0?(()=>{let T=new AbortController,m=T.signal;return setTimeout(()=>T.abort(),n),m})():AbortSignal.timeout(n),a=await fetch(this.#e,{method:s,headers:{...r,"Content-Type":"application/json"},body:JSON.stringify(e),signal:o,keepalive:this.#t}).catch(T=>{throw new x("The network connection encountered a problem.",{cause:T})}),u=a.status,p={};a.headers.forEach((T,m)=>p[m]=T);let b=await a.text();return{status:u,body:b,headers:p}}close(){}};var L;try{L=Ce("node:http2")}catch{L=void 0}var J,ie,ae,ce,I,y,pe,ve,K,me,fe,je,ye,$e,U=class{constructor({http2_session_idle_ms:e,url:r,http2_max_streams:s}){c(this,K);c(this,fe);c(this,ye);c(this,ie,void 0);c(this,ae,void 0);c(this,ce,void 0);c(this,I,0);c(this,y,void 0);if(L===void 0)throw new Error("Your platform does not support Node's http2 library");f(this,ie,e),f(this,ae,s),f(this,ce,r),f(this,y,null)}static getClient(e){var n;let r=l(n=U,pe,ve).call(n,e);i(U,J).has(r)||i(U,J).set(r,new U(e));let s=i(U,J).get(r);return Ne(s,I)._++,s}async request(e){let r=0,s;do try{return await l(this,ye,$e).call(this,e)}catch(n){if(n?.code!=="ERR_HTTP2_GOAWAY_SESSION")throw new x("The network connection encountered a problem.",{cause:n});s=n,r++}while(r<3);throw new x("The network connection encountered a problem.",{cause:s})}close(){this.isClosed()||(Ne(this,I)._--,i(this,I)===0&&i(this,y)&&!i(this,y).closed&&i(this,y).close())}isClosed(){return i(this,I)===0}},G=U;J=new WeakMap,ie=new WeakMap,ae=new WeakMap,ce=new WeakMap,I=new WeakMap,y=new WeakMap,pe=new WeakSet,ve=function({http2_session_idle_ms:e,url:r}){return`${r}|${e}`},K=new WeakSet,me=function(){f(this,I,0),i(this,y)&&!i(this,y).closed&&i(this,y).close()},fe=new WeakSet,je=function(){if(!i(this,y)||i(this,y).closed||i(this,y).destroyed){let e=L.connect(i(this,ce),{peerMaxConcurrentStreams:i(this,ae)}).once("error",()=>l(this,K,me).call(this)).once("goaway",()=>l(this,K,me).call(this));e.setTimeout(i(this,ie),()=>{l(this,K,me).call(this)}),f(this,y,e)}return i(this,y)},ye=new WeakSet,$e=function({client_timeout_ms:e,data:r,headers:s,method:n}){return new Promise((o,a)=>{let u,p=b=>{let T=Number(b[L.constants.HTTP2_HEADER_STATUS]),m="";u.on("data",z=>{m+=z}),u.on("end",()=>{o({status:T,body:m,headers:b})})};try{let b={...s,[L.constants.HTTP2_HEADER_PATH]:"/query/1",[L.constants.HTTP2_HEADER_METHOD]:n};u=l(this,fe,je).call(this).request(b).setEncoding("utf8").on("error",m=>{a(m)}).on("response",p),u.write(JSON.stringify(r),"utf8"),u.setTimeout(e,()=>{u.destroy(new Error("Client timeout"))}),u.end()}catch(b){a(b)}})},c(G,pe),c(G,J,new Map);var Ae=t=>mt()?G.getClient(t):new oe(t),Ie=t=>t instanceof Object&&"body"in t&&"headers"in t&&"status"in t,mt=()=>{if(typeof process<"u"&&process&&process.release?.name==="node")try{return Ce("node:http2"),!0}catch{return!1}return!1};var pt=/(?:\d{4}|[\u2212-]\d{4,}|\+\d{5,})/,ft=/(?:0[1-9]|1[0-2])/,yt=/(?:0[1-9]|[12]\d|3[01])/,Le=/(?:[01][0-9]|2[0-3])/,ue=/(?:[0-5][0-9])/,gt=/(?:\.\d+)/,De=new RegExp(`(${pt.source}-(${ft.source})-(${yt.source}))`),Tt=new RegExp(`(${Le.source}:${ue.source}:${ue.source}${gt.source}?)`),ht=new RegExp(`([zZ]|[+\u2212-]${Le.source}(?::?${ue.source}|:${ue.source}:${ue.source}))`),Ue=new RegExp(`^${De.source}$`),Ge=new RegExp(`^${De.source}`),Be=new RegExp(`^${De.source}T${Tt.source}${ht.source}$`);var E=class{isoString;constructor(e){this.isoString=e}static from(e){if(typeof e!="string")throw new TypeError(`Expected string but received ${typeof e}: ${e}`);if(Be.exec(e)===null)throw new RangeError(`(regex) Expected an ISO date string but received '${e}'`);return new E(e)}static fromDate(e){return new E(e.toISOString())}toDate(){let e=new Date(this.isoString);if(e.toString()==="Invalid Date")throw new RangeError("Fauna Date could not be converted to Javascript Date");return e}toString(){return`TimeStub("${this.isoString}")`}},Q=class{dateString;constructor(e){this.dateString=e}static from(e){if(typeof e!="string")throw new TypeError(`Expected string but received ${typeof e}: ${e}`);let r=Ue.exec(e);if(r===null)throw new RangeError(`Expected a plain date string but received '${e}'`);return new Q(r[0])}static fromDate(e){let r=e.toISOString(),s=Ge.exec(r);if(s===null)throw new w(`Failed to parse date '${e}'`);return new Q(s[0])}toDate(){let e=new Date(this.dateString+"T00:00:00Z");if(e.toString()==="Invalid Date")throw new RangeError("Fauna Date could not be converted to Javascript Date");return e}toString(){return`DateStub("${this.dateString}")`}};var D=class{coll;id;constructor({coll:e,id:r}){this.id=r,typeof e=="string"?this.coll=new V(e):this.coll=e}},Z=class extends D{ts;constructor(e){let{coll:r,id:s,ts:n,...o}=e;super({coll:r,id:s}),this.ts=n,Object.assign(this,o)}toObject(){return{...this}}},B=class{coll;name;constructor({coll:e,name:r}){this.name=r,typeof e=="string"?this.coll=new V(e):this.coll=e}},ee=class extends B{ts;data;constructor(e){let{coll:r,name:s,ts:n,data:o,...a}=e;super({coll:r,name:s}),this.ts=n,this.data=o||{},Object.assign(this,a)}toObject(){return{...this}}},V=class{name;constructor(e){this.name=e}},te=class{ref;cause;constructor(e,r){this.ref=e,this.cause=r}};var O=class{data;after;constructor({data:e,after:r}){this.data=e,this.after=r}},q=class{after;constructor(e){this.after=e}},R=class{#e;constructor(e,r,s){if(s=s??{},r instanceof Function)this.#e=wt(e,r,s);else if(r instanceof O||r instanceof q)this.#e=Xe(e,r,s);else throw new TypeError(`Expected 'Page<T> | EmbeddedSet | (() => Promise<T | Page<T> | EmbeddedSet>)', but received ${JSON.stringify(r)}`)}static fromQuery(e,r,s){return new R(e,async()=>(await e.query(r,s)).data,s)}static fromPageable(e,r,s){return new R(e,r,s)}flatten(){return new Ve(this)}async next(){return this.#e.next()}async return(){return this.#e.return()}async throw(e){return this.#e.throw(e)}[Symbol.asyncIterator](){return this}},Ve=class{#e;constructor(e){this.#e=xt(e)}async next(){return this.#e.next()}async return(){return this.#e.return()}async throw(e){return this.#e.throw(e)}[Symbol.asyncIterator](){return this}};async function*Xe(t,e,r){let s=e;for(s instanceof O&&(yield s.data);s.after;){let n=qe`Set.paginate(${s.after})`;s=(await t.query(n,r)).data,yield s.data}}async function*wt(t,e,r){let s=await e();if(s instanceof O||s instanceof q){for await(let n of Xe(t,s,r))yield n;return}yield[s]}async function*xt(t){for await(let e of t)for(let r of e)yield r}var H=class{static encode(e){return ge(e)}static decode(e,r){return JSON.parse(e,(s,n)=>{if(n==null)return null;if(n["@mod"])return new V(n["@mod"]);if(n["@doc"]){if(typeof n["@doc"]=="string"){let[a,u]=n["@doc"].split(":");return new D({coll:a,id:u})}let o=n["@doc"];return o.id?new Z(o):new ee(o)}else if(n["@ref"]){let o=n["@ref"],a;return o.id?a=new D(o):a=new B(o),"exists"in o&&o.exists===!1?new te(a,o.cause):a}else{if(n["@set"])return typeof n["@set"]=="string"?new q(n["@set"]):new O(n["@set"]);if(n["@int"])return Number(n["@int"]);if(n["@long"]){let o=BigInt(n["@long"]);return r.long_type==="number"?((o>Number.MAX_SAFE_INTEGER||o<Number.MIN_SAFE_INTEGER)&&console.warn("Value is too large to be represented as a number. Returning as Number with loss of precision. Use long_type 'bigint' instead."),Number(o)):o}else{if(n["@double"])return Number(n["@double"]);if(n["@date"])return Q.from(n["@date"]);if(n["@time"])return E.from(n["@time"]);if(n["@object"])return n["@object"]}}return n})}},Je=BigInt("-9223372036854775808"),Ke=BigInt("9223372036854775807"),Ye=-(2**31),ze=2**31-1,g={bigint:t=>{if(t<Je||t>Ke)throw new RangeError("BigInt value exceeds max magnitude for a 64-bit Fauna long. Use a 'number' to represent doubles beyond that limit.");return t>=Ye&&t<=ze?{"@int":t.toString()}:{"@long":t.toString()}},number:t=>{if(t===Number.POSITIVE_INFINITY||t===Number.NEGATIVE_INFINITY)throw new RangeError(`Cannot convert ${t} to a Fauna type.`);return Number.isInteger(t)?t>=Ye&&t<=ze?{"@int":t.toString()}:Number.isSafeInteger(t)?{"@long":t.toString()}:{"@double":t.toString()}:{"@double":t.toString()}},string:t=>t,object:t=>{let e=!1,r={};for(let s in t)s.startsWith("@")&&(e=!0),t[s]!==void 0&&(r[s]=ge(t[s]));return e?{"@object":r}:r},array:t=>{let e=[];for(let r in t)e.push(ge(t[r]));return e},date:t=>({"@time":t.toISOString()}),faunadate:t=>({"@date":t.dateString}),faunatime:t=>({"@time":t.isoString}),module:t=>({"@mod":t.name}),documentReference:t=>({"@ref":{id:t.id,coll:{"@mod":t.coll.name}}}),document:t=>({"@ref":{id:t.id,coll:{"@mod":t.coll.name}}}),namedDocumentReference:t=>({"@ref":{name:t.name,coll:{"@mod":t.coll.name}}}),namedDocument:t=>({"@ref":{name:t.name,coll:{"@mod":t.coll.name}}}),set:t=>{throw new w("Page could not be encoded. Fauna does not accept encoded Set values, yet. Use Page.data and Page.after as arguments, instead.")}},ge=t=>{if(t===void 0)throw new TypeError("Passing undefined as a QueryValue is not supported");switch(typeof t){case"bigint":return g.bigint(t);case"string":return g.string(t);case"number":return g.number(t);case"boolean":return t;case"object":return t==null?null:Array.isArray(t)?g.array(t):t instanceof Date?g.date(t):t instanceof Q?g.faunadate(t):t instanceof E?g.faunatime(t):t instanceof V?g.module(t):t instanceof Z?g.document(t):t instanceof D?g.documentReference(t):t instanceof ee?g.namedDocument(t):t instanceof B?g.namedDocumentReference(t):t instanceof te?ge(t.ref):t instanceof O||t instanceof q?g.set(t):g.object(t)}};function qe(t,...e){return new X(t,...e)}var X=class{#e;#t;constructor(e,...r){if(e.length===0||e.length!==r.length+1)throw new Error("invalid query constructed");this.#e=e,this.#t=r}toQuery(e={}){return{...this.#r(e),...e}}#r(e){if(this.#e.length===1)return{query:{fql:[this.#e[0]]},arguments:{}};let r={};return{query:{fql:this.#e.flatMap((n,o)=>{if(o===this.#e.length-1)return n===""?[]:[n];let a=this.#t[o],u;if(a instanceof X){let p=a.toQuery(e);u=p.query,r={...r,...p.arguments}}else u={value:H.encode(a)};return[n,u].filter(p=>p!=="")})},arguments:r}}};var Ze="1.3.1";var Te;try{Te=Ce("node:os")}catch{Te=void 0}var rt=()=>{let t={driver:["javascript",Ze].join("-"),env:"unknown",os:"unknown",runtime:"unknown"};try{let e=typeof window>"u"&&typeof process<"u"&&process.versions!=null&&process.versions.node!=null,r=typeof window<"u"&&typeof window.document<"u",s=typeof self=="object"&&self.constructor&&self.constructor.name==="DedicatedWorkerGlobalScope";e?(t.runtime=["nodejs",process.version].join("-"),t.env=_t(),t.os=[Te.platform(),Te.release()].join("-")):s?(t.runtime=et(navigator),t.env="Service Worker",t.os=tt(navigator)):r?(t.runtime=et(navigator),t.env="browser",t.os=tt(navigator)):typeof EdgeRuntime!="string"&&(t.runtime="Vercel Edge Runtime",t.env="edge")}catch{}return Object.entries(t).filter(([e,r])=>r!=="unknown").map(e=>e.join("=")).join("; ")},et=t=>{let e=t.appName,r=""+parseFloat(t.appVersion),s,n,o;return(n=t.userAgent.indexOf("Opera"))!=-1?(e="Opera",r=t.userAgent.substring(n+6),(n=t.userAgent.indexOf("Version"))!=-1&&(r=t.userAgent.substring(n+8))):(n=t.userAgent.indexOf("MSIE"))!=-1?(e="Microsoft Internet Explorer",r=t.userAgent.substring(n+5)):e=="Netscape"&&t.userAgent.indexOf("Trident/")!=-1?(e="Microsoft Internet Explorer",r=t.userAgent.substring(n+5),(n=t.userAgent.indexOf("rv:"))!=-1&&(r=t.userAgent.substring(n+3))):(n=t.userAgent.indexOf("Chrome"))!=-1?(e="Chrome",r=t.userAgent.substring(n+7)):(n=t.userAgent.indexOf("Safari"))!=-1?(e="Safari",r=t.userAgent.substring(n+7),(n=t.userAgent.indexOf("Version"))!=-1&&(r=t.userAgent.substring(n+8)),t.userAgent.indexOf("CriOS")!=-1&&(e="Chrome")):(n=t.userAgent.indexOf("Firefox"))!=-1?(e="Firefox",r=t.userAgent.substring(n+8)):(s=t.userAgent.lastIndexOf(" ")+1)<(n=t.userAgent.lastIndexOf("/"))&&(e=t.userAgent.substring(s,n),r=t.userAgent.substring(n+1),e.toLowerCase()==e.toUpperCase()&&(e=t.appName)),(o=r.indexOf(";"))!=-1&&(r=r.substring(0,o)),(o=r.indexOf(" "))!=-1&&(r=r.substring(0,o)),(o=r.indexOf(")"))!=-1&&(r=r.substring(0,o)),[e,r].join("-")},tt=t=>{let e="unknown",r=[{s:"Windows 10",r:/(Windows 10.0|Windows NT 10.0)/},{s:"Windows 8.1",r:/(Windows 8.1|Windows NT 6.3)/},{s:"Windows 8",r:/(Windows 8|Windows NT 6.2)/},{s:"Windows 7",r:/(Windows 7|Windows NT 6.1)/},{s:"Windows Vista",r:/Windows NT 6.0/},{s:"Windows Server 2003",r:/Windows NT 5.2/},{s:"Windows XP",r:/(Windows NT 5.1|Windows XP)/},{s:"Windows 2000",r:/(Windows NT 5.0|Windows 2000)/},{s:"Windows ME",r:/(Win 9x 4.90|Windows ME)/},{s:"Windows 98",r:/(Windows 98|Win98)/},{s:"Windows 95",r:/(Windows 95|Win95|Windows_95)/},{s:"Windows NT 4.0",r:/(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/},{s:"Windows CE",r:/Windows CE/},{s:"Windows 3.11",r:/Win16/},{s:"Android",r:/Android/},{s:"Open BSD",r:/OpenBSD/},{s:"Sun OS",r:/SunOS/},{s:"Chrome OS",r:/CrOS/},{s:"Linux",r:/(Linux|X11(?!.*CrOS))/},{s:"iOS",r:/(iPhone|iPad|iPod)/},{s:"Mac OS X",r:/Mac OS X/},{s:"Mac OS",r:/(Mac OS|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/},{s:"QNX",r:/QNX/},{s:"UNIX",r:/UNIX/},{s:"BeOS",r:/BeOS/},{s:"OS/2",r:/OS\/2/},{s:"Search Bot",r:/(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/}];for(let n in r){let o=r[n];if(o.r.test(t.userAgent)){e=o.s;break}}let s="unknown";if(/Windows/.test(e)){let n=/Windows (.*)/.exec(e);n&&(s=n[1]),e="Windows"}switch(e){case"Mac OS":case"Mac OS X":case"Android":{let n=/(?:Android|Mac OS|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh) ([._\d]+)/.exec(t.userAgent);n&&(s=n[1]);break}case"iOS":{let n=/OS (\d+)_(\d+)_?(\d+)?/.exec(t.appVersion);n&&(s=n[1]+"."+n[2]+"."+(n[3]??0));break}}return[e,s].join("-")},St=typeof window<"u"?window:typeof globalThis<"u"?globalThis:typeof global<"u"?global:self,_t=()=>{if(!(typeof process<"u"&&process&&process.env&&typeof process.env=="object"))return"unknown";let e=[{name:"Netlify",check:function(){return!!process.env.NETLIFY_IMAGES_CDN_DOMAIN}},{name:"Vercel",check:function(){return!!process.env.VERCEL}},{name:"Heroku",check:function(){return!!process.env.PATH&&process.env.PATH.indexOf(".heroku")!==-1}},{name:"AWS Lambda",check:function(){return!!process.env.AWS_LAMBDA_FUNCTION_VERSION}},{name:"GCP Cloud Functions",check:function(){return!!process.env._&&process.env._.indexOf("google")!==-1}},{name:"GCP Compute Instances",check:function(){return!!process.env.GOOGLE_CLOUD_PROJECT}},{name:"Azure Cloud Functions",check:function(){return!!process.env.WEBSITE_FUNCTIONS_AZUREMONITOR_CATEGORIES}},{name:"Azure Compute",check:function(){return!!process.env.ORYX_ENV_TYPE&&!!process.env.WEBSITE_INSTANCE_ID&&process.env.ORYX_ENV_TYPE==="AppService"}},{name:"Mongo Stitch",check:function(){return typeof St?.StitchError=="function"}},{name:"Render",check:function(){return!!process.env.RENDER_SERVICE_ID}},{name:"Begin",check:function(){return!!process.env.BEGIN_DATA_SCOPE_ID}}].find(r=>r.check());return e?e.name:"unknown"};var nt=t=>t instanceof Object&&"data"in t,st=t=>t instanceof Object&&"error"in t&&t.error instanceof Object&&"code"in t.error&&"message"in t.error;var He={client_timeout_buffer_ms:5e3,format:"tagged",http2_session_idle_ms:5e3,http2_max_streams:100,long_type:"number",fetch_keepalive:!1,query_timeout_ms:5e3,max_attempts:3,max_backoff:20},be,S,Y,h,re,de,Fe,le,Me,we,ot,xe,it,Se,at,_e,ct,Ee,ut,Qe,dt,We=class{constructor(e,r){c(this,de);c(this,le);c(this,we);c(this,xe);c(this,Se);c(this,_e);c(this,Ee);c(this,Qe);c(this,S,void 0);c(this,Y,void 0);c(this,h,void 0);c(this,re,!1);f(this,S,{...He,...e,secret:l(this,we,ot).call(this,e),endpoint:l(this,xe,it).call(this,e)}),l(this,Qe,dt).call(this),r?f(this,Y,r):f(this,Y,Ae({url:i(this,S).endpoint.toString(),http2_session_idle_ms:i(this,S).http2_session_idle_ms,http2_max_streams:i(this,S).http2_max_streams,fetch_keepalive:i(this,S).fetch_keepalive}))}get lastTxnTs(){return i(this,h)}set lastTxnTs(e){e!==void 0&&f(this,h,i(this,h)?Math.max(e,i(this,h)):e)}get clientConfiguration(){let{...e}=i(this,S);return e}close(){if(i(this,re))throw new A("Your client is closed. You cannot close it again.");i(this,Y).close(),f(this,re,!0)}paginate(e,r){return e instanceof X?R.fromQuery(this,e,r):R.fromPageable(this,e,r)}async query(e,r){if(i(this,re))throw new A("Your client is closed. No further requests can be issued.");let s=e.toQuery(r).query;return l(this,de,Fe).call(this,s,r)}},he=We;be=new WeakMap,S=new WeakMap,Y=new WeakMap,h=new WeakMap,re=new WeakMap,de=new WeakSet,Fe=async function(e,r,s=0){let n=this.clientConfiguration.max_backoff??He.max_backoff,o=this.clientConfiguration.max_attempts??He.max_attempts,a=Math.min(Math.random()*2**s,n)*1e3,u=p=>new Promise(b=>setTimeout(b,p));return s+=1,l(this,_e,ct).call(this,e,r,s).catch(p=>{if(p instanceof k&&s<o)return u(a).then(()=>l(this,de,Fe).call(this,e,r,s));throw p})},le=new WeakSet,Me=function(e){if(e instanceof w||e instanceof x||e instanceof _||e instanceof d)return e;if(Ie(e)){if(st(e.body)){let r=e.body,s=e.status;return l(this,Se,at).call(this,r,s)}return new _({message:`Response is in an unkown format: ${e.body}`,httpStatus:e.status})}return new w("A client level error occurred. Fauna was not called.",{cause:e})},we=new WeakSet,ot=function(e){let r;typeof process<"u"&&process&&typeof process=="object"&&process.env&&typeof process.env=="object"&&(r=process.env.FAUNA_SECRET);let s=e?.secret??r;if(s===void 0)throw new TypeError("You must provide a secret to the driver. Set it in an environmental variable named FAUNA_SECRET or pass it to the Client constructor.");return s},xe=new WeakSet,it=function(e){if(e&&"endpoint"in e&&e.endpoint===void 0)throw new TypeError("ClientConfiguration option endpoint must be defined.");let r;return typeof process<"u"&&process&&typeof process=="object"&&process.env&&typeof process.env=="object"&&(r=process.env.FAUNA_ENDPOINT?new URL(process.env.FAUNA_ENDPOINT):void 0),e?.endpoint??r??ke.default},Se=new WeakSet,at=function(e,r){switch(r){case 400:return Et.includes(e.error.code)?new P(e,r):e.error.code==="invalid_request"?new N(e,r):e.error.code==="abort"&&e.error.abort!==void 0?new ne(e,r):new F(e,r);case 401:return new M(e,r);case 403:return new W(e,r);case 409:return new se(e,r);case 429:return new k(e,r);case 440:return new v(e,r);case 500:return new j(e,r);case 503:return new $(e,r);default:return new d(e,r)}},_e=new WeakSet,ct=async function(e,r,s=0){try{let n={...i(this,S),...r},o={Authorization:`Bearer ${n.secret}`};l(this,Ee,ut).call(this,n,o);let a=n.format==="tagged",u=n.arguments?a?H.encode(n.arguments):n.arguments:void 0,p={query:e,arguments:u},b=n.query_timeout_ms+i(this,S).client_timeout_buffer_ms,T=await i(this,Y).request({client_timeout_ms:b,data:p,headers:o,method:"POST"}),m;try{if(m={...T,body:a?H.decode(T.body,{long_type:n.long_type}):JSON.parse(T.body)},m.body.query_tags){let Re=m.body.query_tags.split(",").map(lt=>lt.split("="));m.body.query_tags=Object.fromEntries(Re)}}catch(Re){throw new _({message:`Error parsing response as JSON: ${Re}`,httpStatus:T.status})}if(!nt(m.body))throw l(this,le,Me).call(this,m);let z=m.body.txn_ts;(i(this,h)===void 0&&z!==void 0||z!==void 0&&i(this,h)!==void 0&&i(this,h)<z)&&f(this,h,z);let Oe=m.body;return Oe.stats&&(Oe.stats.attempts=s),Oe}catch(n){throw l(this,le,Me).call(this,n)}},Ee=new WeakSet,ut=function(e,r){for(let s of Object.entries(e))if(["format","query_timeout_ms","linearized","max_contention_retries","traceparent","typecheck","query_tags"].includes(s[0])){let n,o=`x-${s[0].replaceAll("_","-")}`;s[0]==="query_tags"?n=Object.entries(s[1]).map(a=>a.join("=")).join(","):typeof s[1]=="string"?n=s[1]:n=String(s[1]),s[0]==="traceparent"&&(o=s[0]),r[o]=n}r["x-last-txn-ts"]===void 0&&i(this,h)!==void 0&&(r["x-last-txn-ts"]=i(this,h)),r["x-driver-env"]=i(We,be)},Qe=new WeakSet,dt=function(){let e=i(this,S);if(["client_timeout_buffer_ms","endpoint","format","http2_session_idle_ms","long_type","query_timeout_ms","fetch_keepalive","http2_max_streams"].forEach(s=>{if(e[s]===void 0)throw new TypeError(`ClientConfiguration option '${s}' must be defined.`)}),e.http2_max_streams<=0)throw new RangeError("'http2_max_streams' must be greater than zero.");if(e.client_timeout_buffer_ms<=0)throw new RangeError("'client_timeout_buffer_ms' must be greater than zero.");if(e.query_timeout_ms<=0)throw new RangeError("'query_timeout_ms' must be greater than zero.")},c(he,be,rt());var Et=["invalid_function_definition","invalid_identifier","invalid_query","invalid_syntax","invalid_type"];export{ne as AbortError,M as AuthenticationError,W as AuthorizationError,he as Client,A as ClientClosedError,w as ClientError,se as ContendedTransactionError,Q as DateStub,Z as Document,D as DocumentReference,q as EmbeddedSet,C as FaunaError,oe as FetchClient,N as InvalidRequestError,Ke as LONG_MAX,Je as LONG_MIN,V as Module,ee as NamedDocument,B as NamedDocumentReference,x as NetworkError,G as NodeHTTP2Client,te as NullDocument,O as Page,_ as ProtocolError,P as QueryCheckError,F as QueryRuntimeError,v as QueryTimeoutError,d as ServiceError,j as ServiceInternalError,$ as ServiceTimeoutError,R as SetIterator,H as TaggedTypeFormat,k as ThrottlingError,E as TimeStub,ke as endpoints,qe as fql,Ae as getDefaultHTTPClient,Ie as isHTTPResponse};
var Ie=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var De=(r,e,t)=>{if(!e.has(r))throw TypeError("Cannot "+t)};var a=(r,e,t)=>(De(r,e,"read from private field"),t?t.call(r):e.get(r)),u=(r,e,t)=>{if(e.has(r))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(r):e.set(r,t)},T=(r,e,t,s)=>(De(r,e,"write to private field"),s?s.call(r,t):e.set(r,t),t),ve=(r,e,t,s)=>({set _(n){T(r,e,n,t)},get _(){return a(r,e,s)}}),p=(r,e,t)=>(De(r,e,"access private method"),t);var qe={default:new URL("https://db.fauna.com"),local:new URL("http://localhost:8443"),localhost:new URL("http://localhost:8443")};var R=class extends Error{constructor(...e){super(...e)}},l=class extends R{httpStatus;code;queryInfo;constraint_failures;constructor(e,t){super(e.error.message),Error.captureStackTrace&&Error.captureStackTrace(this,l),this.name="ServiceError",this.code=e.error.code,this.httpStatus=t;let s={txn_ts:e.txn_ts,summary:e.summary,query_tags:e.query_tags,stats:e.stats};this.queryInfo=s,this.constraint_failures=e.error.constraint_failures}},B=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,B),this.name="QueryRuntimeError"}},q=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,q),this.name="QueryCheckError"}},V=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,V),this.name="InvalidRequestError"}},ce=class extends l{abort;constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,q),this.name="AbortError",this.abort=e.error.abort}},z=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,z),this.name="AuthenticationError"}},X=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,X),this.name="AuthorizationError"}},ue=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,V),this.name="ContendedTransactionError"}},F=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,F),this.name="ThrottlingError"}},Y=class extends l{stats;constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,Y),this.name="QueryTimeoutError",this.stats=e.stats}},J=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,J),this.name="ServiceInternalError"}},K=class extends l{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,K),this.name="ServiceTimeoutError"}},b=class extends R{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,b),this.name="ClientError"}},P=class extends R{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,P),this.name="ClientClosedError"}},w=class extends R{constructor(e,t){super(e,t),Error.captureStackTrace&&Error.captureStackTrace(this,w),this.name="NetworkError"}},k=class extends R{httpStatus;constructor(e){super(e.message),Error.captureStackTrace&&Error.captureStackTrace(this,k),this.name="ProtocolError",this.httpStatus=e.httpStatus}};var de=class{#e;#t;#r;constructor({url:e,fetch_keepalive:t}){this.#e=new URL("/query/1",e).toString(),this.#t=new URL("/stream/1",e).toString(),this.#r=t}async request({data:e,headers:t,method:s,client_timeout_ms:n}){let o=AbortSignal.timeout===void 0?(()=>{let f=new AbortController,m=f.signal;return setTimeout(()=>f.abort(),n),m})():AbortSignal.timeout(n),i=await fetch(this.#e,{method:s,headers:{...t,"Content-Type":"application/json"},body:JSON.stringify(e),signal:o,keepalive:this.#r}).catch(f=>{throw new w("The network connection encountered a problem.",{cause:f})}),c=i.status,d={};i.headers.forEach((f,m)=>d[m]=f);let g=await i.text();return{status:c,body:g,headers:d}}stream({data:e,headers:t,method:s}){let n=new Request(this.#t,{method:s,headers:{...t,"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:this.#r}),o=new AbortController,i={signal:o.signal};async function*c(){let d=await fetch(n,i).catch(y=>{throw new w("The network connection encountered a problem.",{cause:y})}),g=d.status;if(!(g>=200&&g<400)){let y=await d.json();throw new l(y,g)}let f=d.body;if(!f)throw new Error("Response body is undefined.");let m=f.getReader();for await(let y of St(m))yield y}return{read:c(),close:()=>{o.abort("Stream closed by the client.")}}}close(){}};async function*St(r){let e=new TextDecoder,t="";for await(let s of wt(r)){let n=e.decode(s),o=(t+n).split(`
`);for(let i=0;i<o.length-1;i++)yield o[i].trim();t=o[o.length-1]}t.trim()!==""&&(yield t)}async function*wt(r){let e=!1;do{let t=await r.read();t.value!==void 0&&(yield t.value),e=t.done}while(!e)}var Q;try{Q=Ie("node:http2")}catch{Q=void 0}var ne,le,me,pe,M,S,be,Xe,se,Te,fe,Ve,Se,Ye,we,Je,Z=class{constructor({http2_session_idle_ms:e,url:t,http2_max_streams:s}){u(this,se);u(this,fe);u(this,Se);u(this,we);u(this,le,void 0);u(this,me,void 0);u(this,pe,void 0);u(this,M,0);u(this,S,void 0);if(Q===void 0)throw new Error("Your platform does not support Node's http2 library");T(this,le,e),T(this,me,s),T(this,pe,t),T(this,S,null)}static getClient(e){var n;let t=p(n=Z,be,Xe).call(n,e);a(Z,ne).has(t)||a(Z,ne).set(t,new Z(e));let s=a(Z,ne).get(t);return ve(s,M)._++,s}async request(e){let t=0,s;do try{return await p(this,Se,Ye).call(this,e)}catch(n){if(n?.code!=="ERR_HTTP2_GOAWAY_SESSION")throw new w("The network connection encountered a problem.",{cause:n});s=n,t++}while(t<3);throw new w("The network connection encountered a problem.",{cause:s})}stream(e){return p(this,we,Je).call(this,e)}close(){this.isClosed()||(ve(this,M)._--,a(this,M)===0&&a(this,S)&&!a(this,S).closed&&a(this,S).close())}isClosed(){return a(this,M)===0}},ee=Z;ne=new WeakMap,le=new WeakMap,me=new WeakMap,pe=new WeakMap,M=new WeakMap,S=new WeakMap,be=new WeakSet,Xe=function({http2_session_idle_ms:e,url:t}){return`${t}|${e}`},se=new WeakSet,Te=function(){T(this,M,0),a(this,S)&&!a(this,S).closed&&a(this,S).close()},fe=new WeakSet,Ve=function(){if(!a(this,S)||a(this,S).closed||a(this,S).destroyed){let e=Q.connect(a(this,pe),{peerMaxConcurrentStreams:a(this,me)}).once("error",()=>p(this,se,Te).call(this)).once("goaway",()=>p(this,se,Te).call(this));e.setTimeout(a(this,le),()=>{p(this,se,Te).call(this)}),T(this,S,e)}return a(this,S)},Se=new WeakSet,Ye=function({client_timeout_ms:e,data:t,headers:s,method:n}){return new Promise((o,i)=>{let c,d=g=>{let f=Number(g[Q.constants.HTTP2_HEADER_STATUS]),m="";c.on("data",y=>{m+=y}),c.on("end",()=>{o({status:f,body:m,headers:g})})};try{let g={...s,[Q.constants.HTTP2_HEADER_PATH]:"/query/1",[Q.constants.HTTP2_HEADER_METHOD]:n};c=p(this,fe,Ve).call(this).request(g).setEncoding("utf8").on("error",m=>{i(m)}).on("response",d),c.write(JSON.stringify(t),"utf8"),c.setTimeout(e,()=>{c.destroy(new Error("Client timeout"))}),c.end()}catch(g){i(g)}})},we=new WeakSet,Je=function({data:e,headers:t,method:s}){let n,o,i=()=>new Promise((y,C)=>{n=y,o=C}),c=i(),d,g=y=>{let C=Number(y[Q.constants.HTTP2_HEADER_STATUS]);if(C>=200&&C<400){let E="";d.on("data",v=>{let G=(E+v).split(`
`);n(G.map(He=>He.trim()).slice(0,-1)),c=i(),E=G[G.length-1]}),d.on("end",()=>{n([E])})}else{let E="";d.on("data",v=>{E+=v}),d.on("end",()=>{o(new l(JSON.parse(E),C))})}},f=this;async function*m(){var v;let y={...t,[Q.constants.HTTP2_HEADER_PATH]:"/stream/1",[Q.constants.HTTP2_HEADER_METHOD]:s};d=p(v=f,fe,Ve).call(v).request(y).setEncoding("utf8").on("error",G=>{o(G)}).on("response",g);let E=JSON.stringify(e);for(d.write(E,"utf8"),d.end();;){let G=await c;for(let He of G)yield He}}return{read:m(),close:()=>{d&&d.close()}}},u(ee,be),u(ee,ne,new Map);var Fe=r=>xt()?ee.getClient(r):new de(r),Me=r=>r instanceof Object&&"body"in r&&"headers"in r&&"status"in r,We=r=>"stream"in r&&typeof r.stream=="function",xt=()=>{if(typeof process<"u"&&process&&process.release?.name==="node")try{return Ie("node:http2"),!0}catch{return!1}return!1};var Et=/(?:\d{4}|[\u2212-]\d{4,}|\+\d{5,})/,_t=/(?:0[1-9]|1[0-2])/,Ct=/(?:0[1-9]|[12]\d|3[01])/,Ke=/(?:[01][0-9]|2[0-3])/,ye=/(?:[0-5][0-9])/,Rt=/(?:\.\d+)/,je=new RegExp(`(${Et.source}-(${_t.source})-(${Ct.source}))`),Qt=new RegExp(`(${Ke.source}:${ye.source}:${ye.source}${Rt.source}?)`),Pt=new RegExp(`([zZ]|[+\u2212-]${Ke.source}(?::?${ye.source}|:${ye.source}:${ye.source}))`),Ze=new RegExp(`^${je.source}$`),et=new RegExp(`^${je.source}`),tt=new RegExp(`^${je.source}T${Qt.source}${Pt.source}$`);var O=class{isoString;constructor(e){this.isoString=e}static from(e){if(typeof e!="string")throw new TypeError(`Expected string but received ${typeof e}: ${e}`);if(tt.exec(e)===null)throw new RangeError(`(regex) Expected an ISO date string but received '${e}'`);return new O(e)}static fromDate(e){return new O(e.toISOString())}toDate(){let e=new Date(this.isoString);if(e.toString()==="Invalid Date")throw new RangeError("Fauna Date could not be converted to Javascript Date");return e}toString(){return`TimeStub("${this.isoString}")`}},A=class{dateString;constructor(e){this.dateString=e}static from(e){if(typeof e!="string")throw new TypeError(`Expected string but received ${typeof e}: ${e}`);let t=Ze.exec(e);if(t===null)throw new RangeError(`Expected a plain date string but received '${e}'`);return new A(t[0])}static fromDate(e){let t=e.toISOString(),s=et.exec(t);if(s===null)throw new b(`Failed to parse date '${e}'`);return new A(s[0])}toDate(){let e=new Date(this.dateString+"T00:00:00Z");if(e.toString()==="Invalid Date")throw new RangeError("Fauna Date could not be converted to Javascript Date");return e}toString(){return`DateStub("${this.dateString}")`}};var W=class{coll;id;constructor({coll:e,id:t}){this.id=t,typeof e=="string"?this.coll=new j(e):this.coll=e}},oe=class extends W{ts;constructor(e){let{coll:t,id:s,ts:n,...o}=e;super({coll:t,id:s}),this.ts=n,Object.assign(this,o)}toObject(){return{...this}}},te=class{coll;name;constructor({coll:e,name:t}){this.name=t,typeof e=="string"?this.coll=new j(e):this.coll=e}},ie=class extends te{ts;data;constructor(e){let{coll:t,name:s,ts:n,data:o,...i}=e;super({coll:t,name:s}),this.ts=n,this.data=o||{},Object.assign(this,i)}toObject(){return{...this}}},j=class{name;constructor(e){this.name=e}},ae=class{ref;cause;constructor(e,t){this.ref=e,this.cause=t}};var N=class{data;after;constructor({data:e,after:t}){this.data=e,this.after=t}},$=class{after;constructor(e){this.after=e}},H=class{#e;constructor(e,t,s){if(s=s??{},t instanceof Function)this.#e=Ot(e,t,s);else if(t instanceof N||t instanceof $)this.#e=rt(e,t,s);else throw new TypeError(`Expected 'Page<T> | EmbeddedSet | (() => Promise<T | Page<T> | EmbeddedSet>)', but received ${JSON.stringify(t)}`)}static fromQuery(e,t,s){return new H(e,async()=>(await e.query(t,s)).data,s)}static fromPageable(e,t,s){return new H(e,t,s)}flatten(){return new $e(this)}async next(){return this.#e.next()}async return(){return this.#e.return()}async throw(e){return this.#e.throw(e)}[Symbol.asyncIterator](){return this}},$e=class{#e;constructor(e){this.#e=At(e)}async next(){return this.#e.next()}async return(){return this.#e.return()}async throw(e){return this.#e.throw(e)}[Symbol.asyncIterator](){return this}};async function*rt(r,e,t){let s=e;for(s instanceof N&&(yield s.data);s.after;){let n=Le`Set.paginate(${s.after})`;s=(await r.query(n,t)).data,yield s.data}}async function*Ot(r,e,t){let s=await e();if(s instanceof N||s instanceof $){for await(let n of rt(r,s,t))yield n;return}yield[s]}async function*At(r){for await(let e of r)for(let t of e)yield t}var I=class{token;constructor(e){this.token=e}};var D=class{static encode(e){return xe(e)}static decode(e,t){return JSON.parse(e,(s,n)=>{if(n==null)return null;if(n["@mod"])return new j(n["@mod"]);if(n["@doc"]){if(typeof n["@doc"]=="string"){let[i,c]=n["@doc"].split(":");return new W({coll:i,id:c})}let o=n["@doc"];return o.id?new oe(o):new ie(o)}else if(n["@ref"]){let o=n["@ref"],i;return o.id?i=new W(o):i=new te(o),"exists"in o&&o.exists===!1?new ae(i,o.cause):i}else{if(n["@set"])return typeof n["@set"]=="string"?new $(n["@set"]):new N(n["@set"]);if(n["@int"])return Number(n["@int"]);if(n["@long"]){let o=BigInt(n["@long"]);return t.long_type==="number"?((o>Number.MAX_SAFE_INTEGER||o<Number.MIN_SAFE_INTEGER)&&console.warn("Value is too large to be represented as a number. Returning as Number with loss of precision. Use long_type 'bigint' instead."),Number(o)):o}else{if(n["@double"])return Number(n["@double"]);if(n["@date"])return A.from(n["@date"]);if(n["@time"])return O.from(n["@time"]);if(n["@object"])return n["@object"];if(n["@stream"])return new I(n["@stream"])}}return n})}},ot=BigInt("-9223372036854775808"),it=BigInt("9223372036854775807"),nt=-(2**31),st=2**31-1,h={bigint:r=>{if(r<ot||r>it)throw new RangeError("BigInt value exceeds max magnitude for a 64-bit Fauna long. Use a 'number' to represent doubles beyond that limit.");return r>=nt&&r<=st?{"@int":r.toString()}:{"@long":r.toString()}},number:r=>{if(r===Number.POSITIVE_INFINITY||r===Number.NEGATIVE_INFINITY)throw new RangeError(`Cannot convert ${r} to a Fauna type.`);return Number.isInteger(r)?r>=nt&&r<=st?{"@int":r.toString()}:Number.isSafeInteger(r)?{"@long":r.toString()}:{"@double":r.toString()}:{"@double":r.toString()}},string:r=>r,object:r=>{let e=!1,t={};for(let s in r)s.startsWith("@")&&(e=!0),r[s]!==void 0&&(t[s]=xe(r[s]));return e?{"@object":t}:t},array:r=>{let e=[];for(let t in r)e.push(xe(r[t]));return e},date:r=>({"@time":r.toISOString()}),faunadate:r=>({"@date":r.dateString}),faunatime:r=>({"@time":r.isoString}),module:r=>({"@mod":r.name}),documentReference:r=>({"@ref":{id:r.id,coll:{"@mod":r.coll.name}}}),document:r=>({"@ref":{id:r.id,coll:{"@mod":r.coll.name}}}),namedDocumentReference:r=>({"@ref":{name:r.name,coll:{"@mod":r.coll.name}}}),namedDocument:r=>({"@ref":{name:r.name,coll:{"@mod":r.coll.name}}}),set:r=>{throw new b("Page could not be encoded. Fauna does not accept encoded Set values, yet. Use Page.data and Page.after as arguments, instead.")},streamToken:r=>r.token},xe=r=>{if(r===void 0)throw new TypeError("Passing undefined as a QueryValue is not supported");switch(typeof r){case"bigint":return h.bigint(r);case"string":return h.string(r);case"number":return h.number(r);case"boolean":return r;case"object":return r==null?null:Array.isArray(r)?h.array(r):r instanceof Date?h.date(r):r instanceof A?h.faunadate(r):r instanceof O?h.faunatime(r):r instanceof j?h.module(r):r instanceof oe?h.document(r):r instanceof W?h.documentReference(r):r instanceof ie?h.namedDocument(r):r instanceof te?h.namedDocumentReference(r):r instanceof ae?xe(r.ref):r instanceof N||r instanceof $?h.set(r):r instanceof I?h.streamToken(r):h.object(r)}};function Le(r,...e){return new L(r,...e)}var L=class{#e;#t;constructor(e,...t){if(e.length===0||e.length!==t.length+1)throw new Error("invalid query constructed");this.#e=e,this.#t=t}toQuery(e={}){return{...this.#r(e),...e}}#r(e){if(this.#e.length===1)return{query:{fql:[this.#e[0]]},arguments:{}};let t={};return{query:{fql:this.#e.flatMap((n,o)=>{if(o===this.#e.length-1)return n===""?[]:[n];let i=this.#t[o],c;if(i instanceof L){let d=i.toQuery(e);c=d.query,t={...t,...d.arguments}}else c={value:D.encode(i)};return[n,c].filter(d=>d!=="")})},arguments:t}}};var at="1.4.0-beta.0";var Ee;try{Ee=Ie("node:os")}catch{Ee=void 0}var dt=()=>{let r={driver:["javascript",at].join("-"),env:"unknown",os:"unknown",runtime:"unknown"};try{let e=typeof window>"u"&&typeof process<"u"&&process.versions!=null&&process.versions.node!=null,t=typeof window<"u"&&typeof window.document<"u",s=typeof self=="object"&&self.constructor&&self.constructor.name==="DedicatedWorkerGlobalScope";e?(r.runtime=["nodejs",process.version].join("-"),r.env=Ht(),r.os=[Ee.platform(),Ee.release()].join("-")):s?(r.runtime=ct(navigator),r.env="Service Worker",r.os=ut(navigator)):t?(r.runtime=ct(navigator),r.env="browser",r.os=ut(navigator)):typeof EdgeRuntime!="string"&&(r.runtime="Vercel Edge Runtime",r.env="edge")}catch{}return Object.entries(r).filter(([e,t])=>t!=="unknown").map(e=>e.join("=")).join("; ")},ct=r=>{let e=r.appName,t=""+parseFloat(r.appVersion),s,n,o;return(n=r.userAgent.indexOf("Opera"))!=-1?(e="Opera",t=r.userAgent.substring(n+6),(n=r.userAgent.indexOf("Version"))!=-1&&(t=r.userAgent.substring(n+8))):(n=r.userAgent.indexOf("MSIE"))!=-1?(e="Microsoft Internet Explorer",t=r.userAgent.substring(n+5)):e=="Netscape"&&r.userAgent.indexOf("Trident/")!=-1?(e="Microsoft Internet Explorer",t=r.userAgent.substring(n+5),(n=r.userAgent.indexOf("rv:"))!=-1&&(t=r.userAgent.substring(n+3))):(n=r.userAgent.indexOf("Chrome"))!=-1?(e="Chrome",t=r.userAgent.substring(n+7)):(n=r.userAgent.indexOf("Safari"))!=-1?(e="Safari",t=r.userAgent.substring(n+7),(n=r.userAgent.indexOf("Version"))!=-1&&(t=r.userAgent.substring(n+8)),r.userAgent.indexOf("CriOS")!=-1&&(e="Chrome")):(n=r.userAgent.indexOf("Firefox"))!=-1?(e="Firefox",t=r.userAgent.substring(n+8)):(s=r.userAgent.lastIndexOf(" ")+1)<(n=r.userAgent.lastIndexOf("/"))&&(e=r.userAgent.substring(s,n),t=r.userAgent.substring(n+1),e.toLowerCase()==e.toUpperCase()&&(e=r.appName)),(o=t.indexOf(";"))!=-1&&(t=t.substring(0,o)),(o=t.indexOf(" "))!=-1&&(t=t.substring(0,o)),(o=t.indexOf(")"))!=-1&&(t=t.substring(0,o)),[e,t].join("-")},ut=r=>{let e="unknown",t=[{s:"Windows 10",r:/(Windows 10.0|Windows NT 10.0)/},{s:"Windows 8.1",r:/(Windows 8.1|Windows NT 6.3)/},{s:"Windows 8",r:/(Windows 8|Windows NT 6.2)/},{s:"Windows 7",r:/(Windows 7|Windows NT 6.1)/},{s:"Windows Vista",r:/Windows NT 6.0/},{s:"Windows Server 2003",r:/Windows NT 5.2/},{s:"Windows XP",r:/(Windows NT 5.1|Windows XP)/},{s:"Windows 2000",r:/(Windows NT 5.0|Windows 2000)/},{s:"Windows ME",r:/(Win 9x 4.90|Windows ME)/},{s:"Windows 98",r:/(Windows 98|Win98)/},{s:"Windows 95",r:/(Windows 95|Win95|Windows_95)/},{s:"Windows NT 4.0",r:/(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/},{s:"Windows CE",r:/Windows CE/},{s:"Windows 3.11",r:/Win16/},{s:"Android",r:/Android/},{s:"Open BSD",r:/OpenBSD/},{s:"Sun OS",r:/SunOS/},{s:"Chrome OS",r:/CrOS/},{s:"Linux",r:/(Linux|X11(?!.*CrOS))/},{s:"iOS",r:/(iPhone|iPad|iPod)/},{s:"Mac OS X",r:/Mac OS X/},{s:"Mac OS",r:/(Mac OS|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/},{s:"QNX",r:/QNX/},{s:"UNIX",r:/UNIX/},{s:"BeOS",r:/BeOS/},{s:"OS/2",r:/OS\/2/},{s:"Search Bot",r:/(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/}];for(let n in t){let o=t[n];if(o.r.test(r.userAgent)){e=o.s;break}}let s="unknown";if(/Windows/.test(e)){let n=/Windows (.*)/.exec(e);n&&(s=n[1]),e="Windows"}switch(e){case"Mac OS":case"Mac OS X":case"Android":{let n=/(?:Android|Mac OS|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh) ([._\d]+)/.exec(r.userAgent);n&&(s=n[1]);break}case"iOS":{let n=/OS (\d+)_(\d+)_?(\d+)?/.exec(r.appVersion);n&&(s=n[1]+"."+n[2]+"."+(n[3]??0));break}}return[e,s].join("-")},Nt=typeof window<"u"?window:typeof globalThis<"u"?globalThis:typeof global<"u"?global:self,Ht=()=>{if(!(typeof process<"u"&&process&&process.env&&typeof process.env=="object"))return"unknown";let e=[{name:"Netlify",check:function(){return!!process.env.NETLIFY_IMAGES_CDN_DOMAIN}},{name:"Vercel",check:function(){return!!process.env.VERCEL}},{name:"Heroku",check:function(){return!!process.env.PATH&&process.env.PATH.indexOf(".heroku")!==-1}},{name:"AWS Lambda",check:function(){return!!process.env.AWS_LAMBDA_FUNCTION_VERSION}},{name:"GCP Cloud Functions",check:function(){return!!process.env._&&process.env._.indexOf("google")!==-1}},{name:"GCP Compute Instances",check:function(){return!!process.env.GOOGLE_CLOUD_PROJECT}},{name:"Azure Cloud Functions",check:function(){return!!process.env.WEBSITE_FUNCTIONS_AZUREMONITOR_CATEGORIES}},{name:"Azure Compute",check:function(){return!!process.env.ORYX_ENV_TYPE&&!!process.env.WEBSITE_INSTANCE_ID&&process.env.ORYX_ENV_TYPE==="AppService"}},{name:"Mongo Stitch",check:function(){return typeof Nt?.StitchError=="function"}},{name:"Render",check:function(){return!!process.env.RENDER_SERVICE_ID}},{name:"Begin",check:function(){return!!process.env.BEGIN_DATA_SCOPE_ID}}].find(t=>t.check());return e?e.name:"unknown"};var lt=r=>r instanceof Object&&"data"in r,mt=r=>r instanceof Object&&"error"in r&&r.error instanceof Object&&"code"in r.error&&"message"in r.error;var Ue={client_timeout_buffer_ms:5e3,format:"tagged",http2_session_idle_ms:5e3,http2_max_streams:100,long_type:"number",fetch_keepalive:!1,query_timeout_ms:5e3,max_attempts:3,max_backoff:20},Re,x,U,_,re,ge,Ge,he,Be,Qe,pt,Pe,ft,ke,yt,Oe,gt,Ae,ht,Ne,Tt,ze=class{constructor(e,t){u(this,ge);u(this,he);u(this,Qe);u(this,Pe);u(this,ke);u(this,Oe);u(this,Ae);u(this,Ne);u(this,x,void 0);u(this,U,void 0);u(this,_,void 0);u(this,re,!1);T(this,x,{...Ue,...e,secret:p(this,Qe,pt).call(this,e),endpoint:p(this,Pe,ft).call(this,e)}),p(this,Ne,Tt).call(this),t?T(this,U,t):T(this,U,Fe({url:a(this,x).endpoint.toString(),http2_session_idle_ms:a(this,x).http2_session_idle_ms,http2_max_streams:a(this,x).http2_max_streams,fetch_keepalive:a(this,x).fetch_keepalive}))}get lastTxnTs(){return a(this,_)}set lastTxnTs(e){e!==void 0&&T(this,_,a(this,_)?Math.max(e,a(this,_)):e)}get clientConfiguration(){let{...e}=a(this,x);return e}close(){if(a(this,re))throw new P("Your client is closed. You cannot close it again.");a(this,U).close(),T(this,re,!0)}paginate(e,t){return e instanceof L?H.fromQuery(this,e,t):H.fromPageable(this,e,t)}async query(e,t){if(a(this,re))throw new P("Your client is closed. No further requests can be issued.");let s=e.toQuery(t).query;return p(this,ge,Ge).call(this,s,t)}stream(e,t){if(a(this,re))throw new P("Your client is closed. No further requests can be issued.");let s=a(this,U);if(We(s)){let n={...a(this,x),httpStreamClient:s,...t},o=e instanceof L?()=>this.query(e).then(i=>i.data):e;return new Ce(o,n)}else throw new b("Streaming is not supported by this client.")}},_e=ze;Re=new WeakMap,x=new WeakMap,U=new WeakMap,_=new WeakMap,re=new WeakMap,ge=new WeakSet,Ge=async function(e,t,s=0){let n=this.clientConfiguration.max_backoff??Ue.max_backoff,o=this.clientConfiguration.max_attempts??Ue.max_attempts,i=Math.min(Math.random()*2**s,n)*1e3;s+=1;try{return await p(this,Oe,gt).call(this,e,t,s)}catch(c){if(c instanceof F&&s<o)return await bt(i),p(this,ge,Ge).call(this,e,t,s);throw c}},he=new WeakSet,Be=function(e){if(e instanceof b||e instanceof w||e instanceof k||e instanceof l)return e;if(Me(e)){if(mt(e.body)){let t=e.body,s=e.status;return p(this,ke,yt).call(this,t,s)}return new k({message:`Response is in an unkown format: ${e.body}`,httpStatus:e.status})}return new b("A client level error occurred. Fauna was not called.",{cause:e})},Qe=new WeakSet,pt=function(e){let t;typeof process<"u"&&process&&typeof process=="object"&&process.env&&typeof process.env=="object"&&(t=process.env.FAUNA_SECRET);let s=e?.secret??t;if(s===void 0)throw new TypeError("You must provide a secret to the driver. Set it in an environmental variable named FAUNA_SECRET or pass it to the Client constructor.");return s},Pe=new WeakSet,ft=function(e){if(e&&"endpoint"in e&&e.endpoint===void 0)throw new TypeError("ClientConfiguration option endpoint must be defined.");let t;return typeof process<"u"&&process&&typeof process=="object"&&process.env&&typeof process.env=="object"&&(t=process.env.FAUNA_ENDPOINT?new URL(process.env.FAUNA_ENDPOINT):void 0),e?.endpoint??t??qe.default},ke=new WeakSet,yt=function(e,t){switch(t){case 400:return It.includes(e.error.code)?new q(e,t):e.error.code==="invalid_request"?new V(e,t):e.error.code==="abort"&&e.error.abort!==void 0?new ce(e,t):new B(e,t);case 401:return new z(e,t);case 403:return new X(e,t);case 409:return new ue(e,t);case 429:return new F(e,t);case 440:return new Y(e,t);case 500:return new J(e,t);case 503:return new K(e,t);default:return new l(e,t)}},Oe=new WeakSet,gt=async function(e,t,s=0){try{let n={...a(this,x),...t},o={Authorization:`Bearer ${n.secret}`};p(this,Ae,ht).call(this,n,o);let i=n.format==="tagged",c=n.arguments?i?D.encode(n.arguments):n.arguments:void 0,d={query:e,arguments:c},g=n.query_timeout_ms+a(this,x).client_timeout_buffer_ms,f=await a(this,U).request({client_timeout_ms:g,data:d,headers:o,method:"POST"}),m;try{if(m={...f,body:i?D.decode(f.body,{long_type:n.long_type}):JSON.parse(f.body)},m.body.query_tags){let E=m.body.query_tags.split(",").map(v=>v.split("="));m.body.query_tags=Object.fromEntries(E)}}catch(E){throw new k({message:`Error parsing response as JSON: ${E}`,httpStatus:f.status})}if(!lt(m.body))throw p(this,he,Be).call(this,m);let y=m.body.txn_ts;(a(this,_)===void 0&&y!==void 0||y!==void 0&&a(this,_)!==void 0&&a(this,_)<y)&&T(this,_,y);let C=m.body;return C.stats&&(C.stats.attempts=s),C}catch(n){throw p(this,he,Be).call(this,n)}},Ae=new WeakSet,ht=function(e,t){let s=(n,o,i=c=>String(c))=>{o!==void 0&&(t[n]=i(o))};s("x-format",e.format),s("x-typecheck",e.typecheck),s("x-query-timeout-ms",e.query_timeout_ms),s("x-linearized",e.linearized),s("x-max-contention-retries",e.max_contention_retries),s("traceparent",e.traceparent),s("x-query-tags",e.query_tags,n=>Object.entries(n).map(o=>o.join("=")).join(",")),s("x-last-txn-ts",a(this,_),n=>n),s("x-driver-env",a(ze,Re))},Ne=new WeakSet,Tt=function(){let e=a(this,x);if(["client_timeout_buffer_ms","endpoint","format","http2_session_idle_ms","long_type","query_timeout_ms","fetch_keepalive","http2_max_streams","max_backoff","max_attempts"].forEach(s=>{if(e[s]===void 0)throw new TypeError(`ClientConfiguration option '${s}' must be defined.`)}),e.http2_max_streams<=0)throw new RangeError("'http2_max_streams' must be greater than zero.");if(e.client_timeout_buffer_ms<=0)throw new RangeError("'client_timeout_buffer_ms' must be greater than zero.");if(e.query_timeout_ms<=0)throw new RangeError("'query_timeout_ms' must be greater than zero.");if(e.max_backoff<=0)throw new RangeError("'max_backoff' must be greater than zero.");if(e.max_attempts<=0)throw new RangeError("'max_attempts' must be greater than zero.")},u(_e,Re,dt());var Ce=class{closed=!1;#e;#t=0;#r;#s;#n;#o;constructor(e,t){e instanceof I?this.#r=()=>Promise.resolve(e):this.#r=e,this.#e=t,this.#a()}start(e,t){if(typeof e!="function")throw new TypeError(`Expected a function as the 'onEvent' argument, but received ${typeof e}. Please provide a valid function.`);if(t&&typeof t!="function")throw new TypeError(`Expected a function as the 'onError' argument, but received ${typeof t}. Please provide a valid function.`);(async()=>{try{for await(let n of this)e(n)}catch(n){t&&t(n)}})()}async*[Symbol.asyncIterator](){if(this.closed)throw new b("The stream has been closed and cannot be reused.");for(this.#o||(this.#o=await this.#r().then(e=>{if(!(e instanceof I))throw new b(`Error requesting a stream token. Expected a StreamToken as the query result, but received ${typeof e}. Your query must return the result of '<Set>.toStream' or '<Set>.changesOn')
Query result: ${JSON.stringify(e,null)}`);return e})),this.#t=1;!this.closed;){let e=Math.min(Math.random()*2**this.#t,this.#e.max_backoff)*1e3;try{for await(let t of this.#i(this.#s))yield t}catch(t){if(t instanceof R||this.#t>=this.#e.max_attempts)throw this.close(),t;this.#t+=1,await bt(e)}}}close(){this.#n&&(this.#n.close(),this.#n=void 0),this.closed=!0}get last_ts(){return this.#s}async*#i(e){let t=this.#o,s={Authorization:`Bearer ${this.#e.secret}`},n=this.#e.httpStreamClient.stream({data:{token:t.token,start_ts:e},headers:s,method:"POST"});this.#n=n;for await(let o of n.read){let i=D.decode(o,{long_type:this.#e.long_type});if(i.type==="error")throw this.close(),new l(i,400);this.#s=i.txn_ts,i.type==="start"&&(i.type="status"),!(!this.#e.status_events&&i.type==="status")&&(yield i)}}#a(){let e=this.#e;if(["long_type","httpStreamClient","max_backoff","max_attempts","secret"].forEach(s=>{if(e[s]===void 0)throw new TypeError(`ClientConfiguration option '${s}' must be defined.`)}),e.max_backoff<=0)throw new RangeError("'max_backoff' must be greater than zero.");if(e.max_attempts<=0)throw new RangeError("'max_attempts' must be greater than zero.")}},It=["invalid_function_definition","invalid_identifier","invalid_query","invalid_syntax","invalid_type"];function bt(r){return new Promise(e=>setTimeout(e,r))}export{ce as AbortError,z as AuthenticationError,X as AuthorizationError,_e as Client,P as ClientClosedError,b as ClientError,ue as ContendedTransactionError,A as DateStub,oe as Document,W as DocumentReference,$ as EmbeddedSet,R as FaunaError,de as FetchClient,V as InvalidRequestError,it as LONG_MAX,ot as LONG_MIN,j as Module,ie as NamedDocument,te as NamedDocumentReference,w as NetworkError,ee as NodeHTTP2Client,ae as NullDocument,N as Page,k as ProtocolError,q as QueryCheckError,B as QueryRuntimeError,Y as QueryTimeoutError,l as ServiceError,J as ServiceInternalError,K as ServiceTimeoutError,H as SetIterator,Ce as StreamClient,I as StreamToken,D as TaggedTypeFormat,F as ThrottlingError,O as TimeStub,qe as endpoints,Le as fql,Fe as getDefaultHTTPClient,Me as isHTTPResponse,We as isStreamClient};
//# sourceMappingURL=index.js.map

@@ -0,1 +1,2 @@

import { HTTPStreamClient } from "./http-client";
import type { ValueFormat } from "./wire-protocol";

@@ -138,2 +139,37 @@ /**

/**
* Configuration for a streaming client. This typically comes from the `Client`
* instance configuration.
*/
export type StreamClientConfiguration = {
/**
* The underlying {@link HTTPStreamClient} that will execute the actual HTTP calls
*/
httpStreamClient: HTTPStreamClient;
/**
* Controls what Javascript type to deserialize {@link https://fqlx-beta--fauna-docs.netlify.app/fqlx/beta/reference/language/types#long | Fauna longs} to.
* @see {@link ClientConfiguration.long_type}
*/
long_type: "number" | "bigint";
/**
* Max attempts for retryable exceptions.
*/
max_attempts: number;
/**
* Max backoff between retries.
*/
max_backoff: number;
/**
* A secret for your Fauna DB, used to authorize your queries.
* @see https://docs.fauna.com/fauna/current/security/keys
*/
secret: string;
/**
* Indicates if stream should include "status" events, periodic events that
* update the client with the latest valid timestamp (in the event of a
* dropped connection) as well as metrics about about the cost of maintaining
* the stream other than the cost of the received events.
*/
status_events?: boolean;
};
/**
* A extensible set of endpoints for calling Fauna.

@@ -140,0 +176,0 @@ * @remarks Most clients will will not need to extend this set.

93

dist/client.d.ts

@@ -1,6 +0,6 @@

import { ClientConfiguration } from "./client-configuration";
import { ClientConfiguration, StreamClientConfiguration } from "./client-configuration";
import { type HTTPClient } from "./http-client";
import { Query } from "./query-builder";
import { EmbeddedSet, Page, SetIterator } from "./values";
import { type QueryOptions, type QuerySuccess, type QueryValue } from "./wire-protocol";
import { EmbeddedSet, Page, SetIterator, StreamToken } from "./values";
import { StreamEventData, StreamEventStatus, type QueryOptions, type QuerySuccess, type QueryValue } from "./wire-protocol";
/**

@@ -118,2 +118,89 @@ * Client for calling Fauna.

query<T extends QueryValue>(query: Query, options?: QueryOptions): Promise<QuerySuccess<T>>;
/**
* Initialize a streaming request to Fauna
* @param query - A string-encoded streaming token, or a {@link Query}
* @returns A {@link StreamClient} that which can be used to listen to a stream
* of events
*
* @example
* ```javascript
* const stream = client.stream(fql`MyCollection.all().toStream()`)
*
* try {
* for await (const event of stream) {
* switch (event.type) {
* case "update":
* case "add":
* case "remove":
* console.log("Stream update:", event);
* // ...
* break;
* }
* }
* } catch (error) {
* // An error will be handled here if Fauna returns a terminal, "error" event, or
* // if Fauna returns a non-200 response when trying to connect, or
* // if the max number of retries on network errors is reached.
*
* // ... handle fatal error
* };
* ```
*
* @example
* ```javascript
* const stream = client.stream(fql`MyCollection.all().toStream()`)
*
* stream.start(
* function onEvent(event) {
* switch (event.type) {
* case "update":
* case "add":
* case "remove":
* console.log("Stream update:", event);
* // ...
* break;
* }
* },
* function onError(error) {
* // An error will be handled here if Fauna returns a terminal, "error" event, or
* // if Fauna returns a non-200 response when trying to connect, or
* // if the max number of retries on network errors is reached.
*
* // ... handle fatal error
* }
* );
* ```
*/
stream<T extends QueryValue>(tokenOrQuery: StreamToken | Query, options?: Partial<StreamClientConfiguration>): StreamClient<T>;
}
/**
* A class to listen to Fauna streams.
*/
export declare class StreamClient<T extends QueryValue = any> {
#private;
/** Whether or not this stream has been closed */
closed: boolean;
/**
*
* @param query - A lambda that returns a promise for a {@link StreamToken}
* @param clientConfiguration - The {@link ClientConfiguration} to apply
* @param httpStreamClient - The underlying {@link HTTPStreamClient} that will
* execute the actual HTTP calls
* @example
* ```typescript
* const streamClient = client.stream(streamToken);
* ```
*/
constructor(token: StreamToken | (() => Promise<StreamToken>), clientConfiguration: StreamClientConfiguration);
/**
* A synchronous method to start listening to the stream and handle events
* using callbacks.
* @param onEvent - A callback function to handle each event
* @param onError - An Optional callback function to handle errors. If none is
* provided, error will not be handled, and the stream will simply end.
*/
start(onEvent: (event: StreamEventData<T> | StreamEventStatus) => void, onError?: (error: Error) => void): void;
[Symbol.asyncIterator](): AsyncGenerator<StreamEventData<T> | StreamEventStatus>;
close(): void;
get last_ts(): number | undefined;
}
/** following reference needed to include types for experimental fetch API in Node */
/// <reference lib="dom" />
import { HTTPClient, HTTPClientOptions, HTTPRequest, HTTPResponse } from "./http-client";
import { HTTPClient, HTTPClientOptions, HTTPRequest, HTTPResponse, HTTPStreamRequest, HTTPStreamClient, StreamAdapter } from "./http-client";
/**
* An implementation for {@link HTTPClient} that uses the native fetch API
*/
export declare class FetchClient implements HTTPClient {
export declare class FetchClient implements HTTPClient, HTTPStreamClient {
#private;

@@ -12,4 +12,6 @@ constructor({ url, fetch_keepalive }: HTTPClientOptions);

request({ data, headers: requestHeaders, method, client_timeout_ms, }: HTTPRequest): Promise<HTTPResponse>;
/** {@inheritDoc HTTPStreamClient.stream} */
stream({ data, headers: requestHeaders, method, }: HTTPStreamRequest): StreamAdapter;
/** {@inheritDoc HTTPClient.close} */
close(): void;
}

@@ -1,2 +0,2 @@

import { QueryRequest } from "../wire-protocol";
import { QueryRequest, StreamRequest } from "../wire-protocol";
/**

@@ -58,1 +58,34 @@ * An object representing an http request.

}
/**
* An object representing an http request.
* The {@link Client} provides this to the {@link HTTPStreamClient} implementation.
*/
export type HTTPStreamRequest = {
/** The encoded Fauna query to send */
data: StreamRequest;
/** Headers in object format */
headers: Record<string, string | undefined>;
/** HTTP method to use */
method: "POST";
};
/**
* A common interface for a StreamClient to operate a stream from any HTTPStreamClient
*/
export interface StreamAdapter {
read: AsyncGenerator<string>;
close: () => void;
}
/**
* An interface to provide implementation-specific, asyncronous http calls.
* This driver provides default implementations for common environments. Users
* can configure the {@link Client} to use custom implementations if desired.
*/
export interface HTTPStreamClient {
/**
* Makes an HTTP request and returns the response
* @param req - an {@link HTTPStreamRequest}
* @returns A Promise&lt;{@link HTTPResponse}&gt;
* @throws {@link NetworkError} on request timeout or other network issue.
*/
stream(req: HTTPStreamRequest): StreamAdapter;
}

@@ -1,6 +0,8 @@

import { FetchClient } from "./fetch-client";
import { NodeHTTP2Client } from "./node-http2-client";
import { HTTPClient, HTTPClientOptions, HTTPRequest, HTTPResponse } from "./http-client";
export declare const getDefaultHTTPClient: (options: HTTPClientOptions) => HTTPClient;
import { HTTPClient, HTTPClientOptions, HTTPResponse, HTTPStreamClient } from "./http-client";
export * from "./fetch-client";
export * from "./http-client";
export * from "./node-http2-client";
export declare const getDefaultHTTPClient: (options: HTTPClientOptions) => HTTPClient & HTTPStreamClient;
export declare const isHTTPResponse: (res: any) => res is HTTPResponse;
export { FetchClient, NodeHTTP2Client, HTTPClient, HTTPRequest, HTTPResponse };
export declare const isStreamClient: (client: Partial<HTTPStreamClient>) => client is HTTPStreamClient;
export declare const nodeHttp2IsSupported: () => boolean;

@@ -1,6 +0,6 @@

import { HTTPClient, HTTPClientOptions, HTTPRequest, HTTPResponse } from "./http-client";
import { HTTPClient, HTTPClientOptions, HTTPRequest, HTTPResponse, HTTPStreamClient, HTTPStreamRequest, StreamAdapter } from "./http-client";
/**
* An implementation for {@link HTTPClient} that uses the node http package
*/
export declare class NodeHTTP2Client implements HTTPClient {
export declare class NodeHTTP2Client implements HTTPClient, HTTPStreamClient {
#private;

@@ -16,2 +16,4 @@ private constructor();

request(req: HTTPRequest): Promise<HTTPResponse>;
/** {@inheritDoc HTTPStreamClient.stream} */
stream(req: HTTPStreamRequest): StreamAdapter;
/** {@inheritDoc HTTPClient.close} */

@@ -18,0 +20,0 @@ close(): void;

@@ -1,3 +0,3 @@

export { Client } from "./client";
export { endpoints, type ClientConfiguration, type Endpoints, } from "./client-configuration";
export { Client, StreamClient } from "./client";
export { endpoints, type ClientConfiguration, type Endpoints, type StreamClientConfiguration, } from "./client-configuration";
export { AbortError, AuthenticationError, AuthorizationError, ClientError, ClientClosedError, ContendedTransactionError, FaunaError, InvalidRequestError, NetworkError, ProtocolError, QueryCheckError, QueryRuntimeError, QueryTimeoutError, ServiceError, ServiceInternalError, ServiceTimeoutError, ThrottlingError, } from "./errors";

@@ -7,3 +7,3 @@ export { type Query, fql } from "./query-builder";

export { type QueryValueObject, type QueryValue, type QueryFailure, type QueryInfo, type QueryInterpolation, type QueryOptions, type QueryRequest, type QueryStats, type QuerySuccess, type Span, type ValueFragment, } from "./wire-protocol";
export { DateStub, Document, DocumentReference, type DocumentT, EmbeddedSet, Module, NamedDocument, NamedDocumentReference, NullDocument, Page, SetIterator, TimeStub, } from "./values";
export { FetchClient, getDefaultHTTPClient, isHTTPResponse, NodeHTTP2Client, type HTTPClient, type HTTPRequest, type HTTPResponse, } from "./http-client";
export { DateStub, Document, DocumentReference, EmbeddedSet, Module, NamedDocument, NamedDocumentReference, NullDocument, Page, SetIterator, StreamToken, TimeStub, type DocumentT, } from "./values";
export { FetchClient, getDefaultHTTPClient, isHTTPResponse, isStreamClient, NodeHTTP2Client, type HTTPClient, type HTTPRequest, type HTTPResponse, type HTTPStreamClient, type StreamAdapter, } from "./http-client";

@@ -84,2 +84,4 @@ "use strict";

SetIterator: () => SetIterator,
StreamClient: () => StreamClient,
StreamToken: () => StreamToken,
TaggedTypeFormat: () => TaggedTypeFormat,

@@ -91,3 +93,4 @@ ThrottlingError: () => ThrottlingError,

getDefaultHTTPClient: () => getDefaultHTTPClient,
isHTTPResponse: () => isHTTPResponse
isHTTPResponse: () => isHTTPResponse,
isStreamClient: () => isStreamClient
});

@@ -276,6 +279,8 @@ module.exports = __toCommonJS(src_exports);

var FetchClient = class {
#url;
#queryURL;
#streamURL;
#keepalive;
constructor({ url, fetch_keepalive }) {
this.#url = new URL("/query/1", url).toString();
this.#queryURL = new URL("/query/1", url).toString();
this.#streamURL = new URL("/stream/1", url).toString();
this.#keepalive = fetch_keepalive;

@@ -295,3 +300,3 @@ }

})() : AbortSignal.timeout(client_timeout_ms);
const response = await fetch(this.#url, {
const response = await fetch(this.#queryURL, {
method,

@@ -317,5 +322,75 @@ headers: { ...requestHeaders, "Content-Type": "application/json" },

}
stream({
data,
headers: requestHeaders,
method
}) {
const request = new Request(this.#streamURL, {
method,
headers: { ...requestHeaders, "Content-Type": "application/json" },
body: JSON.stringify(data),
keepalive: this.#keepalive
});
const abortController = new AbortController();
const options = {
signal: abortController.signal
};
async function* reader() {
const response = await fetch(request, options).catch((error) => {
throw new NetworkError(
"The network connection encountered a problem.",
{
cause: error
}
);
});
const status = response.status;
if (!(status >= 200 && status < 400)) {
const body2 = await response.json();
throw new ServiceError(body2, status);
}
const body = response.body;
if (!body) {
throw new Error("Response body is undefined.");
}
const reader2 = body.getReader();
for await (const line of readLines(reader2)) {
yield line;
}
}
return {
read: reader(),
close: () => {
abortController.abort("Stream closed by the client.");
}
};
}
close() {
}
};
async function* readLines(reader) {
const textDecoder = new TextDecoder();
let partOfLine = "";
for await (const chunk of readChunks(reader)) {
const chunkText = textDecoder.decode(chunk);
const chunkLines = (partOfLine + chunkText).split("\n");
for (let i = 0; i < chunkLines.length - 1; i++) {
yield chunkLines[i].trim();
}
partOfLine = chunkLines[chunkLines.length - 1];
}
if (partOfLine.trim() !== "") {
yield partOfLine;
}
}
async function* readChunks(reader) {
let done = false;
do {
const readResult = await reader.read();
if (readResult.value !== void 0) {
yield readResult.value;
}
done = readResult.done;
} while (!done);
}

@@ -329,3 +404,3 @@ // src/http-client/node-http2-client.ts

}
var _clients, _http2_session_idle_ms, _http2_max_streams, _url, _numberOfUsers, _session, _getClientKey, getClientKey_fn, _closeForAll, closeForAll_fn, _connect, connect_fn, _doRequest, doRequest_fn;
var _clients, _http2_session_idle_ms, _http2_max_streams, _url, _numberOfUsers, _session, _getClientKey, getClientKey_fn, _closeForAll, closeForAll_fn, _connect, connect_fn, _doRequest, doRequest_fn, _doStream, doStream_fn;
var _NodeHTTP2Client = class {

@@ -340,2 +415,3 @@ constructor({

__privateAdd(this, _doRequest);
__privateAdd(this, _doStream);
__privateAdd(this, _http2_session_idle_ms, void 0);

@@ -390,2 +466,5 @@ __privateAdd(this, _http2_max_streams, void 0);

}
stream(req) {
return __privateMethod(this, _doStream, doStream_fn).call(this, req);
}
close() {

@@ -480,2 +559,72 @@ if (this.isClosed()) {

};
_doStream = new WeakSet();
doStream_fn = function({
data: requestData,
headers: requestHeaders,
method
}) {
let resolveChunk;
let rejectChunk;
const setChunkPromise = () => new Promise((res, rej) => {
resolveChunk = res;
rejectChunk = rej;
});
let chunkPromise = setChunkPromise();
let req;
const onResponse = (http2ResponseHeaders) => {
const status = Number(
http2ResponseHeaders[http2.constants.HTTP2_HEADER_STATUS]
);
if (!(status >= 200 && status < 400)) {
let responseData = "";
req.on("data", (chunk) => {
responseData += chunk;
});
req.on("end", () => {
rejectChunk(new ServiceError(JSON.parse(responseData), status));
});
} else {
let partOfLine = "";
req.on("data", (chunk) => {
const chunkLines = (partOfLine + chunk).split("\n");
resolveChunk(chunkLines.map((s) => s.trim()).slice(0, -1));
chunkPromise = setChunkPromise();
partOfLine = chunkLines[chunkLines.length - 1];
});
req.on("end", () => {
resolveChunk([partOfLine]);
});
}
};
const self2 = this;
async function* reader() {
var _a;
const httpRequestHeaders = {
...requestHeaders,
[http2.constants.HTTP2_HEADER_PATH]: "/stream/1",
[http2.constants.HTTP2_HEADER_METHOD]: method
};
const session = __privateMethod(_a = self2, _connect, connect_fn).call(_a);
req = session.request(httpRequestHeaders).setEncoding("utf8").on("error", (error) => {
rejectChunk(error);
}).on("response", onResponse);
const body = JSON.stringify(requestData);
req.write(body, "utf8");
req.end();
while (true) {
const chunks = await chunkPromise;
for (const chunk of chunks) {
yield chunk;
}
}
}
return {
read: reader(),
close: () => {
if (req) {
req.close();
}
}
};
};
__privateAdd(NodeHTTP2Client, _getClientKey);

@@ -487,2 +636,5 @@ __privateAdd(NodeHTTP2Client, _clients, /* @__PURE__ */ new Map());

var isHTTPResponse = (res) => res instanceof Object && "body" in res && "headers" in res && "status" in res;
var isStreamClient = (client) => {
return "stream" in client && typeof client.stream === "function";
};
var nodeHttp2IsSupported = () => {

@@ -781,2 +933,10 @@ if (typeof process !== "undefined" && process && process.release?.name === "node") {

// src/values/stream.ts
var StreamToken = class {
token;
constructor(token) {
this.token = token;
}
};
// src/tagged-type.ts

@@ -840,2 +1000,4 @@ var TaggedTypeFormat = class {

return value["@object"];
} else if (value["@stream"]) {
return new StreamToken(value["@stream"]);
}

@@ -925,3 +1087,4 @@ return value;

);
}
},
streamToken: (value) => value.token
};

@@ -968,2 +1131,4 @@ var encode = (input) => {

return encodeMap["set"](input);
} else if (input instanceof StreamToken) {
return encodeMap["streamToken"](input);
} else {

@@ -1020,3 +1185,3 @@ return encodeMap["object"](input);

// src/util/package-version.ts
var packageVersion = "1.3.1";
var packageVersion = "1.4.0-beta.0";

@@ -1345,2 +1510,21 @@ // src/util/environment.ts

}
stream(tokenOrQuery, options) {
if (__privateGet(this, _isClosed)) {
throw new ClientClosedError(
"Your client is closed. No further requests can be issued."
);
}
const streamClient = __privateGet(this, _httpClient);
if (isStreamClient(streamClient)) {
const streamClientConfig = {
...__privateGet(this, _clientConfiguration),
httpStreamClient: streamClient,
...options
};
const tokenOrGetToken = tokenOrQuery instanceof Query2 ? () => this.query(tokenOrQuery).then((res) => res.data) : tokenOrQuery;
return new StreamClient(tokenOrGetToken, streamClientConfig);
} else {
throw new ClientError("Streaming is not supported by this client.");
}
}
};

@@ -1358,12 +1542,12 @@ var Client = _Client;

const backoffMs = Math.min(Math.random() * 2 ** attempt, maxBackoff) * 1e3;
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
attempt += 1;
return __privateMethod(this, _query, query_fn).call(this, queryInterpolation, options, attempt).catch((e) => {
if (e instanceof ThrottlingError && attempt < maxAttempts) {
return wait(backoffMs).then(
() => __privateMethod(this, _queryWithRetries, queryWithRetries_fn).call(this, queryInterpolation, options, attempt)
);
try {
return await __privateMethod(this, _query, query_fn).call(this, queryInterpolation, options, attempt);
} catch (error) {
if (error instanceof ThrottlingError && attempt < maxAttempts) {
await wait(backoffMs);
return __privateMethod(this, _queryWithRetries, queryWithRetries_fn).call(this, queryInterpolation, options, attempt);
}
throw e;
});
throw error;
}
};

@@ -1515,33 +1699,20 @@ _getError = new WeakSet();

setHeaders_fn = function(fromObject, headerObject) {
for (const entry of Object.entries(fromObject)) {
if ([
"format",
"query_timeout_ms",
"linearized",
"max_contention_retries",
"traceparent",
"typecheck",
"query_tags"
].includes(entry[0])) {
let headerValue;
let headerKey = `x-${entry[0].replaceAll("_", "-")}`;
if ("query_tags" === entry[0]) {
headerValue = Object.entries(entry[1]).map((tag) => tag.join("=")).join(",");
} else {
if (typeof entry[1] === "string") {
headerValue = entry[1];
} else {
headerValue = String(entry[1]);
}
}
if ("traceparent" === entry[0]) {
headerKey = entry[0];
}
headerObject[headerKey] = headerValue;
const setHeader = (header, value, transform = (v) => String(v)) => {
if (value !== void 0) {
headerObject[header] = transform(value);
}
}
if (headerObject["x-last-txn-ts"] === void 0 && __privateGet(this, _lastTxnTs) !== void 0) {
headerObject["x-last-txn-ts"] = __privateGet(this, _lastTxnTs);
}
headerObject["x-driver-env"] = __privateGet(_Client, _driverEnvHeader);
};
setHeader("x-format", fromObject.format);
setHeader("x-typecheck", fromObject.typecheck);
setHeader("x-query-timeout-ms", fromObject.query_timeout_ms);
setHeader("x-linearized", fromObject.linearized);
setHeader("x-max-contention-retries", fromObject.max_contention_retries);
setHeader("traceparent", fromObject.traceparent);
setHeader(
"x-query-tags",
fromObject.query_tags,
(tags) => Object.entries(tags).map((tag) => tag.join("=")).join(",")
);
setHeader("x-last-txn-ts", __privateGet(this, _lastTxnTs), (v) => v);
setHeader("x-driver-env", __privateGet(_Client, _driverEnvHeader));
};

@@ -1559,3 +1730,5 @@ _validateConfiguration = new WeakSet();

"fetch_keepalive",
"http2_max_streams"
"http2_max_streams",
"max_backoff",
"max_attempts"
];

@@ -1580,4 +1753,149 @@ required_options.forEach((option) => {

}
if (config.max_backoff <= 0) {
throw new RangeError(`'max_backoff' must be greater than zero.`);
}
if (config.max_attempts <= 0) {
throw new RangeError(`'max_attempts' must be greater than zero.`);
}
};
__privateAdd(Client, _driverEnvHeader, getDriverEnv());
var StreamClient = class {
closed = false;
#clientConfiguration;
#connectionAttempts = 0;
#query;
#last_ts;
#streamAdapter;
#streamToken;
constructor(token, clientConfiguration) {
if (token instanceof StreamToken) {
this.#query = () => Promise.resolve(token);
} else {
this.#query = token;
}
this.#clientConfiguration = clientConfiguration;
this.#validateConfiguration();
}
start(onEvent, onError) {
if (typeof onEvent !== "function") {
throw new TypeError(
`Expected a function as the 'onEvent' argument, but received ${typeof onEvent}. Please provide a valid function.`
);
}
if (onError && typeof onError !== "function") {
throw new TypeError(
`Expected a function as the 'onError' argument, but received ${typeof onError}. Please provide a valid function.`
);
}
const run = async () => {
try {
for await (const event of this) {
onEvent(event);
}
} catch (error) {
if (onError) {
onError(error);
}
}
};
run();
}
async *[Symbol.asyncIterator]() {
if (this.closed) {
throw new ClientError("The stream has been closed and cannot be reused.");
}
if (!this.#streamToken) {
this.#streamToken = await this.#query().then((maybeStreamToken) => {
if (!(maybeStreamToken instanceof StreamToken)) {
throw new ClientError(
`Error requesting a stream token. Expected a StreamToken as the query result, but received ${typeof maybeStreamToken}. Your query must return the result of '<Set>.toStream' or '<Set>.changesOn')
Query result: ${JSON.stringify(maybeStreamToken, null)}`
);
}
return maybeStreamToken;
});
}
this.#connectionAttempts = 1;
while (!this.closed) {
const backoffMs = Math.min(
Math.random() * 2 ** this.#connectionAttempts,
this.#clientConfiguration.max_backoff
) * 1e3;
try {
for await (const event of this.#startStream(this.#last_ts)) {
yield event;
}
} catch (error) {
if (error instanceof FaunaError || this.#connectionAttempts >= this.#clientConfiguration.max_attempts) {
this.close();
throw error;
}
this.#connectionAttempts += 1;
await wait(backoffMs);
}
}
}
close() {
if (this.#streamAdapter) {
this.#streamAdapter.close();
this.#streamAdapter = void 0;
}
this.closed = true;
}
get last_ts() {
return this.#last_ts;
}
async *#startStream(start_ts) {
const streamToken = this.#streamToken;
const headers = {
Authorization: `Bearer ${this.#clientConfiguration.secret}`
};
const streamAdapter = this.#clientConfiguration.httpStreamClient.stream({
data: { token: streamToken.token, start_ts },
headers,
method: "POST"
});
this.#streamAdapter = streamAdapter;
for await (const event of streamAdapter.read) {
const deserializedEvent = TaggedTypeFormat.decode(event, {
long_type: this.#clientConfiguration.long_type
});
if (deserializedEvent.type === "error") {
this.close();
throw new ServiceError(deserializedEvent, 400);
}
this.#last_ts = deserializedEvent.txn_ts;
if (deserializedEvent.type === "start") {
deserializedEvent.type = "status";
}
if (!this.#clientConfiguration.status_events && deserializedEvent.type === "status") {
continue;
}
yield deserializedEvent;
}
}
#validateConfiguration() {
const config = this.#clientConfiguration;
const required_options = [
"long_type",
"httpStreamClient",
"max_backoff",
"max_attempts",
"secret"
];
required_options.forEach((option) => {
if (config[option] === void 0) {
throw new TypeError(
`ClientConfiguration option '${option}' must be defined.`
);
}
});
if (config.max_backoff <= 0) {
throw new RangeError(`'max_backoff' must be greater than zero.`);
}
if (config.max_attempts <= 0) {
throw new RangeError(`'max_attempts' must be greater than zero.`);
}
}
};
var QUERY_CHECK_FAILURE_CODES = [

@@ -1590,2 +1908,5 @@ "invalid_function_definition",

];
function wait(ms) {
return new Promise((r) => setTimeout(r, ms));
}
// Annotate the CommonJS export names for ESM import in node:

@@ -1624,2 +1945,4 @@ 0 && (module.exports = {

SetIterator,
StreamClient,
StreamToken,
TaggedTypeFormat,

@@ -1631,4 +1954,5 @@ ThrottlingError,

getDefaultHTTPClient,
isHTTPResponse
isHTTPResponse,
isStreamClient
});
//# sourceMappingURL=index.js.map
/** The current package version. */
export declare const packageVersion = "1.3.1";
export declare const packageVersion = "1.4.0-beta.0";
export * from "./date-time";
export * from "./doc";
export * from "./set";
export * from "./stream";

@@ -1,2 +0,2 @@

import { DateStub, Document, DocumentReference, EmbeddedSet, Module, NamedDocument, NamedDocumentReference, NullDocument, Page, TimeStub } from "./values";
import { DateStub, Document, DocumentReference, EmbeddedSet, Module, NamedDocument, NamedDocumentReference, NullDocument, Page, StreamToken, TimeStub } from "./values";
/**

@@ -256,2 +256,22 @@ * A request to make to Fauna.

*/
export type QueryValue = null | string | number | bigint | boolean | QueryValueObject | Array<QueryValue> | DateStub | TimeStub | Module | Document | DocumentReference | NamedDocument | NamedDocumentReference | NullDocument | Page<QueryValue> | EmbeddedSet;
export type QueryValue = null | string | number | bigint | boolean | QueryValueObject | Array<QueryValue> | DateStub | TimeStub | Module | Document | DocumentReference | NamedDocument | NamedDocumentReference | NullDocument | Page<QueryValue> | EmbeddedSet | StreamToken;
export type StreamRequest = {
token: string;
start_ts?: number;
};
export type StreamEventType = "status" | "add" | "remove" | "update" | "error";
export type StreamEventStatus = {
type: "status";
txn_ts: number;
stats: QueryStats;
};
export type StreamEventData<T extends QueryValue> = {
type: "add" | "remove" | "update";
txn_ts: number;
stats: QueryStats;
data: T;
};
export type StreamEventError = {
type: "error";
} & QueryFailure;
export type StreamEvent<T extends QueryValue> = StreamEventStatus | StreamEventData<T> | StreamEventError;
{
"name": "fauna",
"version": "1.3.1",
"version": "1.4.0-beta.0",
"description": "A driver to query Fauna databases in browsers, Node.js, and other Javascript runtimes",

@@ -45,3 +45,3 @@ "homepage": "https://fauna.com",

"lint": "eslint -f unix \"src/**/*.{ts,tsx}\"",
"fauna-local": "docker start faunadb-local || docker run --rm -d --name faunadb-local -p 8443:8443 -p 8084:8084 fauna/faunadb",
"fauna-local": "docker start faunadb-local || docker run --rm -d --name faunadb-local -p 8443:8443 -p 8084:8084 --mount type=bind,source=\"$(pwd)\"/docker/feature-flags.json,target=/etc/feature-flag-periodic.d/feature-flags.json fauna/faunadb",
"fauna-local-alt-port": "docker start faunadb-local-alt-port || docker run --rm -d --name faunadb-local-alt-port -p 7443:8443 -p 7084:8084 fauna/faunadb",

@@ -48,0 +48,0 @@ "prepare": "husky install",

@@ -13,3 +13,3 @@ # The Official Javascript Driver for [Fauna](https://fauna.com).

- [A JavaScript driver for Fauna.](#a-javascript-driver-for-fauna)
- [The Official Javascript Driver for Fauna.](#the-official-javascript-driver-for-fauna)
- [Quick-Start](#quick-start)

@@ -27,2 +27,5 @@ - [Supported Runtimes](#supported-runtimes)

- [Client Configuration](#client-configuration)
- [Retry](#retry)
- [Max Attempts](#max-attempts)
- [Max Backoff](#max-backoff)
- [Timeouts](#timeouts)

@@ -34,2 +37,3 @@ - [Query Timeout](#query-timeout)

- [Query Statistics](#query-statistics)
- [Streaming](#streaming)
- [Contributing](#contributing)

@@ -408,2 +412,81 @@ - [Setting up this Repo](#setting-up-this-repo)

## Streaming
Obtain a stream token using a regular query with either the `toStream()` or `changesOn()` FQL methods on a Set.
```javascript
import { Client, fql } from "fauna"
const client = new Client({ secret: FAUNA_SECRET })
const response = await client.query(fql`
let set = MyCollection.all()
{
initialPage: set.pageSize(10),
streamToken: set.toStream()
}
`);
const { initialPage, streamToken } = response.data;
const stream = client.stream(streamToken)
```
The driver will take care of the initial request to convert to a stream if you provide a Query
```javascript
import { Client, fql } from "fauna"
const client = new Client({ secret: FAUNA_SECRET })
const stream = await client.stream(fql`MyCollection.all().changesOn(.field1, .field2)`)
```
There are two Two ways to initiate the stream:
1. Async Iterator
2. Callbacks
_Async Iterator example_
```javascript
try {
for await (const event of stream) {
switch (event.type) {
case "update":
case "add":
case "remove":
console.log("Stream event:", event);
// ...
break;
}
}
} catch (error) {
// An error will be handled here if Fauna returns a terminal, "error" event, or
// if Fauna returns a non-200 response when trying to connect, or
// if the max number of retries on network errors is reached.
// ... handle fatal error
}
```
_Callbacks example_
```javascript
stream.start(
function onEvent(event) {
switch (event.type) {
case "update":
case "add":
case "remove":
console.log("Stream event:", event);
// ...
break;
}
},
function onFatalError(error) {
// An error will be handled here if Fauna returns a terminal, "error" event, or
// if Fauna returns a non-200 response when trying to connect, or
// if the max number of retries on network errors is reached.
// ... handle fatal error
}
);
```
# Contributing

@@ -410,0 +493,0 @@

@@ -0,1 +1,2 @@

import { HTTPStreamClient } from "./http-client";
import type { ValueFormat } from "./wire-protocol";

@@ -159,2 +160,43 @@

/**
* Configuration for a streaming client. This typically comes from the `Client`
* instance configuration.
*/
export type StreamClientConfiguration = {
/**
* The underlying {@link HTTPStreamClient} that will execute the actual HTTP calls
*/
httpStreamClient: HTTPStreamClient;
/**
* Controls what Javascript type to deserialize {@link https://fqlx-beta--fauna-docs.netlify.app/fqlx/beta/reference/language/types#long | Fauna longs} to.
* @see {@link ClientConfiguration.long_type}
*/
long_type: "number" | "bigint";
/**
* Max attempts for retryable exceptions.
*/
max_attempts: number;
/**
* Max backoff between retries.
*/
max_backoff: number;
/**
* A secret for your Fauna DB, used to authorize your queries.
* @see https://docs.fauna.com/fauna/current/security/keys
*/
secret: string;
/**
* Indicates if stream should include "status" events, periodic events that
* update the client with the latest valid timestamp (in the event of a
* dropped connection) as well as metrics about about the cost of maintaining
* the stream other than the cost of the received events.
*/
status_events?: boolean;
};
/**
* A extensible set of endpoints for calling Fauna.

@@ -161,0 +203,0 @@ * @remarks Most clients will will not need to extend this set.

@@ -1,3 +0,7 @@

import { ClientConfiguration, endpoints } from "./client-configuration";
import {
ClientConfiguration,
StreamClientConfiguration,
endpoints,
} from "./client-configuration";
import {
AuthenticationError,

@@ -19,5 +23,9 @@ AuthorizationError,

InvalidRequestError,
FaunaError,
} from "./errors";
import {
HTTPStreamClient,
StreamAdapter,
getDefaultHTTPClient,
isStreamClient,
isHTTPResponse,

@@ -29,3 +37,3 @@ type HTTPClient,

import { getDriverEnv } from "./util/environment";
import { EmbeddedSet, Page, SetIterator } from "./values";
import { EmbeddedSet, Page, SetIterator, StreamToken } from "./values";
import {

@@ -35,2 +43,5 @@ isQueryFailure,

QueryInterpolation,
StreamEvent,
StreamEventData,
StreamEventStatus,
type QueryFailure,

@@ -86,3 +97,3 @@ type QueryOptions,

/** The underlying {@link HTTPClient} client. */
readonly #httpClient: HTTPClient;
readonly #httpClient: HTTPClient & Partial<HTTPStreamClient>;
/** The last transaction timestamp this client has seen */

@@ -271,2 +282,88 @@ #lastTxnTs?: number;

/**
* Initialize a streaming request to Fauna
* @param query - A string-encoded streaming token, or a {@link Query}
* @returns A {@link StreamClient} that which can be used to listen to a stream
* of events
*
* @example
* ```javascript
* const stream = client.stream(fql`MyCollection.all().toStream()`)
*
* try {
* for await (const event of stream) {
* switch (event.type) {
* case "update":
* case "add":
* case "remove":
* console.log("Stream update:", event);
* // ...
* break;
* }
* }
* } catch (error) {
* // An error will be handled here if Fauna returns a terminal, "error" event, or
* // if Fauna returns a non-200 response when trying to connect, or
* // if the max number of retries on network errors is reached.
*
* // ... handle fatal error
* };
* ```
*
* @example
* ```javascript
* const stream = client.stream(fql`MyCollection.all().toStream()`)
*
* stream.start(
* function onEvent(event) {
* switch (event.type) {
* case "update":
* case "add":
* case "remove":
* console.log("Stream update:", event);
* // ...
* break;
* }
* },
* function onError(error) {
* // An error will be handled here if Fauna returns a terminal, "error" event, or
* // if Fauna returns a non-200 response when trying to connect, or
* // if the max number of retries on network errors is reached.
*
* // ... handle fatal error
* }
* );
* ```
*/
// TODO: implement options
stream<T extends QueryValue>(
tokenOrQuery: StreamToken | Query,
options?: Partial<StreamClientConfiguration>
): StreamClient<T> {
if (this.#isClosed) {
throw new ClientClosedError(
"Your client is closed. No further requests can be issued."
);
}
const streamClient = this.#httpClient;
if (isStreamClient(streamClient)) {
const streamClientConfig: StreamClientConfiguration = {
...this.#clientConfiguration,
httpStreamClient: streamClient,
...options,
};
const tokenOrGetToken =
tokenOrQuery instanceof Query
? () => this.query<StreamToken>(tokenOrQuery).then((res) => res.data)
: tokenOrQuery;
return new StreamClient(tokenOrGetToken, streamClientConfig);
} else {
throw new ClientError("Streaming is not supported by this client.");
}
}
async #queryWithRetries<T extends QueryValue>(

@@ -285,12 +382,13 @@ queryInterpolation: string | QueryInterpolation,

const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));
attempt += 1;
return this.#query<T>(queryInterpolation, options, attempt).catch((e) => {
if (e instanceof ThrottlingError && attempt < maxAttempts) {
return wait(backoffMs).then(() =>
this.#queryWithRetries<T>(queryInterpolation, options, attempt)
);
try {
return await this.#query<T>(queryInterpolation, options, attempt);
} catch (error) {
if (error instanceof ThrottlingError && attempt < maxAttempts) {
await wait(backoffMs);
return this.#queryWithRetries<T>(queryInterpolation, options, attempt);
}
throw e;
});
throw error;
}
}

@@ -516,41 +614,25 @@

): void {
for (const entry of Object.entries(fromObject)) {
if (
[
"format",
"query_timeout_ms",
"linearized",
"max_contention_retries",
"traceparent",
"typecheck",
"query_tags",
].includes(entry[0])
) {
let headerValue: string;
let headerKey = `x-${entry[0].replaceAll("_", "-")}`;
if ("query_tags" === entry[0]) {
headerValue = Object.entries(entry[1])
.map((tag) => tag.join("="))
.join(",");
} else {
if (typeof entry[1] === "string") {
headerValue = entry[1];
} else {
headerValue = String(entry[1]);
}
}
if ("traceparent" === entry[0]) {
headerKey = entry[0];
}
headerObject[headerKey] = headerValue;
const setHeader = <V>(
header: string,
value: V | undefined,
transform: (v: V) => string | number = (v) => String(v)
) => {
if (value !== undefined) {
headerObject[header] = transform(value);
}
}
if (
headerObject["x-last-txn-ts"] === undefined &&
this.#lastTxnTs !== undefined
) {
headerObject["x-last-txn-ts"] = this.#lastTxnTs;
}
};
headerObject["x-driver-env"] = Client.#driverEnvHeader;
setHeader("x-format", fromObject.format);
setHeader("x-typecheck", fromObject.typecheck);
setHeader("x-query-timeout-ms", fromObject.query_timeout_ms);
setHeader("x-linearized", fromObject.linearized);
setHeader("x-max-contention-retries", fromObject.max_contention_retries);
setHeader("traceparent", fromObject.traceparent);
setHeader("x-query-tags", fromObject.query_tags, (tags) =>
Object.entries(tags)
.map((tag) => tag.join("="))
.join(",")
);
setHeader("x-last-txn-ts", this.#lastTxnTs, (v) => v); // x-last-txn-ts doesn't get stringified
setHeader("x-driver-env", Client.#driverEnvHeader);
}

@@ -570,2 +652,4 @@

"http2_max_streams",
"max_backoff",
"max_attempts",
];

@@ -593,5 +677,230 @@ required_options.forEach((option) => {

}
if (config.max_backoff <= 0) {
throw new RangeError(`'max_backoff' must be greater than zero.`);
}
if (config.max_attempts <= 0) {
throw new RangeError(`'max_attempts' must be greater than zero.`);
}
}
}
/**
* A class to listen to Fauna streams.
*/
export class StreamClient<T extends QueryValue = any> {
/** Whether or not this stream has been closed */
closed = false;
/** The stream client options */
#clientConfiguration: StreamClientConfiguration;
/** A tracker for the number of connection attempts */
#connectionAttempts = 0;
/** A lambda that returns a promise for a {@link StreamToken} */
#query: () => Promise<StreamToken>;
/** The last `txn_ts` value received from events */
#last_ts?: number;
/** A common interface to operate a stream from any HTTPStreamClient */
#streamAdapter?: StreamAdapter;
/** A saved copy of the StreamToken once received */
#streamToken?: StreamToken;
/**
*
* @param query - A lambda that returns a promise for a {@link StreamToken}
* @param clientConfiguration - The {@link ClientConfiguration} to apply
* @param httpStreamClient - The underlying {@link HTTPStreamClient} that will
* execute the actual HTTP calls
* @example
* ```typescript
* const streamClient = client.stream(streamToken);
* ```
*/
// TODO: implement stream-specific options
constructor(
token: StreamToken | (() => Promise<StreamToken>),
clientConfiguration: StreamClientConfiguration
) {
if (token instanceof StreamToken) {
this.#query = () => Promise.resolve(token);
} else {
this.#query = token;
}
this.#clientConfiguration = clientConfiguration;
this.#validateConfiguration();
}
/**
* A synchronous method to start listening to the stream and handle events
* using callbacks.
* @param onEvent - A callback function to handle each event
* @param onError - An Optional callback function to handle errors. If none is
* provided, error will not be handled, and the stream will simply end.
*/
start(
onEvent: (event: StreamEventData<T> | StreamEventStatus) => void,
onError?: (error: Error) => void
) {
if (typeof onEvent !== "function") {
throw new TypeError(
`Expected a function as the 'onEvent' argument, but received ${typeof onEvent}. Please provide a valid function.`
);
}
if (onError && typeof onError !== "function") {
throw new TypeError(
`Expected a function as the 'onError' argument, but received ${typeof onError}. Please provide a valid function.`
);
}
const run = async () => {
try {
for await (const event of this) {
onEvent(event);
}
} catch (error) {
if (onError) {
onError(error as Error);
}
}
};
run();
}
async *[Symbol.asyncIterator](): AsyncGenerator<
StreamEventData<T> | StreamEventStatus
> {
if (this.closed) {
throw new ClientError("The stream has been closed and cannot be reused.");
}
if (!this.#streamToken) {
this.#streamToken = await this.#query().then((maybeStreamToken) => {
if (!(maybeStreamToken instanceof StreamToken)) {
throw new ClientError(
`Error requesting a stream token. Expected a StreamToken as the query result, but received ${typeof maybeStreamToken}. Your query must return the result of '<Set>.toStream' or '<Set>.changesOn')\n` +
`Query result: ${JSON.stringify(maybeStreamToken, null)}`
);
}
return maybeStreamToken;
});
}
this.#connectionAttempts = 1;
while (!this.closed) {
const backoffMs =
Math.min(
Math.random() * 2 ** this.#connectionAttempts,
this.#clientConfiguration.max_backoff
) * 1_000;
try {
for await (const event of this.#startStream(this.#last_ts)) {
yield event;
}
} catch (error: any) {
if (
error instanceof FaunaError ||
this.#connectionAttempts >= this.#clientConfiguration.max_attempts
) {
// A terminal error from Fauna
this.close();
throw error;
}
this.#connectionAttempts += 1;
await wait(backoffMs);
}
}
}
close() {
if (this.#streamAdapter) {
this.#streamAdapter.close();
this.#streamAdapter = undefined;
}
this.closed = true;
}
get last_ts(): number | undefined {
return this.#last_ts;
}
async *#startStream(
start_ts?: number
): AsyncGenerator<StreamEventData<T> | StreamEventStatus> {
// Safety: This method must only be called after a stream token has been acquired
const streamToken = this.#streamToken as StreamToken;
const headers = {
Authorization: `Bearer ${this.#clientConfiguration.secret}`,
};
const streamAdapter = this.#clientConfiguration.httpStreamClient.stream({
data: { token: streamToken.token, start_ts },
headers,
method: "POST",
});
this.#streamAdapter = streamAdapter;
for await (const event of streamAdapter.read) {
// stream events are always tagged
const deserializedEvent: StreamEvent<T> = TaggedTypeFormat.decode(event, {
long_type: this.#clientConfiguration.long_type,
});
if (deserializedEvent.type === "error") {
// Errors sent from Fauna are assumed fatal
this.close();
// TODO: replace with appropriate class from existing error heirarchy
throw new ServiceError(deserializedEvent, 400);
}
this.#last_ts = deserializedEvent.txn_ts;
// TODO: remove this once all environments have updated the events to use "status" instead of "start"
if ((deserializedEvent.type as any) === "start") {
deserializedEvent.type = "status";
}
if (
!this.#clientConfiguration.status_events &&
deserializedEvent.type === "status"
) {
continue;
}
yield deserializedEvent;
}
}
#validateConfiguration() {
const config = this.#clientConfiguration;
const required_options: (keyof StreamClientConfiguration)[] = [
"long_type",
"httpStreamClient",
"max_backoff",
"max_attempts",
"secret",
];
required_options.forEach((option) => {
if (config[option] === undefined) {
throw new TypeError(
`ClientConfiguration option '${option}' must be defined.`
);
}
});
if (config.max_backoff <= 0) {
throw new RangeError(`'max_backoff' must be greater than zero.`);
}
if (config.max_attempts <= 0) {
throw new RangeError(`'max_attempts' must be greater than zero.`);
}
}
}
// Private types and constants for internal logic.

@@ -606,1 +915,5 @@

];
function wait(ms: number) {
return new Promise((r) => setTimeout(r, ms));
}
/** following reference needed to include types for experimental fetch API in Node */
/// <reference lib="dom" />
import { NetworkError } from "../errors";
import { NetworkError, ServiceError } from "../errors";
import {

@@ -10,2 +10,5 @@ HTTPClient,

HTTPResponse,
HTTPStreamRequest,
HTTPStreamClient,
StreamAdapter,
} from "./http-client";

@@ -16,8 +19,10 @@

*/
export class FetchClient implements HTTPClient {
#url: string;
export class FetchClient implements HTTPClient, HTTPStreamClient {
#queryURL: string;
#streamURL: string;
#keepalive: boolean;
constructor({ url, fetch_keepalive }: HTTPClientOptions) {
this.#url = new URL("/query/1", url).toString();
this.#queryURL = new URL("/query/1", url).toString();
this.#streamURL = new URL("/stream/1", url).toString();
this.#keepalive = fetch_keepalive;

@@ -43,3 +48,3 @@ }

const response = await fetch(this.#url, {
const response = await fetch(this.#queryURL, {
method,

@@ -70,2 +75,55 @@ headers: { ...requestHeaders, "Content-Type": "application/json" },

/** {@inheritDoc HTTPStreamClient.stream} */
stream({
data,
headers: requestHeaders,
method,
}: HTTPStreamRequest): StreamAdapter {
const request = new Request(this.#streamURL, {
method,
headers: { ...requestHeaders, "Content-Type": "application/json" },
body: JSON.stringify(data),
keepalive: this.#keepalive,
});
const abortController = new AbortController();
const options = {
signal: abortController.signal,
};
async function* reader() {
const response = await fetch(request, options).catch((error) => {
throw new NetworkError(
"The network connection encountered a problem.",
{
cause: error,
}
);
});
const status = response.status;
if (!(status >= 200 && status < 400)) {
const body = await response.json();
throw new ServiceError(body, status);
}
const body = response.body;
if (!body) {
throw new Error("Response body is undefined.");
}
const reader = body.getReader();
for await (const line of readLines(reader)) {
yield line;
}
}
return {
read: reader(),
close: () => {
abortController.abort("Stream closed by the client.");
},
};
}
/** {@inheritDoc HTTPClient.close} */

@@ -76,1 +134,41 @@ close() {

}
/**
* Get individual lines from the stream
*
* The stream may be broken into arbitrary chunks, but the events are delimited by a newline character.
*
* @param reader - The stream reader
*/
async function* readLines(reader: ReadableStreamDefaultReader<Uint8Array>) {
const textDecoder = new TextDecoder();
let partOfLine = "";
for await (const chunk of readChunks(reader)) {
const chunkText = textDecoder.decode(chunk);
const chunkLines = (partOfLine + chunkText).split("\n");
// Yield all complete lines
for (let i = 0; i < chunkLines.length - 1; i++) {
yield chunkLines[i].trim();
}
// Store the partial line
partOfLine = chunkLines[chunkLines.length - 1];
}
// Yield the remaining partial line if any
if (partOfLine.trim() !== "") {
yield partOfLine;
}
}
async function* readChunks(reader: ReadableStreamDefaultReader<Uint8Array>) {
let done = false;
do {
const readResult = await reader.read();
if (readResult.value !== undefined) {
yield readResult.value;
}
done = readResult.done;
} while (!done);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { Client } from "../client";
import { QueryRequest } from "../wire-protocol";
import { QueryRequest, StreamRequest } from "../wire-protocol";

@@ -68,1 +68,40 @@ /**

}
/**
* An object representing an http request.
* The {@link Client} provides this to the {@link HTTPStreamClient} implementation.
*/
export type HTTPStreamRequest = {
/** The encoded Fauna query to send */
// TODO: Allow type to be a QueryRequest once implemented by the db
data: StreamRequest;
/** Headers in object format */
headers: Record<string, string | undefined>;
/** HTTP method to use */
method: "POST";
};
/**
* A common interface for a StreamClient to operate a stream from any HTTPStreamClient
*/
export interface StreamAdapter {
read: AsyncGenerator<string>;
close: () => void;
}
/**
* An interface to provide implementation-specific, asyncronous http calls.
* This driver provides default implementations for common environments. Users
* can configure the {@link Client} to use custom implementations if desired.
*/
export interface HTTPStreamClient {
/**
* Makes an HTTP request and returns the response
* @param req - an {@link HTTPStreamRequest}
* @returns A Promise&lt;{@link HTTPResponse}&gt;
* @throws {@link NetworkError} on request timeout or other network issue.
*/
stream(req: HTTPStreamRequest): StreamAdapter;
}
import { FetchClient } from "./fetch-client";
import { NodeHTTP2Client } from "./node-http2-client";
import {
HTTPClient,
HTTPClientOptions,
HTTPRequest,
HTTPResponse,
HTTPStreamClient,
} from "./http-client";
import { NodeHTTP2Client } from "./node-http2-client";
export const getDefaultHTTPClient = (options: HTTPClientOptions): HTTPClient =>
export * from "./fetch-client";
export * from "./http-client";
export * from "./node-http2-client";
export const getDefaultHTTPClient = (
options: HTTPClientOptions
): HTTPClient & HTTPStreamClient =>
nodeHttp2IsSupported()

@@ -18,3 +24,9 @@ ? NodeHTTP2Client.getClient(options)

const nodeHttp2IsSupported = () => {
export const isStreamClient = (
client: Partial<HTTPStreamClient>
): client is HTTPStreamClient => {
return "stream" in client && typeof client.stream === "function";
};
export const nodeHttp2IsSupported = () => {
if (

@@ -34,3 +46,1 @@ typeof process !== "undefined" &&

};
export { FetchClient, NodeHTTP2Client, HTTPClient, HTTPRequest, HTTPResponse };

@@ -12,4 +12,7 @@ let http2: any;

HTTPResponse,
HTTPStreamClient,
HTTPStreamRequest,
StreamAdapter,
} from "./http-client";
import { NetworkError } from "../errors";
import { ServiceError, NetworkError } from "../errors";

@@ -26,3 +29,3 @@ // alias http2 types

*/
export class NodeHTTP2Client implements HTTPClient {
export class NodeHTTP2Client implements HTTPClient, HTTPStreamClient {
static #clients: Map<string, NodeHTTP2Client> = new Map();

@@ -112,2 +115,7 @@

/** {@inheritDoc HTTPStreamClient.stream} */
stream(req: HTTPStreamRequest): StreamAdapter {
return this.#doStream(req);
}
/** {@inheritDoc HTTPClient.close} */

@@ -176,3 +184,3 @@ close() {

// data chunks in the response
req.on("data", (chunk: any) => {
req.on("data", (chunk: string) => {
responseData += chunk;

@@ -220,2 +228,108 @@ });

}
/** {@inheritDoc HTTPStreamClient.stream} */
#doStream({
data: requestData,
headers: requestHeaders,
method,
}: HTTPStreamRequest): StreamAdapter {
let resolveChunk: (chunk: string[]) => void;
let rejectChunk: (reason: any) => void;
const setChunkPromise = () =>
new Promise<string[]>((res, rej) => {
resolveChunk = res;
rejectChunk = rej;
});
let chunkPromise = setChunkPromise();
let req: ClientHttp2Stream;
const onResponse = (
http2ResponseHeaders: IncomingHttpHeaders & IncomingHttpStatusHeader
) => {
const status = Number(
http2ResponseHeaders[http2.constants.HTTP2_HEADER_STATUS]
);
if (!(status >= 200 && status < 400)) {
// Get the error body and then throw an error
let responseData = "";
// append response data to the data string every time we receive new
// data chunks in the response
req.on("data", (chunk: string) => {
responseData += chunk;
});
// Once the response is finished, resolve the promise
// TODO: The Client contains the information for how to parse an error
// into the appropriate class, so lift this logic out of the HTTPClient.
req.on("end", () => {
rejectChunk(new ServiceError(JSON.parse(responseData), status));
});
} else {
let partOfLine = "";
// append response data to the data string every time we receive new
// data chunks in the response
req.on("data", (chunk: string) => {
const chunkLines = (partOfLine + chunk).split("\n");
// Yield all complete lines
resolveChunk(chunkLines.map((s) => s.trim()).slice(0, -1));
chunkPromise = setChunkPromise();
// Store the partial line
partOfLine = chunkLines[chunkLines.length - 1];
});
// Once the response is finished, resolve the promise
req.on("end", () => {
resolveChunk([partOfLine]);
});
}
};
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
async function* reader(): AsyncGenerator<string> {
const httpRequestHeaders: OutgoingHttpHeaders = {
...requestHeaders,
[http2.constants.HTTP2_HEADER_PATH]: "/stream/1",
[http2.constants.HTTP2_HEADER_METHOD]: method,
};
const session = self.#connect();
req = session
.request(httpRequestHeaders)
.setEncoding("utf8")
.on("error", (error: any) => {
rejectChunk(error);
})
.on("response", onResponse);
const body = JSON.stringify(requestData);
req.write(body, "utf8");
req.end();
while (true) {
const chunks = await chunkPromise;
for (const chunk of chunks) {
yield chunk;
}
}
}
return {
read: reader(),
close: () => {
if (req) {
req.close();
}
},
};
}
}

@@ -1,2 +0,2 @@

export { Client } from "./client";
export { Client, StreamClient } from "./client";
export {

@@ -6,2 +6,3 @@ endpoints,

type Endpoints,
type StreamClientConfiguration,
} from "./client-configuration";

@@ -46,3 +47,2 @@ export {

DocumentReference,
type DocumentT,
EmbeddedSet,

@@ -55,3 +55,5 @@ Module,

SetIterator,
StreamToken,
TimeStub,
type DocumentT,
} from "./values";

@@ -62,2 +64,3 @@ export {

isHTTPResponse,
isStreamClient,
NodeHTTP2Client,

@@ -67,2 +70,4 @@ type HTTPClient,

type HTTPResponse,
type HTTPStreamClient,
type StreamAdapter,
} from "./http-client";

@@ -13,2 +13,3 @@ import { ClientError } from "./errors";

EmbeddedSet,
StreamToken,
} from "./values";

@@ -99,2 +100,4 @@ import { QueryValueObject, QueryValue } from "./wire-protocol";

return value["@object"];
} else if (value["@stream"]) {
return new StreamToken(value["@stream"]);
}

@@ -214,2 +217,5 @@

},
// TODO: encode as a tagged value if provided as a query arg?
// streamToken: (value: StreamToken): TaggedStreamToken => ({ "@stream": value.token }),
streamToken: (value: StreamToken): string => value.token,
};

@@ -259,2 +265,4 @@

return encodeMap["set"](input);
} else if (input instanceof StreamToken) {
return encodeMap["streamToken"](input);
} else {

@@ -261,0 +269,0 @@ return encodeMap["object"](input);

//THIS FILE IS AUTOGENERATED. DO NOT EDIT. SEE .husky/pre-commit
/** The current package version. */
export const packageVersion = "1.3.1";
export const packageVersion = "1.4.0-beta.0";
export * from "./date-time";
export * from "./doc";
export * from "./set";
export * from "./stream";

@@ -13,2 +13,3 @@ // eslint-disable-next-line @typescript-eslint/no-unused-vars

Page,
StreamToken,
TimeStub,

@@ -320,2 +321,26 @@ } from "./values";

| Page<QueryValue>
| EmbeddedSet;
| EmbeddedSet
| StreamToken;
export type StreamRequest = {
token: string;
start_ts?: number;
};
export type StreamEventType = "status" | "add" | "remove" | "update" | "error";
export type StreamEventStatus = {
type: "status";
txn_ts: number;
stats: QueryStats;
};
export type StreamEventData<T extends QueryValue> = {
type: "add" | "remove" | "update";
txn_ts: number;
stats: QueryStats;
data: T;
};
export type StreamEventError = { type: "error" } & QueryFailure;
export type StreamEvent<T extends QueryValue> =
| StreamEventStatus
| StreamEventData<T>
| StreamEventError;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc