@electric-sql/client 1.4.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +83 -19
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +34 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.legacy-esm.js +83 -19
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +83 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +121 -20
- package/src/types.ts +10 -0
package/dist/cjs/index.d.cts
CHANGED
|
@@ -84,6 +84,16 @@ type SubsetParams = {
|
|
|
84
84
|
whereExpr?: SerializedExpression;
|
|
85
85
|
/** Structured ORDER BY clauses (preferred when available) */
|
|
86
86
|
orderByExpr?: SerializedOrderByClause[];
|
|
87
|
+
/**
|
|
88
|
+
* HTTP method to use for the request. Overrides `subsetMethod` from ShapeStreamOptions.
|
|
89
|
+
* - `GET` (default): Sends subset params as query parameters. May fail with 414 errors
|
|
90
|
+
* for large queries.
|
|
91
|
+
* - `POST`: Sends subset params in request body as JSON. Recommended to avoid URL
|
|
92
|
+
* length limits with large WHERE clauses or many parameters.
|
|
93
|
+
*
|
|
94
|
+
* In Electric 2.0, GET will be deprecated and only POST will be supported.
|
|
95
|
+
*/
|
|
96
|
+
method?: `GET` | `POST`;
|
|
87
97
|
};
|
|
88
98
|
type ControlMessage = {
|
|
89
99
|
headers: (Header & {
|
|
@@ -629,6 +639,26 @@ interface ShapeStreamOptions<T = never> {
|
|
|
629
639
|
* ```
|
|
630
640
|
*/
|
|
631
641
|
onError?: ShapeStreamErrorHandler;
|
|
642
|
+
/**
|
|
643
|
+
* HTTP method to use for subset snapshot requests (`requestSnapshot`/`fetchSnapshot`).
|
|
644
|
+
*
|
|
645
|
+
* - `'GET'` (default): Sends subset params as URL query parameters. May fail with
|
|
646
|
+
* HTTP 414 errors for large queries with many parameters.
|
|
647
|
+
* - `'POST'`: Sends subset params in request body as JSON. Recommended for queries
|
|
648
|
+
* with large parameter lists (e.g., `WHERE id = ANY($1)` with hundreds of IDs).
|
|
649
|
+
*
|
|
650
|
+
* This can be overridden per-request by passing `method` in the subset params.
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```typescript
|
|
654
|
+
* const stream = new ShapeStream({
|
|
655
|
+
* url: 'http://localhost:3000/v1/shape',
|
|
656
|
+
* params: { table: 'items' },
|
|
657
|
+
* subsetMethod: 'POST', // Use POST for all subset requests
|
|
658
|
+
* })
|
|
659
|
+
* ```
|
|
660
|
+
*/
|
|
661
|
+
subsetMethod?: `GET` | `POST`;
|
|
632
662
|
}
|
|
633
663
|
interface ShapeStreamInterface<T extends Row<unknown> = Row> {
|
|
634
664
|
subscribe(callback: (messages: Message<T>[]) => MaybePromise<void> | {
|
|
@@ -748,6 +778,10 @@ declare class ShapeStream<T extends Row<unknown> = Row> implements ShapeStreamIn
|
|
|
748
778
|
* Fetch a snapshot for subset of data.
|
|
749
779
|
* Returns the metadata and the data, but does not inject it into the subscribed data stream.
|
|
750
780
|
*
|
|
781
|
+
* By default, uses GET to send subset parameters as query parameters. This may hit URL length
|
|
782
|
+
* limits (HTTP 414) with large WHERE clauses or many parameters. Set `method: 'POST'` or use
|
|
783
|
+
* `subsetMethod: 'POST'` on the stream to send parameters in the request body instead.
|
|
784
|
+
*
|
|
751
785
|
* @param opts - The options for the snapshot request.
|
|
752
786
|
* @returns The metadata and the data for the snapshot.
|
|
753
787
|
*/
|
package/dist/index.browser.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var Ts=Object.defineProperty,
|
|
1
|
+
var Ts=Object.defineProperty,Ps=Object.defineProperties;var Ms=Object.getOwnPropertyDescriptors;var Qe=Object.getOwnPropertySymbols;var Vt=Object.prototype.hasOwnProperty,Wt=Object.prototype.propertyIsEnumerable;var Kt=r=>{throw TypeError(r)};var Yt=(r,e,t)=>e in r?Ts(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,E=(r,e)=>{for(var t in e||(e={}))Vt.call(e,t)&&Yt(r,t,e[t]);if(Qe)for(var t of Qe(e))Wt.call(e,t)&&Yt(r,t,e[t]);return r},re=(r,e)=>Ps(r,Ms(e));var Qt=(r,e)=>{var t={};for(var s in r)Vt.call(r,s)&&e.indexOf(s)<0&&(t[s]=r[s]);if(r!=null&&Qe)for(var s of Qe(r))e.indexOf(s)<0&&Wt.call(r,s)&&(t[s]=r[s]);return t};var gt=(r,e,t)=>e.has(r)||Kt("Cannot "+t);var n=(r,e,t)=>(gt(r,e,"read from private field"),t?t.call(r):e.get(r)),u=(r,e,t)=>e.has(r)?Kt("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),c=(r,e,t,s)=>(gt(r,e,"write to private field"),s?s.call(r,t):e.set(r,t),t),p=(r,e,t)=>(gt(r,e,"access private method"),t);var ke=(r,e,t,s)=>({set _(i){c(r,e,i,t)},get _(){return n(r,e,s)}});var A=class r extends Error{constructor(t,s,i,o,a,h){super(h||`HTTP Error ${t} at ${a}: ${s!=null?s:JSON.stringify(i)}`);this.url=a;this.name="FetchError",this.status=t,this.text=s,this.json=i,this.headers=o}static async fromResponse(t,s){let i=t.status,o=Object.fromEntries([...t.headers.entries()]),a,h,d=t.headers.get("content-type");return t.bodyUsed||(d&&d.includes("application/json")?h=await t.json():a=await t.text()),new r(i,a,h,o,s)}},D=class extends Error{constructor(){super("Fetch with backoff aborted"),this.name="FetchBackoffAbortError"}};var Ge=class extends Error{constructor(){super("Invalid shape options: missing required url parameter"),this.name="MissingShapeUrlError"}},ze=class extends Error{constructor(){super("Invalid signal option. It must be an instance of AbortSignal."),this.name="InvalidSignalError"}},Je=class extends Error{constructor(){super("shapeHandle is required if this isn't an initial fetch (i.e. offset > -1)"),this.name="MissingShapeHandleError"}},Xe=class extends Error{constructor(e){super(`Cannot use reserved Electric parameter names in custom params: ${e.join(", ")}`),this.name="ReservedParamError"}},Ze=class extends Error{constructor(e){super(`Column "${e!=null?e:"unknown"}" does not allow NULL values`),this.name="ParserNullValueError"}};var ne=class extends Error{constructor(e,t){let s=`The response for the shape request to ${e} didn't include the following required headers:
|
|
2
2
|
`;t.forEach(i=>{s+=`- ${i}
|
|
3
3
|
`}),s+=`
|
|
4
4
|
This is often due to a proxy not setting CORS correctly so that all Electric headers can be read by the client.`,s+=`
|
|
5
|
-
For more information visit the troubleshooting guide: /docs/guides/troubleshooting/missing-headers`,super(s)}},Me=class extends Error{constructor(e){super(e),this.name="StaleCacheError"}};var Je=r=>Number(r),vs=r=>r==="true"||r==="t",Ms=r=>BigInt(r),zt=r=>JSON.parse(r),Cs=r=>r,ks={int2:Je,int4:Je,int8:Ms,bool:vs,float4:Je,float8:Je,json:zt,jsonb:zt};function Us(r,e){let t=0,s=null,i="",o=!1,a=0,h;function d(l,g,S){let _=l.slice(g,S);return _=_==="NULL"?null:_,e?e(_):_}function m(l){let g=[];for(;t<l.length;t++){if(s=l[t],o)s==="\\"?i+=l[++t]:s==='"'?(g.push(e?e(i):i),i="",o=l[t+1]==='"',a=t+2):i+=s;else if(s==='"')o=!0;else if(s==="{")a=++t,g.push(m(l));else if(s==="}"){o=!1,a<t&&g.push(d(l,a,t)),a=t+1;break}else s===","&&h!=="}"&&h!=='"'&&(g.push(d(l,a,t)),a=t+1);h=s}return a<t&&g.push(g.push(d(l,a,t+1))),g}return m(r)[0]}var Xe=class{constructor(e,t){this.parser=E(E({},ks),e),this.transformer=t}parse(e,t){return JSON.parse(e,(s,i)=>(s==="value"||s==="old_value")&&typeof i=="object"&&i!==null?this.transformMessageValue(i,t):i)}parseSnapshotData(e,t){return e.map(s=>{let i=s;return i.value&&typeof i.value=="object"&&i.value!==null&&(i.value=this.transformMessageValue(i.value,t)),i.old_value&&typeof i.old_value=="object"&&i.old_value!==null&&(i.old_value=this.transformMessageValue(i.old_value,t)),i})}transformMessageValue(e,t){let s=e;return Object.keys(s).forEach(i=>{s[i]=this.parseRow(i,s[i],t)}),this.transformer?this.transformer(s):s}parseRow(e,t,s){var g;let i=s[e];if(!i)return t;let l=i,{type:o,dims:a}=l,h=Kt(l,["type","dims"]),d=(g=this.parser[o])!=null?g:Cs,m=Gt(d,i,e);return a&&a>0?Gt((_,y)=>Us(_,m),i,e)(t):m(t,h)}};function Gt(r,e,t){var i;let s=!((i=e.not_null)!=null&&i);return o=>{if(o===null){if(!s)throw new Ge(t!=null?t:"unknown");return null}return r(o,e)}}function Ce(r){return`"${r.replace(/"/g,'""')}"`}function mt(r){var h,d,m,l;let e=(d=(h=r.match(/^_+/))==null?void 0:h[0])!=null?d:"",t=r.slice(e.length),s=(l=(m=t.match(/_+$/))==null?void 0:m[0])!=null?l:"",a=(s?t.slice(0,t.length-s.length):t).toLowerCase().replace(/_+([a-z])/g,(g,S)=>S.toUpperCase());return e+a+s}function Jt(r){return r.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()}function Xt(r){let e={};for(let[t,s]of Object.entries(r))e[s]=t;return{decode:t=>{var s;return(s=r[t])!=null?s:t},encode:t=>{var s;return(s=e[t])!=null?s:t}}}function Ze(r,e){if(!r||!e)return r!=null?r:"";let t=new Set(["SELECT","FROM","WHERE","AND","OR","NOT","IN","IS","NULL","NULLS","FIRST","LAST","TRUE","FALSE","LIKE","ILIKE","BETWEEN","ASC","DESC","LIMIT","OFFSET","ORDER","BY","GROUP","HAVING","DISTINCT","AS","ON","JOIN","LEFT","RIGHT","INNER","OUTER","CROSS","CASE","WHEN","THEN","ELSE","END","CAST","LOWER","UPPER","COALESCE","NULLIF"]),s=[],i=0;for(;i<r.length;){let h=r[i];if(h==="'"||h==='"'){let d=i,m=h;for(i++;i<r.length;)if(r[i]===m)if(r[i+1]===m)i+=2;else{i++;break}else i++;s.push({start:d,end:i})}else i++}let o=h=>s.some(d=>h>=d.start&&h<d.end),a=new RegExp("(?<![a-zA-Z0-9_])([a-zA-Z_][a-zA-Z0-9_]*)(?![a-zA-Z0-9_])","g");return r.replace(a,(h,d,m)=>o(m)||t.has(h.toUpperCase())||h.startsWith("$")?h:e(h))}function Os(r){if(r){let e={};for(let t of Object.keys(r))e[t]=mt(t);return Xt(e)}return{decode:e=>mt(e),encode:e=>Jt(e)}}function he(r){return"key"in r}function et(r){return!he(r)}function gt(r){return et(r)&&r.headers.control==="up-to-date"}function Zt(r){if(r.headers.control!="up-to-date")return;let e=r.headers.global_last_seen_lsn;return e?`${e}_0`:void 0}function Et(r,e){let t=BigInt(r),s=BigInt(e.xmin),i=BigInt(e.xmax),o=e.xip_list.map(BigInt);return t<s||t<i&&!o.includes(t)}var es="electric-cursor",ke="electric-handle",tt="electric-offset",St="electric-schema",ts="electric-up-to-date",yt="columns",st="cursor",Ue="expired_handle",le="handle",H="live",de="offset",ss="table",rs="where",ns="replica",is="params",as="experimental_live_sse",Rt="live_sse",bt="force-disconnect-and-refresh",At="pause-stream",_t="log",ue="subset__where",Oe="subset__limit",Le="subset__offset",fe="subset__order_by",De="subset__params",xt="subset__where_expr",Tt="subset__order_by_expr",rt="cache-buster",wt=[H,Rt,le,de,st,Ue,_t,ue,Oe,Le,fe,De,xt,Tt,rt];var Ls=[429],it={initialDelay:100,maxDelay:6e4,multiplier:1.3,maxRetries:1/0};function Ds(r){if(!r)return 0;let e=Number(r);if(Number.isFinite(e)&&e>0)return e*1e3;let t=Date.parse(r);if(!isNaN(t)){let s=t-Date.now();return Math.max(0,Math.min(s,36e5))}return 0}function os(r,e=it){let{initialDelay:t,maxDelay:s,multiplier:i,debug:o=!1,onFailedAttempt:a,maxRetries:h=1/0}=e;return async(...d)=>{var _;let m=d[0],l=d[1],g=t,S=0;for(;;)try{let y=await r(...d);if(y.ok)return y;throw await x.fromResponse(y,m.toString())}catch(y){if(a==null||a(),(_=l==null?void 0:l.signal)!=null&&_.aborted)throw new D;if(y instanceof x&&!Ls.includes(y.status)&&y.status>=400&&y.status<500)throw y;{if(S++,S>h)throw o&&console.log(`Max retries reached (${S}/${h}), giving up`),y;let O=y instanceof x&&y.headers?Ds(y.headers["retry-after"]):0,b=Math.random()*g,L=Math.min(b,s),V=Math.max(O,L);if(o){let Pe=O>0?"server+client":"client";console.log(`Retry attempt #${S} after ${V}ms (${Pe}, serverMin=${O}ms, clientBackoff=${L}ms)`)}await new Promise(Pe=>setTimeout(Pe,V)),g=Math.min(g*i,s)}}}}var Hs=[201,204,205];function cs(r){return async(...e)=>{var i,o;let t=e[0],s=await r(...e);try{if(s.status<200||Hs.includes(s.status))return s;let a=await s.text();return new Response(a,s)}catch(a){throw(o=(i=e[1])==null?void 0:i.signal)!=null&&o.aborted?new D:new x(s.status,void 0,void 0,Object.fromEntries([...s.headers.entries()]),t.toString(),a instanceof Error?a.message:typeof a=="string"?a:"failed to read body")}}}var Is={maxChunksToPrefetch:2};function hs(r,e=Is){let{maxChunksToPrefetch:t}=e,s;return async(...o)=>{let a=o[0].toString(),h=s==null?void 0:s.consume(...o);if(h)return h;s==null||s.abort(),s=void 0;let d=await r(...o),m=vt(a,d);return m&&(s=new Pt({fetchClient:r,maxPrefetchedRequests:t,url:m,requestInit:o[1]})),d}}var Ns=["electric-offset","electric-handle"],Bs=["electric-cursor"],Fs=["electric-schema"];function ls(r){return async(...e)=>{let t=await r(...e);if(t.ok){let s=t.headers,i=[],o=l=>i.push(...l.filter(g=>!s.has(g))),h=e[0].toString(),d=new URL(h);if([ue,De,Oe,Le,fe].some(l=>d.searchParams.has(l)))return t;if(o(Ns),d.searchParams.get(H)==="true"&&o(Bs),(!d.searchParams.has(H)||d.searchParams.get(H)==="false")&&o(Fs),i.length>0)throw new re(h,i)}return t}}var He,Ie,M,ne,I,pe,nt,Pt=class{constructor(e){u(this,pe);u(this,He);u(this,Ie);u(this,M,new Map);u(this,ne);u(this,I);var t;c(this,He,(t=e.fetchClient)!=null?t:(...s)=>fetch(...s)),c(this,Ie,e.maxPrefetchedRequests),c(this,ne,e.url.toString()),c(this,I,n(this,ne)),p(this,pe,nt).call(this,e.url,e.requestInit)}abort(){n(this,M).forEach(([e,t])=>t.abort()),n(this,M).clear()}consume(...e){let t=e[0].toString(),s=n(this,M).get(t);if(!s||t!==n(this,ne))return;let[i,o]=s;if(o.signal.aborted){n(this,M).delete(t);return}return n(this,M).delete(t),i.then(a=>{let h=vt(t,a);c(this,ne,h),n(this,I)&&!n(this,M).has(n(this,I))&&p(this,pe,nt).call(this,n(this,I),e[1])}).catch(()=>{}),i}};He=new WeakMap,Ie=new WeakMap,M=new WeakMap,ne=new WeakMap,I=new WeakMap,pe=new WeakSet,nt=function(...e){var i,o;let t=e[0].toString();if(n(this,M).size>=n(this,Ie))return;let s=new AbortController;try{let{signal:a,cleanup:h}=qs(s,(i=e[1])==null?void 0:i.signal),d=n(this,He).call(this,t,ce(E({},(o=e[1])!=null?o:{}),{signal:a}));n(this,M).set(t,[d,s]),d.then(m=>{if(!m.ok||s.signal.aborted)return;let l=vt(t,m);if(!l||l===t){c(this,I,void 0);return}return c(this,I,l),p(this,pe,nt).call(this,l,e[1])}).catch(()=>{}).finally(h)}catch(a){}};function vt(r,e){let t=e.headers.get(ke),s=e.headers.get(tt),i=e.headers.has(ts);if(!t||!s||i)return;let o=new URL(r);if(o.searchParams.has(H))return;let a=o.searchParams.get(Ue);if(a&&t===a){console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${t}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Skipping prefetch to prevent infinite 409 loop.`);return}return o.searchParams.set(le,t),o.searchParams.set(de,s),o.searchParams.sort(),o.toString()}function qs(r,e){let t=$s;if(e)if(e.aborted)r.abort();else{let s=()=>r.abort();e.addEventListener("abort",s,{once:!0,signal:r.signal}),t=()=>e.removeEventListener("abort",s)}return{signal:r.signal,cleanup:t}}function $s(){}function at(r,e){switch(r.type){case"ref":{let t=e?e(r.column):r.column;return Ce(t)}case"val":return`$${r.paramIndex}`;case"func":return js(r,e);default:{let t=r;throw new Error(`Unknown expression type: ${JSON.stringify(t)}`)}}}function js(r,e){let t=r.args.map(s=>at(s,e));switch(r.name){case"eq":return`${t[0]} = ${t[1]}`;case"gt":return`${t[0]} > ${t[1]}`;case"gte":return`${t[0]} >= ${t[1]}`;case"lt":return`${t[0]} < ${t[1]}`;case"lte":return`${t[0]} <= ${t[1]}`;case"and":return t.map(s=>`(${s})`).join(" AND ");case"or":return t.map(s=>`(${s})`).join(" OR ");case"not":return`NOT (${t[0]})`;case"in":return`${t[0]} = ANY(${t[1]})`;case"like":return`${t[0]} LIKE ${t[1]}`;case"ilike":return`${t[0]} ILIKE ${t[1]}`;case"isNull":case"isUndefined":return`${t[0]} IS NULL`;case"upper":return`UPPER(${t[0]})`;case"lower":return`LOWER(${t[0]})`;case"length":return`LENGTH(${t[0]})`;case"concat":return`CONCAT(${t.join(", ")})`;case"coalesce":return`COALESCE(${t.join(", ")})`;default:throw new Error(`Unknown function: ${r.name}`)}}function Mt(r,e){return r.map(t=>{let s=e?e(t.column):t.column,i=Ce(s);return t.direction==="desc"&&(i+=" DESC"),t.nulls==="first"&&(i+=" NULLS FIRST"),t.nulls==="last"&&(i+=" NULLS LAST"),i}).join(", ")}import{fetchEventSource as Ys}from"@microsoft/fetch-event-source";var Ct=class{constructor(){this.data={};this.max=250;this.storageKey="electric_expired_shapes";this.load()}getExpiredHandle(e){let t=this.data[e];return t?(t.lastUsed=Date.now(),this.save(),t.expiredHandle):null}markExpired(e,t){this.data[e]={expiredHandle:t,lastUsed:Date.now()};let s=Object.keys(this.data);if(s.length>this.max){let i=s.reduce((o,a)=>this.data[a].lastUsed<this.data[o].lastUsed?a:o);delete this.data[i]}this.save()}save(){if(typeof localStorage!="undefined")try{localStorage.setItem(this.storageKey,JSON.stringify(this.data))}catch(e){}}load(){if(typeof localStorage!="undefined")try{let e=localStorage.getItem(this.storageKey);e&&(this.data=JSON.parse(e))}catch(e){this.data={}}}clear(){this.data={},this.save()}},ot=new Ct;var kt=class{constructor(){this.data={};this.storageKey="electric_up_to_date_tracker";this.cacheTTL=6e4;this.maxEntries=250;this.writeThrottleMs=6e4;this.lastWriteTime=0;this.load(),this.cleanup()}recordUpToDate(e,t){this.data[e]={timestamp:Date.now(),cursor:t};let s=Object.keys(this.data);if(s.length>this.maxEntries){let i=s.reduce((o,a)=>this.data[a].timestamp<this.data[o].timestamp?a:o);delete this.data[i]}this.scheduleSave()}scheduleSave(){let e=Date.now(),t=e-this.lastWriteTime;if(t>=this.writeThrottleMs)this.lastWriteTime=e,this.save();else if(!this.pendingSaveTimer){let s=this.writeThrottleMs-t;this.pendingSaveTimer=setTimeout(()=>{this.lastWriteTime=Date.now(),this.pendingSaveTimer=void 0,this.save()},s)}}shouldEnterReplayMode(e){let t=this.data[e];return!t||Date.now()-t.timestamp>=this.cacheTTL?null:t.cursor}cleanup(){let e=Date.now(),t=Object.keys(this.data),s=!1;for(let i of t)e-this.data[i].timestamp>this.cacheTTL&&(delete this.data[i],s=!0);s&&this.save()}save(){if(typeof localStorage!="undefined")try{localStorage.setItem(this.storageKey,JSON.stringify(this.data))}catch(e){}}load(){if(typeof localStorage!="undefined")try{let e=localStorage.getItem(this.storageKey);e&&(this.data=JSON.parse(e))}catch(e){this.data={}}}clear(){this.data={},this.pendingSaveTimer&&(clearTimeout(this.pendingSaveTimer),this.pendingSaveTimer=void 0),this.save()}},Ut=new kt;var ct=class{constructor(){this.activeSnapshots=new Map;this.xmaxSnapshots=new Map;this.snapshotsByDatabaseLsn=new Map}addSnapshot(e,t){var o,a,h,d;this.activeSnapshots.set(e.snapshot_mark,{xmin:BigInt(e.xmin),xmax:BigInt(e.xmax),xip_list:e.xip_list.map(BigInt),keys:t});let s=(a=(o=this.xmaxSnapshots.get(BigInt(e.xmax)))==null?void 0:o.add(e.snapshot_mark))!=null?a:new Set([e.snapshot_mark]);this.xmaxSnapshots.set(BigInt(e.xmax),s);let i=(d=(h=this.snapshotsByDatabaseLsn.get(BigInt(e.database_lsn)))==null?void 0:h.add(e.snapshot_mark))!=null?d:new Set([e.snapshot_mark]);this.snapshotsByDatabaseLsn.set(BigInt(e.database_lsn),i)}removeSnapshot(e){this.activeSnapshots.delete(e)}shouldRejectMessage(e){let t=e.headers.txids||[];if(t.length===0)return!1;let s=Math.max(...t);for(let[i,o]of this.xmaxSnapshots.entries())if(s>=i)for(let a of o)this.removeSnapshot(a);return[...this.activeSnapshots.values()].some(i=>i.keys.has(e.key)&&Et(s,i))}lastSeenUpdate(e){for(let[t,s]of this.snapshotsByDatabaseLsn.entries())if(t<=e)for(let i of s)this.removeSnapshot(i)}};var Vs=new Set([st,le,H,de,rt]);async function qt(r){return typeof r=="function"?r():r}async function Ws(r){let e=Object.entries(r),t=await Promise.all(e.map(async([s,i])=>{if(i===void 0)return[s,void 0];let o=await qt(i);return[s,Array.isArray(o)?o.join(","):o]}));return Object.fromEntries(t.filter(([s,i])=>i!==void 0))}async function Qs(r){if(!r)return{};let e=Object.entries(r),t=await Promise.all(e.map(async([s,i])=>[s,await qt(i)]));return Object.fromEntries(t)}function Ne(r){let e=new URL(r.origin+r.pathname);for(let[t,s]of r.searchParams)wt.includes(t)||e.searchParams.set(t,s);return e.searchParams.sort(),e.toString()}var ge,Ee,Se,ie,W,U,A,N,B,Q,v,ae,C,T,K,F,ye,k,oe,q,Re,z,be,Fe,G,$,Ae,J,j,qe,$e,X,lt,_e,dt,ut,je,Y,Z,xe,f,Lt,Be,me,Dt,us,Ht,ht,fs,ps,ms,It,Nt,gs,Es,Bt,Ft,Ss,ys,Ot=class{constructor(e){u(this,f);u(this,ge,null);u(this,Ee);u(this,Se);u(this,ie);u(this,W,new Map);u(this,U,!1);u(this,A,"active");u(this,N);u(this,B);u(this,Q);u(this,v,!1);u(this,ae,!0);u(this,C,!1);u(this,T);u(this,K);u(this,F);u(this,ye);u(this,k);u(this,oe,!1);u(this,q);u(this,Re);u(this,z);u(this,be,Promise.resolve([]));u(this,Fe,new ct);u(this,G,0);u(this,$);u(this,Ae);u(this,J);u(this,j);u(this,qe);u(this,$e,1e3);u(this,X,0);u(this,lt,3);u(this,_e,!1);u(this,dt,100);u(this,ut,5e3);u(this,je);u(this,Y);u(this,Z,0);u(this,xe,3);var a,h,d,m;this.options=E({subscribe:!0},e),Ks(this.options),c(this,N,(a=this.options.offset)!=null?a:"-1"),c(this,B,""),c(this,T,this.options.handle);let t;if(e.columnMapper){let l=g=>{let S={};for(let[_,y]of Object.entries(g)){let O=e.columnMapper.decode(_);S[O]=y}return S};t=e.transformer?g=>e.transformer(l(g)):l}else t=e.transformer;c(this,ie,new Xe(e.parser,t)),c(this,ye,this.options.onError),c(this,K,(h=this.options.log)!=null?h:"full");let s=(d=e.fetchClient)!=null?d:(...l)=>fetch(...l),i=ce(E({},(m=e.backoffOptions)!=null?m:it),{onFailedAttempt:()=>{var l,g;c(this,C,!1),(g=(l=e.backoffOptions)==null?void 0:l.onFailedAttempt)==null||g.call(l)}}),o=os(s,i);c(this,Se,ls(hs(o))),c(this,Ee,cs(n(this,Se))),p(this,f,Ss).call(this)}get shapeHandle(){return n(this,T)}get error(){return n(this,ge)}get isUpToDate(){return n(this,v)}get lastOffset(){return n(this,N)}get mode(){return n(this,K)}subscribe(e,t=()=>{}){let s={};return n(this,W).set(s,[e,t]),n(this,U)||p(this,f,Be).call(this),()=>{n(this,W).delete(s)}}unsubscribeAll(){var e;n(this,W).clear(),(e=n(this,je))==null||e.call(this)}lastSyncedAt(){return n(this,Q)}lastSynced(){return n(this,Q)===void 0?1/0:Date.now()-n(this,Q)}isConnected(){return n(this,C)}isLoading(){return!n(this,v)}hasStarted(){return n(this,U)}isPaused(){return n(this,A)==="paused"}async forceDisconnectAndRefresh(){var e,t;c(this,oe,!0),n(this,v)&&!((e=n(this,k))!=null&&e.signal.aborted)&&((t=n(this,k))==null||t.abort(bt)),await p(this,f,gs).call(this),c(this,oe,!1)}async requestSnapshot(e){if(n(this,K)==="full")throw new Error(`Snapshot requests are not supported in ${n(this,K)} mode, as the consumer is guaranteed to observe all data`);n(this,U)||await p(this,f,Be).call(this),await p(this,f,Es).call(this),ve(this,G)._++;try{n(this,G)===1&&p(this,f,It).call(this);let{metadata:t,data:s}=await this.fetchSnapshot(e),i=s.concat([{headers:E({control:"snapshot-end"},t)},{headers:E({control:"subset-end"},e)}]);return n(this,Fe).addSnapshot(t,new Set(s.map(o=>o.key))),p(this,f,ht).call(this,i,!1),{metadata:t,data:s}}finally{ve(this,G)._--,n(this,G)===0&&p(this,f,Nt).call(this)}}async fetchSnapshot(e){var m;let{fetchUrl:t,requestHeaders:s}=await p(this,f,Dt).call(this,this.options.url,!0,e),i=await n(this,Ee).call(this,t.toString(),{headers:s});if(!i.ok)throw new x(i.status,void 0,void 0,Object.fromEntries([...i.headers.entries()]),t.toString());let o=(m=n(this,F))!=null?m:ds(i.headers,{required:!0,url:t.toString()}),{metadata:a,data:h}=await i.json(),d=n(this,ie).parseSnapshotData(h,o);return{metadata:a,data:d}}};ge=new WeakMap,Ee=new WeakMap,Se=new WeakMap,ie=new WeakMap,W=new WeakMap,U=new WeakMap,A=new WeakMap,N=new WeakMap,B=new WeakMap,Q=new WeakMap,v=new WeakMap,ae=new WeakMap,C=new WeakMap,T=new WeakMap,K=new WeakMap,F=new WeakMap,ye=new WeakMap,k=new WeakMap,oe=new WeakMap,q=new WeakMap,Re=new WeakMap,z=new WeakMap,be=new WeakMap,Fe=new WeakMap,G=new WeakMap,$=new WeakMap,Ae=new WeakMap,J=new WeakMap,j=new WeakMap,qe=new WeakMap,$e=new WeakMap,X=new WeakMap,lt=new WeakMap,_e=new WeakMap,dt=new WeakMap,ut=new WeakMap,je=new WeakMap,Y=new WeakMap,Z=new WeakMap,xe=new WeakMap,f=new WeakSet,Lt=function(){return n(this,J)!==void 0},Be=async function(){var e,t,s,i,o;c(this,U,!0);try{await p(this,f,me).call(this)}catch(a){if(c(this,ge,a),n(this,ye)){let h=await n(this,ye).call(this,a),d=!(a instanceof re);if(h&&typeof h=="object"&&d){h.params&&(this.options.params=E(E({},(e=this.options.params)!=null?e:{}),h.params)),h.headers&&(this.options.headers=E(E({},(t=this.options.headers)!=null?t:{}),h.headers)),c(this,ge,null),c(this,U,!1),await p(this,f,Be).call(this);return}a instanceof Error&&p(this,f,Ft).call(this,a),c(this,C,!1),(s=n(this,z))==null||s.call(this);return}throw a instanceof Error&&p(this,f,Ft).call(this,a),c(this,C,!1),(i=n(this,z))==null||i.call(this),a}c(this,C,!1),(o=n(this,z))==null||o.call(this)},me=async function(){var d,m;if(n(this,A)==="pause-requested"){c(this,A,"paused");return}if(!this.options.subscribe&&((d=this.options.signal)!=null&&d.aborted||n(this,v)))return;let e=n(this,A)==="paused";c(this,A,"active");let{url:t,signal:s}=this.options,{fetchUrl:i,requestHeaders:o}=await p(this,f,Dt).call(this,t,e),a=await p(this,f,us).call(this,s),h=n(this,k);try{await p(this,f,fs).call(this,{fetchUrl:i,requestAbortController:h,headers:o,resumingFromPause:e})}catch(l){if((l instanceof x||l instanceof D)&&h.signal.aborted&&h.signal.reason===bt)return p(this,f,me).call(this);if(l instanceof D){let g=n(this,A);h.signal.aborted&&h.signal.reason===At&&g==="pause-requested"&&c(this,A,"paused");return}if(l instanceof Me)return p(this,f,me).call(this);if(!(l instanceof x))throw l;if(l.status==409){if(n(this,T)){let S=Ne(i);ot.markExpired(S,n(this,T))}let g=l.headers[ke]||`${n(this,T)}-next`;return p(this,f,ys).call(this,g),await p(this,f,Bt).call(this,Array.isArray(l.json)?l.json:[l.json]),p(this,f,me).call(this)}else throw l}finally{a&&s&&s.removeEventListener("abort",a),c(this,k,void 0)}return(m=n(this,Re))==null||m.call(this),p(this,f,me).call(this)},Dt=async function(e,t,s){var l,g,S,_,y,O;let[i,o]=await Promise.all([Qs(this.options.headers),this.options.params?Ws(zs(this.options.params)):void 0]);o&&Rs(o);let a=new URL(e);if(o){if(o.table&&w(a,ss,o.table),o.where&&typeof o.where=="string"){let L=Ze(o.where,(l=this.options.columnMapper)==null?void 0:l.encode);w(a,rs,L)}if(o.columns){let L=await qt((g=this.options.params)==null?void 0:g.columns);if(Array.isArray(L)){let V=L.map(String);this.options.columnMapper&&(V=V.map(this.options.columnMapper.encode));let Pe=V.map(Ce).join(",");w(a,yt,Pe)}else w(a,yt,o.columns)}o.replica&&w(a,ns,o.replica),o.params&&w(a,is,o.params);let b=E({},o);delete b.table,delete b.where,delete b.columns,delete b.replica,delete b.params;for(let[L,V]of Object.entries(b))w(a,L,V)}if(s){if(s.whereExpr){let b=at(s.whereExpr,(S=this.options.columnMapper)==null?void 0:S.encode);w(a,ue,b),a.searchParams.set(xt,JSON.stringify(s.whereExpr))}else if(s.where&&typeof s.where=="string"){let b=Ze(s.where,(_=this.options.columnMapper)==null?void 0:_.encode);w(a,ue,b)}if(s.params&&a.searchParams.set(De,JSON.stringify(s.params)),s.limit&&w(a,Oe,s.limit),s.offset&&w(a,Le,s.offset),s.orderByExpr){let b=Mt(s.orderByExpr,(y=this.options.columnMapper)==null?void 0:y.encode);w(a,fe,b),a.searchParams.set(Tt,JSON.stringify(s.orderByExpr))}else if(s.orderBy&&typeof s.orderBy=="string"){let b=Ze(s.orderBy,(O=this.options.columnMapper)==null?void 0:O.encode);w(a,fe,b)}}a.searchParams.set(de,n(this,N)),a.searchParams.set(_t,n(this,K));let h=s!==void 0;n(this,v)&&!h&&(!n(this,oe)&&!t&&a.searchParams.set(H,"true"),a.searchParams.set(st,n(this,B))),n(this,T)&&a.searchParams.set(le,n(this,T));let d=Ne(a),m=ot.getExpiredHandle(d);return m&&a.searchParams.set(Ue,m),n(this,Y)&&a.searchParams.set(rt,n(this,Y)),a.searchParams.sort(),{fetchUrl:a,requestHeaders:i}},us=async function(e){var t;if(c(this,k,new AbortController),e){let s=()=>{var i;(i=n(this,k))==null||i.abort(e.reason)};return e.addEventListener("abort",s,{once:!0}),e.aborted&&((t=n(this,k))==null||t.abort(e.reason)),s}},Ht=async function(e){var h,d,m,l;let{headers:t,status:s}=e,i=t.get(ke);if(i){let g=n(this,j)?Ne(n(this,j)):null,S=g?ot.getExpiredHandle(g):null;if(i!==S)c(this,T,i),n(this,Y)&&(c(this,Y,void 0),c(this,Z,0));else{if(n(this,T)===void 0)throw ve(this,Z)._++,await((h=e.body)==null?void 0:h.cancel()),n(this,Z)>n(this,xe)?new x(502,void 0,void 0,{},(m=(d=n(this,j))==null?void 0:d.toString())!=null?m:"",`CDN continues serving stale cached responses after ${n(this,xe)} retry attempts. This indicates a severe proxy/CDN misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: https://electric-sql.com/docs/guides/troubleshooting`):(console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${i}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: https://electric-sql.com/docs/guides/troubleshooting Retrying with a random cache buster to bypass the stale cache (attempt ${n(this,Z)}/${n(this,xe)}).`),c(this,Y,`${Date.now()}-${Math.random().toString(36).substring(2,9)}`),new Me(`Received stale cached response with expired handle "${i}". This indicates a proxy/CDN caching misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key.`));console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${i}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Ignoring the stale handle and continuing with handle "${n(this,T)}".`)}}let o=t.get(tt);o&&c(this,N,o);let a=t.get(es);a&&c(this,B,a),c(this,F,(l=n(this,F))!=null?l:ds(t)),s===204&&c(this,Q,Date.now())},ht=async function(e,t=!1){var s;if(e.length>0){c(this,ae,!0);let i=e[e.length-1];if(gt(i)){if(t){let a=Zt(i);a&&c(this,N,a)}if(c(this,Q,Date.now()),c(this,v,!0),c(this,ae,!1),(s=n(this,Ae))==null||s.call(this),n(this,f,Lt)&&!t&&n(this,B)===n(this,J)){c(this,J,void 0);return}if(c(this,J,void 0),n(this,j)){let a=Ne(n(this,j));Ut.recordUpToDate(a,n(this,B))}}let o=e.filter(a=>he(a)?!n(this,Fe).shouldRejectMessage(a):!0);await p(this,f,Bt).call(this,o)}},fs=async function(e){var s;if(c(this,j,e.fetchUrl),!n(this,v)&&!n(this,f,Lt)){let i=Ne(e.fetchUrl),o=Ut.shouldEnterReplayMode(i);o&&c(this,J,o)}let t=(s=this.options.liveSse)!=null?s:this.options.experimentalLiveSse;return n(this,v)&&t&&!n(this,oe)&&!e.resumingFromPause&&!n(this,_e)?(e.fetchUrl.searchParams.set(as,"true"),e.fetchUrl.searchParams.set(Rt,"true"),p(this,f,ms).call(this,e)):p(this,f,ps).call(this,e)},ps=async function(e){let{fetchUrl:t,requestAbortController:s,headers:i}=e,o=await n(this,Ee).call(this,t.toString(),{signal:s.signal,headers:i});c(this,C,!0),await p(this,f,Ht).call(this,o);let a=n(this,F),d=await o.text()||"[]",m=n(this,ie).parse(d,a);await p(this,f,ht).call(this,m)},ms=async function(e){let{fetchUrl:t,requestAbortController:s,headers:i}=e,o=n(this,Se);c(this,qe,Date.now());let a=ce(E({},i),{Accept:"text/event-stream"});try{let h=[];await Ys(t.toString(),{headers:a,fetch:o,onopen:async d=>{c(this,C,!0),await p(this,f,Ht).call(this,d)},onmessage:d=>{if(d.data){let m=n(this,F),l=n(this,ie).parse(d.data,m);h.push(l),gt(l)&&(p(this,f,ht).call(this,h,!0),h=[])}},onerror:d=>{throw d},signal:s.signal})}catch(h){throw s.signal.aborted?new D:h}finally{let h=Date.now()-n(this,qe),d=s.signal.aborted;if(h<n(this,$e)&&!d)if(ve(this,X)._++,n(this,X)>=n(this,lt))c(this,_e,!0),console.warn("[Electric] SSE connections are closing immediately (possibly due to proxy buffering or misconfiguration). Falling back to long polling. Your proxy must support streaming SSE responses (not buffer the complete response). Configuration: Nginx add 'X-Accel-Buffering: no', Caddy add 'flush_interval -1' to reverse_proxy. Note: Do NOT disable caching entirely - Electric uses cache headers to enable request collapsing for efficiency.");else{let m=Math.min(n(this,ut),n(this,dt)*Math.pow(2,n(this,X))),l=Math.floor(Math.random()*m);await new Promise(g=>setTimeout(g,l))}else h>=n(this,$e)&&c(this,X,0)}},It=function(){var e;n(this,U)&&n(this,A)==="active"&&(c(this,A,"pause-requested"),(e=n(this,k))==null||e.abort(At))},Nt=function(){var e;if(n(this,U)&&(n(this,A)==="paused"||n(this,A)==="pause-requested")){if((e=this.options.signal)!=null&&e.aborted)return;n(this,A)==="pause-requested"&&c(this,A,"active"),p(this,f,Be).call(this)}},gs=async function(){return n(this,q)?n(this,q):(c(this,q,new Promise((e,t)=>{c(this,Re,e),c(this,z,t)})),n(this,q).finally(()=>{c(this,q,void 0),c(this,Re,void 0),c(this,z,void 0)}),n(this,q))},Es=async function(){if(n(this,ae))return n(this,$)?n(this,$):(c(this,$,new Promise(e=>{c(this,Ae,e)})),n(this,$).finally(()=>{c(this,$,void 0),c(this,Ae,void 0)}),n(this,$))},Bt=async function(e){return c(this,be,n(this,be).then(()=>Promise.all(Array.from(n(this,W).values()).map(async([t,s])=>{try{await t(e)}catch(i){queueMicrotask(()=>{throw i})}})))),n(this,be)},Ft=function(e){n(this,W).forEach(([t,s])=>{s==null||s(e)})},Ss=function(){if(typeof document=="object"&&typeof document.hidden=="boolean"&&typeof document.addEventListener=="function"){let e=()=>{document.hidden?p(this,f,It).call(this):p(this,f,Nt).call(this)};document.addEventListener("visibilitychange",e),c(this,je,()=>{document.removeEventListener("visibilitychange",e)})}},ys=function(e){c(this,N,"-1"),c(this,B,""),c(this,T,e),c(this,v,!1),c(this,ae,!0),c(this,C,!1),c(this,F,void 0),c(this,G,0),c(this,X,0),c(this,_e,!1),c(this,Y,void 0),c(this,Z,0)},Ot.Replica={FULL:"full",DEFAULT:"default"};function ds(r,e){let t=r.get(St);if(!t){if(e!=null&&e.required&&(e!=null&&e.url))throw new re(e.url,[St]);return{}}return JSON.parse(t)}function Rs(r){if(!r)return;let e=Object.keys(r).filter(t=>Vs.has(t));if(e.length>0)throw new ze(e)}function Ks(r){if(!r.url)throw new We;if(r.signal&&!(r.signal instanceof AbortSignal))throw new Qe;if(r.offset!==void 0&&r.offset!=="-1"&&r.offset!=="now"&&!r.handle)throw new Ke;Rs(r.params)}function w(r,e,t){if(!(t===void 0||t==null))if(typeof t=="string")r.searchParams.set(e,t);else if(typeof t=="object")for(let[s,i]of Object.entries(t))r.searchParams.set(`${e}[${s}]`,i);else r.searchParams.set(e,t.toString())}function zs(r){return Array.isArray(r.params)?ce(E({},r),{params:Object.fromEntries(r.params.map((e,t)=>[t+1,e]))}):r}var P,ee,te,Ye,Te,we,se,R,As,_s,$t,ft,xs,jt,bs=class{constructor(e){u(this,R);u(this,P,new Map);u(this,ee,new Map);u(this,te,new Set);u(this,Ye,new Set);u(this,Te,!1);u(this,we,"syncing");u(this,se,!1);this.stream=e,this.stream.subscribe(p(this,R,As).bind(this),p(this,R,xs).bind(this))}get isUpToDate(){return n(this,we)==="up-to-date"}get lastOffset(){return this.stream.lastOffset}get handle(){return this.stream.shapeHandle}get rows(){return this.value.then(e=>Array.from(e.values()))}get currentRows(){return Array.from(this.currentValue.values())}get value(){return new Promise((e,t)=>{if(this.stream.isUpToDate)e(this.currentValue);else{let s=this.subscribe(({value:i})=>{s(),n(this,se)&&t(n(this,se)),e(i)})}})}get currentValue(){return n(this,P)}get error(){return n(this,se)}lastSyncedAt(){return this.stream.lastSyncedAt()}lastSynced(){return this.stream.lastSynced()}isLoading(){return this.stream.isLoading()}isConnected(){return this.stream.isConnected()}get mode(){return this.stream.mode}async requestSnapshot(e){let t=JSON.stringify(e);n(this,Ye).add(t),await p(this,R,$t).call(this),await this.stream.requestSnapshot(e)}subscribe(e){let t={};return n(this,ee).set(t,e),()=>{n(this,ee).delete(t)}}unsubscribeAll(){n(this,ee).clear()}get numSubscribers(){return n(this,ee).size}};P=new WeakMap,ee=new WeakMap,te=new WeakMap,Ye=new WeakMap,Te=new WeakMap,we=new WeakMap,se=new WeakMap,R=new WeakSet,As=function(e){let t=!1;e.forEach(s=>{if(he(s))if(t=p(this,R,ft).call(this,"syncing"),this.mode==="full")switch(s.headers.operation){case"insert":n(this,P).set(s.key,s.value);break;case"update":n(this,P).set(s.key,E(E({},n(this,P).get(s.key)),s.value));break;case"delete":n(this,P).delete(s.key);break}else switch(s.headers.operation){case"insert":n(this,te).add(s.key),n(this,P).set(s.key,s.value);break;case"update":n(this,te).has(s.key)&&n(this,P).set(s.key,E(E({},n(this,P).get(s.key)),s.value));break;case"delete":n(this,te).has(s.key)&&(n(this,P).delete(s.key),n(this,te).delete(s.key));break}if(et(s))switch(s.headers.control){case"up-to-date":t=p(this,R,ft).call(this,"up-to-date"),n(this,Te)&&(c(this,Te,!1),p(this,R,_s).call(this));break;case"must-refetch":n(this,P).clear(),n(this,te).clear(),c(this,se,!1),t=p(this,R,ft).call(this,"syncing"),c(this,Te,!0);break}}),t&&p(this,R,jt).call(this)},_s=async function(){await p(this,R,$t).call(this),await Promise.all(Array.from(n(this,Ye)).map(async e=>{try{let t=JSON.parse(e);await this.stream.requestSnapshot(t)}catch(t){}}))},$t=async function(){this.stream.isUpToDate||await new Promise(e=>{let t=()=>{this.stream.isUpToDate&&(clearInterval(s),i(),e())},s=setInterval(t,10),i=this.stream.subscribe(()=>t(),()=>t());t()})},ft=function(e){let t=n(this,we)!==e;return c(this,we,e),t&&e==="up-to-date"},xs=function(e){e instanceof x&&(c(this,se,e),p(this,R,jt).call(this))},jt=function(){n(this,ee).forEach(e=>{e({value:this.currentValue,rows:this.currentRows})})};export{it as BackoffDefaults,wt as ELECTRIC_PROTOCOL_QUERY_PARAMS,x as FetchError,bs as Shape,Ot as ShapeStream,Jt as camelToSnake,at as compileExpression,Mt as compileOrderBy,Xt as createColumnMapper,he as isChangeMessage,et as isControlMessage,Et as isVisibleInSnapshot,qt as resolveValue,Os as snakeCamelMapper,mt as snakeToCamel};
|
|
5
|
+
For more information visit the troubleshooting guide: /docs/guides/troubleshooting/missing-headers`,super(s)}},Ue=class extends Error{constructor(e){super(e),this.name="StaleCacheError"}};var et=r=>Number(r),vs=r=>r==="true"||r==="t",Cs=r=>BigInt(r),Gt=r=>JSON.parse(r),ks=r=>r,Us={int2:et,int4:et,int8:Cs,bool:vs,float4:et,float8:et,json:Gt,jsonb:Gt};function Os(r,e){let t=0,s=null,i="",o=!1,a=0,h;function d(l,g,y){let b=l.slice(g,y);return b=b==="NULL"?null:b,e?e(b):b}function m(l){let g=[];for(;t<l.length;t++){if(s=l[t],o)s==="\\"?i+=l[++t]:s==='"'?(g.push(e?e(i):i),i="",o=l[t+1]==='"',a=t+2):i+=s;else if(s==='"')o=!0;else if(s==="{")a=++t,g.push(m(l));else if(s==="}"){o=!1,a<t&&g.push(d(l,a,t)),a=t+1;break}else s===","&&h!=="}"&&h!=='"'&&(g.push(d(l,a,t)),a=t+1);h=s}return a<t&&g.push(g.push(d(l,a,t+1))),g}return m(r)[0]}var tt=class{constructor(e,t){this.parser=E(E({},Us),e),this.transformer=t}parse(e,t){return JSON.parse(e,(s,i)=>(s==="value"||s==="old_value")&&typeof i=="object"&&i!==null?this.transformMessageValue(i,t):i)}parseSnapshotData(e,t){return e.map(s=>{let i=s;return i.value&&typeof i.value=="object"&&i.value!==null&&(i.value=this.transformMessageValue(i.value,t)),i.old_value&&typeof i.old_value=="object"&&i.old_value!==null&&(i.old_value=this.transformMessageValue(i.old_value,t)),i})}transformMessageValue(e,t){let s=e;return Object.keys(s).forEach(i=>{s[i]=this.parseRow(i,s[i],t)}),this.transformer?this.transformer(s):s}parseRow(e,t,s){var g;let i=s[e];if(!i)return t;let l=i,{type:o,dims:a}=l,h=Qt(l,["type","dims"]),d=(g=this.parser[o])!=null?g:ks,m=zt(d,i,e);return a&&a>0?zt((b,S)=>Os(b,m),i,e)(t):m(t,h)}};function zt(r,e,t){var i;let s=!((i=e.not_null)!=null&&i);return o=>{if(o===null){if(!s)throw new Ze(t!=null?t:"unknown");return null}return r(o,e)}}function Oe(r){return`"${r.replace(/"/g,'""')}"`}function Et(r){var h,d,m,l;let e=(d=(h=r.match(/^_+/))==null?void 0:h[0])!=null?d:"",t=r.slice(e.length),s=(l=(m=t.match(/_+$/))==null?void 0:m[0])!=null?l:"",a=(s?t.slice(0,t.length-s.length):t).toLowerCase().replace(/_+([a-z])/g,(g,y)=>y.toUpperCase());return e+a+s}function Jt(r){return r.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()}function Xt(r){let e={};for(let[t,s]of Object.entries(r))e[s]=t;return{decode:t=>{var s;return(s=r[t])!=null?s:t},encode:t=>{var s;return(s=e[t])!=null?s:t}}}function he(r,e){if(!r||!e)return r!=null?r:"";let t=new Set(["SELECT","FROM","WHERE","AND","OR","NOT","IN","IS","NULL","NULLS","FIRST","LAST","TRUE","FALSE","LIKE","ILIKE","BETWEEN","ASC","DESC","LIMIT","OFFSET","ORDER","BY","GROUP","HAVING","DISTINCT","AS","ON","JOIN","LEFT","RIGHT","INNER","OUTER","CROSS","CASE","WHEN","THEN","ELSE","END","CAST","LOWER","UPPER","COALESCE","NULLIF"]),s=[],i=0;for(;i<r.length;){let h=r[i];if(h==="'"||h==='"'){let d=i,m=h;for(i++;i<r.length;)if(r[i]===m)if(r[i+1]===m)i+=2;else{i++;break}else i++;s.push({start:d,end:i})}else i++}let o=h=>s.some(d=>h>=d.start&&h<d.end),a=new RegExp("(?<![a-zA-Z0-9_])([a-zA-Z_][a-zA-Z0-9_]*)(?![a-zA-Z0-9_])","g");return r.replace(a,(h,d,m)=>o(m)||t.has(h.toUpperCase())||h.startsWith("$")?h:e(h))}function Ls(r){if(r){let e={};for(let t of Object.keys(r))e[t]=Et(t);return Xt(e)}return{decode:e=>Et(e),encode:e=>Jt(e)}}function le(r){return"key"in r}function st(r){return!le(r)}function yt(r){return st(r)&&r.headers.control==="up-to-date"}function Zt(r){if(r.headers.control!="up-to-date")return;let e=r.headers.global_last_seen_lsn;return e?`${e}_0`:void 0}function St(r,e){let t=BigInt(r),s=BigInt(e.xmin),i=BigInt(e.xmax),o=e.xip_list.map(BigInt);return t<s||t<i&&!o.includes(t)}var es="electric-cursor",de="electric-handle",rt="electric-offset",Rt="electric-schema",ts="electric-up-to-date",bt="columns",nt="cursor",Le="expired_handle",ue="handle",H="live",fe="offset",ss="table",rs="where",ns="replica",is="params",as="experimental_live_sse",xt="live_sse",_t="force-disconnect-and-refresh",At="pause-stream",wt="log",pe="subset__where",De="subset__limit",He="subset__offset",me="subset__order_by",Ie="subset__params",Tt="subset__where_expr",Pt="subset__order_by_expr",it="cache-buster",Mt=[H,xt,ue,fe,nt,Le,wt,pe,De,He,me,Ie,Tt,Pt,it];var Ds=[429],ot={initialDelay:100,maxDelay:6e4,multiplier:1.3,maxRetries:1/0};function Hs(r){if(!r)return 0;let e=Number(r);if(Number.isFinite(e)&&e>0)return e*1e3;let t=Date.parse(r);if(!isNaN(t)){let s=t-Date.now();return Math.max(0,Math.min(s,36e5))}return 0}function os(r,e=ot){let{initialDelay:t,maxDelay:s,multiplier:i,debug:o=!1,onFailedAttempt:a,maxRetries:h=1/0}=e;return async(...d)=>{var b;let m=d[0],l=d[1],g=t,y=0;for(;;)try{let S=await r(...d);if(S.ok)return S;throw await A.fromResponse(S,m.toString())}catch(S){if(a==null||a(),(b=l==null?void 0:l.signal)!=null&&b.aborted)throw new D;if(S instanceof A&&!Ds.includes(S.status)&&S.status>=400&&S.status<500)throw S;{if(y++,y>h)throw o&&console.log(`Max retries reached (${y}/${h}), giving up`),S;let R=S instanceof A&&S.headers?Hs(S.headers["retry-after"]):0,x=Math.random()*g,L=Math.min(x,s),V=Math.max(R,L);if(o){let Ce=R>0?"server+client":"client";console.log(`Retry attempt #${y} after ${V}ms (${Ce}, serverMin=${R}ms, clientBackoff=${L}ms)`)}await new Promise(Ce=>setTimeout(Ce,V)),g=Math.min(g*i,s)}}}}var Is=[201,204,205];function cs(r){return async(...e)=>{var i,o;let t=e[0],s=await r(...e);try{if(s.status<200||Is.includes(s.status))return s;let a=await s.text();return new Response(a,s)}catch(a){throw(o=(i=e[1])==null?void 0:i.signal)!=null&&o.aborted?new D:new A(s.status,void 0,void 0,Object.fromEntries([...s.headers.entries()]),t.toString(),a instanceof Error?a.message:typeof a=="string"?a:"failed to read body")}}}var Bs={maxChunksToPrefetch:2};function hs(r,e=Bs){let{maxChunksToPrefetch:t}=e,s;return async(...o)=>{let a=o[0].toString(),h=s==null?void 0:s.consume(...o);if(h)return h;s==null||s.abort(),s=void 0;let d=await r(...o),m=Ct(a,d);return m&&(s=new vt({fetchClient:r,maxPrefetchedRequests:t,url:m,requestInit:o[1]})),d}}var Ns=["electric-offset","electric-handle"],Fs=["electric-cursor"],qs=["electric-schema"];function ls(r){return async(...e)=>{let t=await r(...e);if(t.ok){let s=t.headers,i=[],o=l=>i.push(...l.filter(g=>!s.has(g))),h=e[0].toString(),d=new URL(h);if([pe,Ie,De,He,me].some(l=>d.searchParams.has(l)))return t;if(o(Ns),d.searchParams.get(H)==="true"&&o(Fs),(!d.searchParams.has(H)||d.searchParams.get(H)==="false")&&o(qs),i.length>0)throw new ne(h,i)}return t}}var Be,Ne,C,ie,I,ge,at,vt=class{constructor(e){u(this,ge);u(this,Be);u(this,Ne);u(this,C,new Map);u(this,ie);u(this,I);var t;c(this,Be,(t=e.fetchClient)!=null?t:(...s)=>fetch(...s)),c(this,Ne,e.maxPrefetchedRequests),c(this,ie,e.url.toString()),c(this,I,n(this,ie)),p(this,ge,at).call(this,e.url,e.requestInit)}abort(){n(this,C).forEach(([e,t])=>t.abort()),n(this,C).clear()}consume(...e){let t=e[0].toString(),s=n(this,C).get(t);if(!s||t!==n(this,ie))return;let[i,o]=s;if(o.signal.aborted){n(this,C).delete(t);return}return n(this,C).delete(t),i.then(a=>{let h=Ct(t,a);c(this,ie,h),n(this,I)&&!n(this,C).has(n(this,I))&&p(this,ge,at).call(this,n(this,I),e[1])}).catch(()=>{}),i}};Be=new WeakMap,Ne=new WeakMap,C=new WeakMap,ie=new WeakMap,I=new WeakMap,ge=new WeakSet,at=function(...e){var i,o;let t=e[0].toString();if(n(this,C).size>=n(this,Ne))return;let s=new AbortController;try{let{signal:a,cleanup:h}=$s(s,(i=e[1])==null?void 0:i.signal),d=n(this,Be).call(this,t,re(E({},(o=e[1])!=null?o:{}),{signal:a}));n(this,C).set(t,[d,s]),d.then(m=>{if(!m.ok||s.signal.aborted)return;let l=Ct(t,m);if(!l||l===t){c(this,I,void 0);return}return c(this,I,l),p(this,ge,at).call(this,l,e[1])}).catch(()=>{}).finally(h)}catch(a){}};function Ct(r,e){let t=e.headers.get(de),s=e.headers.get(rt),i=e.headers.has(ts);if(!t||!s||i)return;let o=new URL(r);if(o.searchParams.has(H))return;let a=o.searchParams.get(Le);if(a&&t===a){console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${t}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Skipping prefetch to prevent infinite 409 loop.`);return}return o.searchParams.set(ue,t),o.searchParams.set(fe,s),o.searchParams.sort(),o.toString()}function $s(r,e){let t=js;if(e)if(e.aborted)r.abort();else{let s=()=>r.abort();e.addEventListener("abort",s,{once:!0,signal:r.signal}),t=()=>e.removeEventListener("abort",s)}return{signal:r.signal,cleanup:t}}function js(){}function Fe(r,e){switch(r.type){case"ref":{let t=e?e(r.column):r.column;return Oe(t)}case"val":return`$${r.paramIndex}`;case"func":return Ys(r,e);default:{let t=r;throw new Error(`Unknown expression type: ${JSON.stringify(t)}`)}}}function Ys(r,e){let t=r.args.map(s=>Fe(s,e));switch(r.name){case"eq":return`${t[0]} = ${t[1]}`;case"gt":return`${t[0]} > ${t[1]}`;case"gte":return`${t[0]} >= ${t[1]}`;case"lt":return`${t[0]} < ${t[1]}`;case"lte":return`${t[0]} <= ${t[1]}`;case"and":return t.map(s=>`(${s})`).join(" AND ");case"or":return t.map(s=>`(${s})`).join(" OR ");case"not":return`NOT (${t[0]})`;case"in":return`${t[0]} = ANY(${t[1]})`;case"like":return`${t[0]} LIKE ${t[1]}`;case"ilike":return`${t[0]} ILIKE ${t[1]}`;case"isNull":case"isUndefined":return`${t[0]} IS NULL`;case"upper":return`UPPER(${t[0]})`;case"lower":return`LOWER(${t[0]})`;case"length":return`LENGTH(${t[0]})`;case"concat":return`CONCAT(${t.join(", ")})`;case"coalesce":return`COALESCE(${t.join(", ")})`;default:throw new Error(`Unknown function: ${r.name}`)}}function ct(r,e){return r.map(t=>{let s=e?e(t.column):t.column,i=Oe(s);return t.direction==="desc"&&(i+=" DESC"),t.nulls==="first"&&(i+=" NULLS FIRST"),t.nulls==="last"&&(i+=" NULLS LAST"),i}).join(", ")}import{fetchEventSource as Vs}from"@microsoft/fetch-event-source";var kt=class{constructor(){this.data={};this.max=250;this.storageKey="electric_expired_shapes";this.load()}getExpiredHandle(e){let t=this.data[e];return t?(t.lastUsed=Date.now(),this.save(),t.expiredHandle):null}markExpired(e,t){this.data[e]={expiredHandle:t,lastUsed:Date.now()};let s=Object.keys(this.data);if(s.length>this.max){let i=s.reduce((o,a)=>this.data[a].lastUsed<this.data[o].lastUsed?a:o);delete this.data[i]}this.save()}save(){if(typeof localStorage!="undefined")try{localStorage.setItem(this.storageKey,JSON.stringify(this.data))}catch(e){}}load(){if(typeof localStorage!="undefined")try{let e=localStorage.getItem(this.storageKey);e&&(this.data=JSON.parse(e))}catch(e){this.data={}}}clear(){this.data={},this.save()}},qe=new kt;var Ut=class{constructor(){this.data={};this.storageKey="electric_up_to_date_tracker";this.cacheTTL=6e4;this.maxEntries=250;this.writeThrottleMs=6e4;this.lastWriteTime=0;this.load(),this.cleanup()}recordUpToDate(e,t){this.data[e]={timestamp:Date.now(),cursor:t};let s=Object.keys(this.data);if(s.length>this.maxEntries){let i=s.reduce((o,a)=>this.data[a].timestamp<this.data[o].timestamp?a:o);delete this.data[i]}this.scheduleSave()}scheduleSave(){let e=Date.now(),t=e-this.lastWriteTime;if(t>=this.writeThrottleMs)this.lastWriteTime=e,this.save();else if(!this.pendingSaveTimer){let s=this.writeThrottleMs-t;this.pendingSaveTimer=setTimeout(()=>{this.lastWriteTime=Date.now(),this.pendingSaveTimer=void 0,this.save()},s)}}shouldEnterReplayMode(e){let t=this.data[e];return!t||Date.now()-t.timestamp>=this.cacheTTL?null:t.cursor}cleanup(){let e=Date.now(),t=Object.keys(this.data),s=!1;for(let i of t)e-this.data[i].timestamp>this.cacheTTL&&(delete this.data[i],s=!0);s&&this.save()}save(){if(typeof localStorage!="undefined")try{localStorage.setItem(this.storageKey,JSON.stringify(this.data))}catch(e){}}load(){if(typeof localStorage!="undefined")try{let e=localStorage.getItem(this.storageKey);e&&(this.data=JSON.parse(e))}catch(e){this.data={}}}clear(){this.data={},this.pendingSaveTimer&&(clearTimeout(this.pendingSaveTimer),this.pendingSaveTimer=void 0),this.save()}},Ot=new Ut;var ht=class{constructor(){this.activeSnapshots=new Map;this.xmaxSnapshots=new Map;this.snapshotsByDatabaseLsn=new Map}addSnapshot(e,t){var o,a,h,d;this.activeSnapshots.set(e.snapshot_mark,{xmin:BigInt(e.xmin),xmax:BigInt(e.xmax),xip_list:e.xip_list.map(BigInt),keys:t});let s=(a=(o=this.xmaxSnapshots.get(BigInt(e.xmax)))==null?void 0:o.add(e.snapshot_mark))!=null?a:new Set([e.snapshot_mark]);this.xmaxSnapshots.set(BigInt(e.xmax),s);let i=(d=(h=this.snapshotsByDatabaseLsn.get(BigInt(e.database_lsn)))==null?void 0:h.add(e.snapshot_mark))!=null?d:new Set([e.snapshot_mark]);this.snapshotsByDatabaseLsn.set(BigInt(e.database_lsn),i)}removeSnapshot(e){this.activeSnapshots.delete(e)}shouldRejectMessage(e){let t=e.headers.txids||[];if(t.length===0)return!1;let s=Math.max(...t);for(let[i,o]of this.xmaxSnapshots.entries())if(s>=i)for(let a of o)this.removeSnapshot(a);return[...this.activeSnapshots.values()].some(i=>i.keys.has(e.key)&&St(s,i))}lastSeenUpdate(e){for(let[t,s]of this.snapshotsByDatabaseLsn.entries())if(t<=e)for(let i of s)this.removeSnapshot(i)}};var Ws=new Set([nt,ue,H,fe,it]);async function qt(r){return typeof r=="function"?r():r}async function Ks(r){let e=Object.entries(r),t=await Promise.all(e.map(async([s,i])=>{if(i===void 0)return[s,void 0];let o=await qt(i);return[s,Array.isArray(o)?o.join(","):o]}));return Object.fromEntries(t.filter(([s,i])=>i!==void 0))}async function Qs(r){if(!r)return{};let e=Object.entries(r),t=await Promise.all(e.map(async([s,i])=>[s,await qt(i)]));return Object.fromEntries(t)}function Ee(r){let e=new URL(r.origin+r.pathname);for(let[t,s]of r.searchParams)Mt.includes(t)||e.searchParams.set(t,s);return e.searchParams.sort(),e.toString()}var Se,Re,be,ae,W,O,w,B,N,K,v,oe,k,T,Q,F,xe,U,ce,q,_e,G,Ae,je,z,$,we,J,j,Ye,Ve,X,ut,Te,ft,pt,We,Y,Z,Pe,f,Dt,$e,ye,lt,us,Ht,dt,fs,ps,ms,It,Bt,gs,Es,Nt,Ft,ys,Ss,Rs,Lt=class{constructor(e){u(this,f);u(this,Se,null);u(this,Re);u(this,be);u(this,ae);u(this,W,new Map);u(this,O,!1);u(this,w,"active");u(this,B);u(this,N);u(this,K);u(this,v,!1);u(this,oe,!0);u(this,k,!1);u(this,T);u(this,Q);u(this,F);u(this,xe);u(this,U);u(this,ce,!1);u(this,q);u(this,_e);u(this,G);u(this,Ae,Promise.resolve([]));u(this,je,new ht);u(this,z,0);u(this,$);u(this,we);u(this,J);u(this,j);u(this,Ye);u(this,Ve,1e3);u(this,X,0);u(this,ut,3);u(this,Te,!1);u(this,ft,100);u(this,pt,5e3);u(this,We);u(this,Y);u(this,Z,0);u(this,Pe,3);var a,h,d,m;this.options=E({subscribe:!0},e),Gs(this.options),c(this,B,(a=this.options.offset)!=null?a:"-1"),c(this,N,""),c(this,T,this.options.handle);let t;if(e.columnMapper){let l=g=>{let y={};for(let[b,S]of Object.entries(g)){let R=e.columnMapper.decode(b);y[R]=S}return y};t=e.transformer?g=>e.transformer(l(g)):l}else t=e.transformer;c(this,ae,new tt(e.parser,t)),c(this,xe,this.options.onError),c(this,Q,(h=this.options.log)!=null?h:"full");let s=(d=e.fetchClient)!=null?d:(...l)=>fetch(...l),i=re(E({},(m=e.backoffOptions)!=null?m:ot),{onFailedAttempt:()=>{var l,g;c(this,k,!1),(g=(l=e.backoffOptions)==null?void 0:l.onFailedAttempt)==null||g.call(l)}}),o=os(s,i);c(this,be,ls(hs(o))),c(this,Re,cs(n(this,be))),p(this,f,ys).call(this)}get shapeHandle(){return n(this,T)}get error(){return n(this,Se)}get isUpToDate(){return n(this,v)}get lastOffset(){return n(this,B)}get mode(){return n(this,Q)}subscribe(e,t=()=>{}){let s={};return n(this,W).set(s,[e,t]),n(this,O)||p(this,f,$e).call(this),()=>{n(this,W).delete(s)}}unsubscribeAll(){var e;n(this,W).clear(),(e=n(this,We))==null||e.call(this)}lastSyncedAt(){return n(this,K)}lastSynced(){return n(this,K)===void 0?1/0:Date.now()-n(this,K)}isConnected(){return n(this,k)}isLoading(){return!n(this,v)}hasStarted(){return n(this,O)}isPaused(){return n(this,w)==="paused"}async forceDisconnectAndRefresh(){var e,t;c(this,ce,!0),n(this,v)&&!((e=n(this,U))!=null&&e.signal.aborted)&&((t=n(this,U))==null||t.abort(_t)),await p(this,f,gs).call(this),c(this,ce,!1)}async requestSnapshot(e){if(n(this,Q)==="full")throw new Error(`Snapshot requests are not supported in ${n(this,Q)} mode, as the consumer is guaranteed to observe all data`);n(this,O)||await p(this,f,$e).call(this),await p(this,f,Es).call(this),ke(this,z)._++;try{n(this,z)===1&&p(this,f,It).call(this);let{metadata:t,data:s}=await this.fetchSnapshot(e),i=s.concat([{headers:E({control:"snapshot-end"},t)},{headers:E({control:"subset-end"},e)}]);return n(this,je).addSnapshot(t,new Set(s.map(o=>o.key))),p(this,f,dt).call(this,i,!1),{metadata:t,data:s}}finally{ke(this,z)._--,n(this,z)===0&&p(this,f,Bt).call(this)}}async fetchSnapshot(e){var y,b,S;let s=((b=(y=e.method)!=null?y:this.options.subsetMethod)!=null?b:"GET")==="POST",i,o;if(s){let R=await p(this,f,lt).call(this,this.options.url,!0);i=R.fetchUrl,o={method:"POST",headers:re(E({},R.requestHeaders),{"Content-Type":"application/json"}),body:JSON.stringify(p(this,f,Rs).call(this,e))}}else{let R=await p(this,f,lt).call(this,this.options.url,!0,e);i=R.fetchUrl,o={headers:R.requestHeaders}}let a=n(this,T),h;try{h=await n(this,Re).call(this,i.toString(),o)}catch(R){if(R instanceof A&&R.status===409){if(a){let x=Ee(i);qe.markExpired(x,a)}return c(this,T,R.headers[de]||`${a!=null?a:"handle"}-next`),this.fetchSnapshot(e)}throw R}if(!h.ok)throw await A.fromResponse(h,i.toString());let d=(S=n(this,F))!=null?S:ds(h.headers,{required:!0,url:i.toString()}),{metadata:m,data:l}=await h.json(),g=n(this,ae).parseSnapshotData(l,d);return{metadata:m,data:g}}};Se=new WeakMap,Re=new WeakMap,be=new WeakMap,ae=new WeakMap,W=new WeakMap,O=new WeakMap,w=new WeakMap,B=new WeakMap,N=new WeakMap,K=new WeakMap,v=new WeakMap,oe=new WeakMap,k=new WeakMap,T=new WeakMap,Q=new WeakMap,F=new WeakMap,xe=new WeakMap,U=new WeakMap,ce=new WeakMap,q=new WeakMap,_e=new WeakMap,G=new WeakMap,Ae=new WeakMap,je=new WeakMap,z=new WeakMap,$=new WeakMap,we=new WeakMap,J=new WeakMap,j=new WeakMap,Ye=new WeakMap,Ve=new WeakMap,X=new WeakMap,ut=new WeakMap,Te=new WeakMap,ft=new WeakMap,pt=new WeakMap,We=new WeakMap,Y=new WeakMap,Z=new WeakMap,Pe=new WeakMap,f=new WeakSet,Dt=function(){return n(this,J)!==void 0},$e=async function(){var e,t,s,i,o;c(this,O,!0);try{await p(this,f,ye).call(this)}catch(a){if(c(this,Se,a),n(this,xe)){let h=await n(this,xe).call(this,a),d=!(a instanceof ne);if(h&&typeof h=="object"&&d){h.params&&(this.options.params=E(E({},(e=this.options.params)!=null?e:{}),h.params)),h.headers&&(this.options.headers=E(E({},(t=this.options.headers)!=null?t:{}),h.headers)),c(this,Se,null),c(this,O,!1),await p(this,f,$e).call(this);return}a instanceof Error&&p(this,f,Ft).call(this,a),c(this,k,!1),(s=n(this,G))==null||s.call(this);return}throw a instanceof Error&&p(this,f,Ft).call(this,a),c(this,k,!1),(i=n(this,G))==null||i.call(this),a}c(this,k,!1),(o=n(this,G))==null||o.call(this)},ye=async function(){var d,m;if(n(this,w)==="pause-requested"){c(this,w,"paused");return}if(!this.options.subscribe&&((d=this.options.signal)!=null&&d.aborted||n(this,v)))return;let e=n(this,w)==="paused";c(this,w,"active");let{url:t,signal:s}=this.options,{fetchUrl:i,requestHeaders:o}=await p(this,f,lt).call(this,t,e),a=await p(this,f,us).call(this,s),h=n(this,U);try{await p(this,f,fs).call(this,{fetchUrl:i,requestAbortController:h,headers:o,resumingFromPause:e})}catch(l){if((l instanceof A||l instanceof D)&&h.signal.aborted&&h.signal.reason===_t)return p(this,f,ye).call(this);if(l instanceof D){let g=n(this,w);h.signal.aborted&&h.signal.reason===At&&g==="pause-requested"&&c(this,w,"paused");return}if(l instanceof Ue)return p(this,f,ye).call(this);if(!(l instanceof A))throw l;if(l.status==409){if(n(this,T)){let y=Ee(i);qe.markExpired(y,n(this,T))}let g=l.headers[de]||`${n(this,T)}-next`;return p(this,f,Ss).call(this,g),await p(this,f,Nt).call(this,Array.isArray(l.json)?l.json:[l.json]),p(this,f,ye).call(this)}else throw l}finally{a&&s&&s.removeEventListener("abort",a),c(this,U,void 0)}return(m=n(this,_e))==null||m.call(this),p(this,f,ye).call(this)},lt=async function(e,t,s){var l,g,y,b,S,R;let[i,o]=await Promise.all([Qs(this.options.headers),this.options.params?Ks(zs(this.options.params)):void 0]);o&&bs(o);let a=new URL(e);if(o){if(o.table&&P(a,ss,o.table),o.where&&typeof o.where=="string"){let L=he(o.where,(l=this.options.columnMapper)==null?void 0:l.encode);P(a,rs,L)}if(o.columns){let L=await qt((g=this.options.params)==null?void 0:g.columns);if(Array.isArray(L)){let V=L.map(String);this.options.columnMapper&&(V=V.map(this.options.columnMapper.encode));let Ce=V.map(Oe).join(",");P(a,bt,Ce)}else P(a,bt,o.columns)}o.replica&&P(a,ns,o.replica),o.params&&P(a,is,o.params);let x=E({},o);delete x.table,delete x.where,delete x.columns,delete x.replica,delete x.params;for(let[L,V]of Object.entries(x))P(a,L,V)}if(s){if(s.whereExpr){let x=Fe(s.whereExpr,(y=this.options.columnMapper)==null?void 0:y.encode);P(a,pe,x),a.searchParams.set(Tt,JSON.stringify(s.whereExpr))}else if(s.where&&typeof s.where=="string"){let x=he(s.where,(b=this.options.columnMapper)==null?void 0:b.encode);P(a,pe,x)}if(s.params&&a.searchParams.set(Ie,JSON.stringify(s.params)),s.limit&&P(a,De,s.limit),s.offset&&P(a,He,s.offset),s.orderByExpr){let x=ct(s.orderByExpr,(S=this.options.columnMapper)==null?void 0:S.encode);P(a,me,x),a.searchParams.set(Pt,JSON.stringify(s.orderByExpr))}else if(s.orderBy&&typeof s.orderBy=="string"){let x=he(s.orderBy,(R=this.options.columnMapper)==null?void 0:R.encode);P(a,me,x)}}a.searchParams.set(fe,n(this,B)),a.searchParams.set(wt,n(this,Q));let h=s!==void 0;n(this,v)&&!h&&(!n(this,ce)&&!t&&a.searchParams.set(H,"true"),a.searchParams.set(nt,n(this,N))),n(this,T)&&a.searchParams.set(ue,n(this,T));let d=Ee(a),m=qe.getExpiredHandle(d);return m&&a.searchParams.set(Le,m),n(this,Y)&&a.searchParams.set(it,n(this,Y)),a.searchParams.sort(),{fetchUrl:a,requestHeaders:i}},us=async function(e){var t;if(c(this,U,new AbortController),e){let s=()=>{var i;(i=n(this,U))==null||i.abort(e.reason)};return e.addEventListener("abort",s,{once:!0}),e.aborted&&((t=n(this,U))==null||t.abort(e.reason)),s}},Ht=async function(e){var h,d,m,l;let{headers:t,status:s}=e,i=t.get(de);if(i){let g=n(this,j)?Ee(n(this,j)):null,y=g?qe.getExpiredHandle(g):null;if(i!==y)c(this,T,i),n(this,Y)&&(c(this,Y,void 0),c(this,Z,0));else{if(n(this,T)===void 0)throw ke(this,Z)._++,await((h=e.body)==null?void 0:h.cancel()),n(this,Z)>n(this,Pe)?new A(502,void 0,void 0,{},(m=(d=n(this,j))==null?void 0:d.toString())!=null?m:"",`CDN continues serving stale cached responses after ${n(this,Pe)} retry attempts. This indicates a severe proxy/CDN misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: https://electric-sql.com/docs/guides/troubleshooting`):(console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${i}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: https://electric-sql.com/docs/guides/troubleshooting Retrying with a random cache buster to bypass the stale cache (attempt ${n(this,Z)}/${n(this,Pe)}).`),c(this,Y,`${Date.now()}-${Math.random().toString(36).substring(2,9)}`),new Ue(`Received stale cached response with expired handle "${i}". This indicates a proxy/CDN caching misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key.`));console.warn(`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${i}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Ignoring the stale response and continuing with handle "${n(this,T)}".`);return}}let o=t.get(rt);o&&c(this,B,o);let a=t.get(es);a&&c(this,N,a),c(this,F,(l=n(this,F))!=null?l:ds(t)),s===204&&c(this,K,Date.now())},dt=async function(e,t=!1){var s;if(e.length>0){c(this,oe,!0);let i=e[e.length-1];if(yt(i)){if(t){let a=Zt(i);a&&c(this,B,a)}if(c(this,K,Date.now()),c(this,v,!0),c(this,oe,!1),(s=n(this,we))==null||s.call(this),n(this,f,Dt)&&!t&&n(this,N)===n(this,J)){c(this,J,void 0);return}if(c(this,J,void 0),n(this,j)){let a=Ee(n(this,j));Ot.recordUpToDate(a,n(this,N))}}let o=e.filter(a=>le(a)?!n(this,je).shouldRejectMessage(a):!0);await p(this,f,Nt).call(this,o)}},fs=async function(e){var s;if(c(this,j,e.fetchUrl),!n(this,v)&&!n(this,f,Dt)){let i=Ee(e.fetchUrl),o=Ot.shouldEnterReplayMode(i);o&&c(this,J,o)}let t=(s=this.options.liveSse)!=null?s:this.options.experimentalLiveSse;return n(this,v)&&t&&!n(this,ce)&&!e.resumingFromPause&&!n(this,Te)?(e.fetchUrl.searchParams.set(as,"true"),e.fetchUrl.searchParams.set(xt,"true"),p(this,f,ms).call(this,e)):p(this,f,ps).call(this,e)},ps=async function(e){let{fetchUrl:t,requestAbortController:s,headers:i}=e,o=await n(this,Re).call(this,t.toString(),{signal:s.signal,headers:i});c(this,k,!0),await p(this,f,Ht).call(this,o);let a=n(this,F),d=await o.text()||"[]",m=n(this,ae).parse(d,a);await p(this,f,dt).call(this,m)},ms=async function(e){let{fetchUrl:t,requestAbortController:s,headers:i}=e,o=n(this,be);c(this,Ye,Date.now());let a=re(E({},i),{Accept:"text/event-stream"});try{let h=[];await Vs(t.toString(),{headers:a,fetch:o,onopen:async d=>{c(this,k,!0),await p(this,f,Ht).call(this,d)},onmessage:d=>{if(d.data){let m=n(this,F),l=n(this,ae).parse(d.data,m);h.push(l),yt(l)&&(p(this,f,dt).call(this,h,!0),h=[])}},onerror:d=>{throw d},signal:s.signal})}catch(h){throw s.signal.aborted?new D:h}finally{let h=Date.now()-n(this,Ye),d=s.signal.aborted;if(h<n(this,Ve)&&!d)if(ke(this,X)._++,n(this,X)>=n(this,ut))c(this,Te,!0),console.warn("[Electric] SSE connections are closing immediately (possibly due to proxy buffering or misconfiguration). Falling back to long polling. Your proxy must support streaming SSE responses (not buffer the complete response). Configuration: Nginx add 'X-Accel-Buffering: no', Caddy add 'flush_interval -1' to reverse_proxy. Note: Do NOT disable caching entirely - Electric uses cache headers to enable request collapsing for efficiency.");else{let m=Math.min(n(this,pt),n(this,ft)*Math.pow(2,n(this,X))),l=Math.floor(Math.random()*m);await new Promise(g=>setTimeout(g,l))}else h>=n(this,Ve)&&c(this,X,0)}},It=function(){var e;n(this,O)&&n(this,w)==="active"&&(c(this,w,"pause-requested"),(e=n(this,U))==null||e.abort(At))},Bt=function(){var e;if(n(this,O)&&(n(this,w)==="paused"||n(this,w)==="pause-requested")){if((e=this.options.signal)!=null&&e.aborted)return;n(this,w)==="pause-requested"&&c(this,w,"active"),p(this,f,$e).call(this)}},gs=async function(){return n(this,q)?n(this,q):(c(this,q,new Promise((e,t)=>{c(this,_e,e),c(this,G,t)})),n(this,q).finally(()=>{c(this,q,void 0),c(this,_e,void 0),c(this,G,void 0)}),n(this,q))},Es=async function(){if(n(this,oe))return n(this,$)?n(this,$):(c(this,$,new Promise(e=>{c(this,we,e)})),n(this,$).finally(()=>{c(this,$,void 0),c(this,we,void 0)}),n(this,$))},Nt=async function(e){return c(this,Ae,n(this,Ae).then(()=>Promise.all(Array.from(n(this,W).values()).map(async([t,s])=>{try{await t(e)}catch(i){queueMicrotask(()=>{throw i})}})))),n(this,Ae)},Ft=function(e){n(this,W).forEach(([t,s])=>{s==null||s(e)})},ys=function(){if(typeof document=="object"&&typeof document.hidden=="boolean"&&typeof document.addEventListener=="function"){let e=()=>{document.hidden?p(this,f,It).call(this):p(this,f,Bt).call(this)};document.addEventListener("visibilitychange",e),c(this,We,()=>{document.removeEventListener("visibilitychange",e)})}},Ss=function(e){c(this,B,"-1"),c(this,N,""),c(this,T,e),c(this,v,!1),c(this,oe,!0),c(this,k,!1),c(this,F,void 0),c(this,z,0),c(this,X,0),c(this,Te,!1),c(this,Y,void 0),c(this,Z,0)},Rs=function(e){var s,i,o,a;let t={};return e.whereExpr?(t.where=Fe(e.whereExpr,(s=this.options.columnMapper)==null?void 0:s.encode),t.where_expr=e.whereExpr):e.where&&typeof e.where=="string"&&(t.where=he(e.where,(i=this.options.columnMapper)==null?void 0:i.encode)),e.params&&(t.params=e.params),e.limit!==void 0&&(t.limit=e.limit),e.offset!==void 0&&(t.offset=e.offset),e.orderByExpr?(t.order_by=ct(e.orderByExpr,(o=this.options.columnMapper)==null?void 0:o.encode),t.order_by_expr=e.orderByExpr):e.orderBy&&typeof e.orderBy=="string"&&(t.order_by=he(e.orderBy,(a=this.options.columnMapper)==null?void 0:a.encode)),t},Lt.Replica={FULL:"full",DEFAULT:"default"};function ds(r,e){let t=r.get(Rt);if(!t){if(e!=null&&e.required&&(e!=null&&e.url))throw new ne(e.url,[Rt]);return{}}return JSON.parse(t)}function bs(r){if(!r)return;let e=Object.keys(r).filter(t=>Ws.has(t));if(e.length>0)throw new Xe(e)}function Gs(r){if(!r.url)throw new Ge;if(r.signal&&!(r.signal instanceof AbortSignal))throw new ze;if(r.offset!==void 0&&r.offset!=="-1"&&r.offset!=="now"&&!r.handle)throw new Je;bs(r.params)}function P(r,e,t){if(!(t===void 0||t==null))if(typeof t=="string")r.searchParams.set(e,t);else if(typeof t=="object")for(let[s,i]of Object.entries(t))r.searchParams.set(`${e}[${s}]`,i);else r.searchParams.set(e,t.toString())}function zs(r){return Array.isArray(r.params)?re(E({},r),{params:Object.fromEntries(r.params.map((e,t)=>[t+1,e]))}):r}var M,ee,te,Ke,Me,ve,se,_,_s,As,$t,mt,ws,jt,xs=class{constructor(e){u(this,_);u(this,M,new Map);u(this,ee,new Map);u(this,te,new Set);u(this,Ke,new Set);u(this,Me,!1);u(this,ve,"syncing");u(this,se,!1);this.stream=e,this.stream.subscribe(p(this,_,_s).bind(this),p(this,_,ws).bind(this))}get isUpToDate(){return n(this,ve)==="up-to-date"}get lastOffset(){return this.stream.lastOffset}get handle(){return this.stream.shapeHandle}get rows(){return this.value.then(e=>Array.from(e.values()))}get currentRows(){return Array.from(this.currentValue.values())}get value(){return new Promise((e,t)=>{if(this.stream.isUpToDate)e(this.currentValue);else{let s=this.subscribe(({value:i})=>{s(),n(this,se)&&t(n(this,se)),e(i)})}})}get currentValue(){return n(this,M)}get error(){return n(this,se)}lastSyncedAt(){return this.stream.lastSyncedAt()}lastSynced(){return this.stream.lastSynced()}isLoading(){return this.stream.isLoading()}isConnected(){return this.stream.isConnected()}get mode(){return this.stream.mode}async requestSnapshot(e){let t=JSON.stringify(e);n(this,Ke).add(t),await p(this,_,$t).call(this),await this.stream.requestSnapshot(e)}subscribe(e){let t={};return n(this,ee).set(t,e),()=>{n(this,ee).delete(t)}}unsubscribeAll(){n(this,ee).clear()}get numSubscribers(){return n(this,ee).size}};M=new WeakMap,ee=new WeakMap,te=new WeakMap,Ke=new WeakMap,Me=new WeakMap,ve=new WeakMap,se=new WeakMap,_=new WeakSet,_s=function(e){let t=!1;e.forEach(s=>{if(le(s))if(t=p(this,_,mt).call(this,"syncing"),this.mode==="full")switch(s.headers.operation){case"insert":n(this,M).set(s.key,s.value);break;case"update":n(this,M).set(s.key,E(E({},n(this,M).get(s.key)),s.value));break;case"delete":n(this,M).delete(s.key);break}else switch(s.headers.operation){case"insert":n(this,te).add(s.key),n(this,M).set(s.key,s.value);break;case"update":n(this,te).has(s.key)&&n(this,M).set(s.key,E(E({},n(this,M).get(s.key)),s.value));break;case"delete":n(this,te).has(s.key)&&(n(this,M).delete(s.key),n(this,te).delete(s.key));break}if(st(s))switch(s.headers.control){case"up-to-date":t=p(this,_,mt).call(this,"up-to-date"),n(this,Me)&&(c(this,Me,!1),p(this,_,As).call(this));break;case"must-refetch":n(this,M).clear(),n(this,te).clear(),c(this,se,!1),t=p(this,_,mt).call(this,"syncing"),c(this,Me,!0);break}}),t&&p(this,_,jt).call(this)},As=async function(){await p(this,_,$t).call(this),await Promise.all(Array.from(n(this,Ke)).map(async e=>{try{let t=JSON.parse(e);await this.stream.requestSnapshot(t)}catch(t){}}))},$t=async function(){this.stream.isUpToDate||await new Promise(e=>{let t=()=>{this.stream.isUpToDate&&(clearInterval(s),i(),e())},s=setInterval(t,10),i=this.stream.subscribe(()=>t(),()=>t());t()})},mt=function(e){let t=n(this,ve)!==e;return c(this,ve,e),t&&e==="up-to-date"},ws=function(e){e instanceof A&&(c(this,se,e),p(this,_,jt).call(this))},jt=function(){n(this,ee).forEach(e=>{e({value:this.currentValue,rows:this.currentRows})})};export{ot as BackoffDefaults,Mt as ELECTRIC_PROTOCOL_QUERY_PARAMS,A as FetchError,xs as Shape,Lt as ShapeStream,Jt as camelToSnake,Fe as compileExpression,ct as compileOrderBy,Xt as createColumnMapper,le as isChangeMessage,st as isControlMessage,St as isVisibleInSnapshot,qt as resolveValue,Ls as snakeCamelMapper,Et as snakeToCamel};
|
|
6
6
|
//# sourceMappingURL=index.browser.mjs.map
|