UNPKG

@electric-sql/y-electric

Version:

YJS network provider for ElectricSQL

2 lines 7.5 kB
var x=Object.defineProperty,P=Object.defineProperties;var H=Object.getOwnPropertyDescriptors;var S=Object.getOwnPropertySymbols;var T=Object.prototype.hasOwnProperty,E=Object.prototype.propertyIsEnumerable;var y=(n,t,e)=>t in n?x(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e,u=(n,t)=>{for(var e in t||(t={}))T.call(t,e)&&y(n,e,t[e]);if(S)for(var e of S(t))E.call(t,e)&&y(n,e,t[e]);return n},g=(n,t)=>P(n,H(t));import*as h from"lib0/encoding";import*as f from"lib0/decoding";import*as c from"y-protocols/awareness";import{ObservableV2 as O}from"lib0/observable";import*as w from"lib0/environment";import*as d from"yjs";import{isChangeMessage as v,isControlMessage as V,ShapeStream as b}from"@electric-sql/client";var A=class extends O{constructor({doc:e,documentUpdates:s,awarenessUpdates:r,resumeState:a,connect:i=!0,fetchClient:o,debounceMs:p}){var l;super();this._connected=!1;this._synced=!1;this.sendingPendingChanges=!1;this.pendingChanges=null;this.sendingAwarenessState=!1;this.pendingAwarenessUpdate=null;this.debounceTimer=null;this.doc=e,this.documentUpdates=s,this.awarenessUpdates=r,this.resumeState=a!=null?a:{},this.debounceMs=p!=null?p:0,this.fetchClient=o,this.exitHandler=()=>{w.isNode&&typeof process!="undefined"&&process.on("exit",this.destroy.bind(this))},this.documentUpdateHandler=this.doc.on("update",this.applyDocumentUpdate.bind(this)),this.awarenessUpdates&&(this.awarenessUpdateHandler=this.applyAwarenessUpdate.bind(this),this.awarenessUpdates.protocol.on("update",this.awarenessUpdateHandler)),(l=this.resumeState)!=null&&l.stableStateVector&&(this.pendingChanges=d.encodeStateAsUpdate(this.doc,this.resumeState.stableStateVector)),i&&this.connect()}get synced(){return this._synced}set synced(e){this._synced!==e&&(this._synced=e,this.emit("synced",[e]),this.emit("sync",[e]))}set connected(e){this._connected!==e&&(this._connected=e,e&&this.sendOperations(),this.emit("status",[{status:e?"connected":"disconnected"}]))}get connected(){return this._connected}batch(e){this.pendingChanges?this.pendingChanges=d.mergeUpdates([this.pendingChanges,e]):this.pendingChanges=e}clearDebounceTimer(){this.debounceTimer!==null&&(clearTimeout(this.debounceTimer),this.debounceTimer=null)}scheduleSendOperations(){this.debounceMs>0?this.debounceTimer===null&&(this.debounceTimer=setTimeout(async()=>{this.debounceTimer=null,await this.sendOperations(),this.pendingChanges&&this.connected&&!this.sendingPendingChanges&&this.scheduleSendOperations()},this.debounceMs)):this.sendOperations()}destroy(){var e;this.clearDebounceTimer(),this.disconnect(),this.doc.off("update",this.documentUpdateHandler),(e=this.awarenessUpdates)==null||e.protocol.off("update",this.awarenessUpdateHandler),w.isNode&&typeof process!="undefined"&&process.off("exit",this.exitHandler),super.destroy()}disconnect(){var e;this.clearDebounceTimer(),this.pendingChanges&&this.connected&&this.sendOperations(),(e=this.unsubscribeShapes)==null||e.call(this),this.connected&&(this.awarenessUpdates&&(c.removeAwarenessStates(this.awarenessUpdates.protocol,Array.from(this.awarenessUpdates.protocol.getStates().keys()).filter(s=>s!==this.awarenessUpdates.protocol.clientID),this),c.removeAwarenessStates(this.awarenessUpdates.protocol,[this.awarenessUpdates.protocol.clientID],"local"),this.awarenessUpdates.protocol.setLocalState({})),this.emit("connection-close",[]),this.pendingAwarenessUpdate=null,this.connected=!1,this.synced=!1)}connect(){if(this.connected)return;let e=new AbortController,s=new b(g(u(u({},this.documentUpdates.shape),this.resumeState.document),{signal:e.signal})),r=s.subscribe(i=>{this.operationsShapeHandler(i,s.lastOffset,s.shapeHandle)}),a;this.awarenessUpdates&&(a=new b(g(u({},this.awarenessUpdates.shape),{signal:e.signal,offset:"now"})).subscribe(o=>{this.awarenessShapeHandler(o)})),this.unsubscribeShapes=()=>{e.abort(),r(),a==null||a(),this.unsubscribeShapes=void 0},this.emit("status",[{status:"connecting"}])}operationsShapeHandler(e,s,r){for(let a of e)if(v(a)){let i=this.documentUpdates.getUpdateFromRow(a.value);for(;i.pos!==i.arr.length;){let o=f.readVarUint8Array(i);d.applyUpdate(this.doc,o,"server")}}else V(a)&&a.headers.control==="up-to-date"&&(this.resumeState.document={offset:s,handle:r},this.sendingPendingChanges||(this.synced=!0,this.resumeState.stableStateVector=d.encodeStateVector(this.doc)),this.emit("resumeState",[this.resumeState]),this.connected=!0)}async applyDocumentUpdate(e,s){s!=="server"&&(this.batch(e),this.scheduleSendOperations())}async sendOperations(){var e;if(this.clearDebounceTimer(),!(!this.connected||this.sendingPendingChanges))try{for(this.sendingPendingChanges=!0;this.pendingChanges&&this.pendingChanges.length>2&&this.connected;){let s=this.pendingChanges;this.pendingChanges=null;let r=h.createEncoder();h.writeVarUint8Array(r,s),await R(r,this.documentUpdates.sendUrl,(e=this.fetchClient)!=null?e:fetch,this.documentUpdates.sendErrorRetryHandler)||(this.batch(s),this.disconnect())}this.resumeState.stableStateVector=d.encodeStateVector(this.doc),this.emit("resumeState",[this.resumeState])}finally{this.sendingPendingChanges=!1}}async applyAwarenessUpdate(e,s){var r;if(!(s!=="local"||!this.connected)&&(this.pendingAwarenessUpdate=e,!this.sendingAwarenessState)){this.sendingAwarenessState=!0;try{for(;this.pendingAwarenessUpdate&&this.connected;){let a=this.pendingAwarenessUpdate;this.pendingAwarenessUpdate=null;let{added:i,updated:o,removed:p}=a,l=i.concat(o).concat(p),U=h.createEncoder();h.writeVarUint8Array(U,c.encodeAwarenessUpdate(this.awarenessUpdates.protocol,l)),await R(U,this.awarenessUpdates.sendUrl,(r=this.fetchClient)!=null?r:fetch,this.awarenessUpdates.sendErrorRetryHandler)||this.disconnect()}}finally{this.sendingAwarenessState=!1}}}awarenessShapeHandler(e){for(let s of e)if(v(s))if(s.headers.operation==="delete")c.removeAwarenessStates(this.awarenessUpdates.protocol,[Number(s.value.client_id)],"remote");else{let r=this.awarenessUpdates.getUpdateFromRow(s.value);c.applyAwarenessUpdate(this.awarenessUpdates.protocol,f.readVarUint8Array(r),this)}}};async function R(n,t,e,s){var i;let r,a=h.toUint8Array(n);try{if(r=await e(t,{method:"PUT",headers:{"Content-Type":"application/octet-stream"},body:a}),!r.ok)throw new Error("Server did not return 2xx");return!0}catch(o){return await((i=s==null?void 0:s({response:r,error:o}))!=null?i:!1)}}import{ObservableV2 as W}from"lib0/observable.js";import*as m from"lib0/buffer";var C=class extends W{constructor(t){super(),this.key=t}subscribeToResumeState(t){let e=t.on("resumeState",this.save.bind(this));return()=>t.off("resumeState",e)}save(t){let e=JSON.stringify({operations:t.document});if(localStorage.setItem(this.key,e),t.stableStateVector){let s=m.toBase64(t.stableStateVector);localStorage.setItem(`${this.key}_vector`,s)}else localStorage.removeItem(`${this.key}_vector`)}load(){if(this.resumeState)return this.resumeState;let t=localStorage.getItem(this.key);if(!t)this.emit("synced",[{}]);else{this.resumeState=JSON.parse(t);let e=localStorage.getItem(`${this.key}_vector`);e&&(this.resumeState.stableStateVector=m.fromBase64(e)),this.emit("synced",[this.resumeState])}return this.resumeState}};import*as D from"lib0/decoding";var k=n=>{let t=n.startsWith("\\x")?n.slice(2):n;return new Uint8Array(t.match(/.{1,2}/g).map(e=>parseInt(e,16)))},z={bytea:n=>{let t=k(n);return D.createDecoder(t)}};export{A as ElectricProvider,C as LocalStorageResumeStateProvider,z as parseToDecoder}; //# sourceMappingURL=index.browser.mjs.map