@verdant-web/store 3.1.0 → 3.1.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.
@@ -12,5 +12,5 @@ list should be an Array.`),a.length===0)return new w(0);if(a.length===1)return a
12
12
  - Changed collections: ${o.changedCollections.join(", ")}
13
13
  - New indexes: ${Object.keys(o.addedIndexes).map(u=>o.addedIndexes[u].map(m=>`${u}.${m.name}`)).flatMap(u=>u).join(", ")}
14
14
  - Removed indexes: ${Object.keys(o.removedIndexes).map(u=>o.removedIndexes[u].map(m=>`${u}.${m.name}`)).flatMap(u=>u).join(", ")}
15
- `)}})}function Gi({migration:r,meta:t,getMigrationNow:e,newOids:n}){return r.allCollections.reduce((i,o)=>(i[o]={put:async s=>{Pe(r.newSchema.collections[o],s);let c=s[r.newSchema.collections[o].primaryKey],p=Z(o,c);return n.push(p),await t.insertLocalOperations(Fe(s,p,e)),s},delete:async s=>{let c=Z(o,s),p=await t.getAllDocumentRelatedOids(c);return t.insertLocalOperations(p.map(u=>({oid:u,timestamp:e(),data:{op:"delete"}})))}},i),{})}function qs({migration:r,context:t,meta:e}){return r.oldCollections.reduce((n,i)=>(n[i]={get:async o=>{let s=Z(i,o);return await e.getDocumentSnapshot(s,{to:e.time.now(r.oldSchema.version)})},findOne:async o=>{let s=await an({collection:i,index:o,context:t});return s?await e.getDocumentSnapshot(s,{to:e.time.now(r.oldSchema.version)}):null},findAll:async o=>{let s=await cn({collection:i,index:o,context:t});return await Promise.all(s.map(p=>e.getDocumentSnapshot(p,{to:e.time.now(r.oldSchema.version)})))}},n),{})}function Hs({meta:r,migration:t,context:e}){function n(){return r.time.zero(t.version)}let i=new Array,o=qs({migration:t,context:e,meta:r}),s=Gi({migration:t,getMigrationNow:n,newOids:i,meta:r}),c=async m=>{let S=await r.getAllCollectionRelatedOids(m);return r.insertLocalOperations(S.map(g=>({oid:g,timestamp:n(),data:{op:"delete"}})))},p=new Array;return{log:e.log,newOids:i,deleteCollection:c,migrate:async(m,S)=>{let g=await o[m].findAll();await Promise.all(g.filter(Boolean).map(async _=>{let w=ne(_);L(!!w,`Document is missing an OID: ${JSON.stringify(_)}`);let v=ae(_),I=await S(_);if(I){ft(v),ft(I),Ge(I);let x=ht(v,I,n,void 0,[],{mergeUnknownObjects:!0});x.length>0&&await r.insertLocalOperations(x)}}))},queries:o,mutations:s,awaitables:p}}function Ws({meta:r,migration:t,context:e}){function n(){return r.time.zero(t.version)}let i=new Array,o=new Proxy({},{get(){throw new Error("Queries are not available in initial migrations; there is no database yet!")}}),s=Gi({migration:t,getMigrationNow:n,newOids:i,meta:r});return{log:e.log,newOids:i,deleteCollection:()=>{throw new Error("Calling deleteCollection() in initial migrations is not supported! Use initial migrations to seed initial data using mutations.")},migrate:()=>{throw new Error("Calling migrate() in initial migrations is not supported! Use initial migrations to seed initial data using mutations.")},queries:o,mutations:s,awaitables:[]}}async function Qs(r){return new Promise((t,e)=>{let n=r.getAllKeys();n.onsuccess=i=>{t(n.result)},n.onerror=i=>{e(n.error)}})}async function Js(r,t){let e=r.delete(t);return new Promise((n,i)=>{e.onsuccess=o=>{n()},e.onerror=o=>{i(e.error)}})}async function Ys(r,t){let e=r.put(t);return new Promise((n,i)=>{e.onsuccess=o=>{n()},e.onerror=o=>{i(e.error)}})}async function Gs({meta:r,currentVersion:t,newVersion:e}){let n=[];return await r.operations.iterateOverAllOperations(i=>n.push(i),{from:r.time.zero(t+1)}),Array.from(new Set(n.map(i=>$(i.oid))))}var St=class extends V{constructor(){super(...arguments);this._undoable=[];this._undone=[];this.undo=async()=>{let e=this._undoable.pop();if(e){let n=await e();return n&&this._undone.push(n),this.emit("change"),!0}return!1};this.redo=async()=>{let e=this._undone.pop();if(e){let n=await e();return n&&this._undoable.push(n),this.emit("change"),!0}return!1};this.addUndo=e=>{this._undoable.push(e),this._undone=[],this.emit("change")};this.addRedo=e=>{this._undone.push(e),this.emit("change")};this.clear=()=>{this._undoable=[],this._undone=[],this.emit("change")}}get canUndo(){return this._undoable.length>0}get canRedo(){return this._undone.length>0}};var un=class{constructor(t,e,n){this.meta=t;this.schema=e;this.entities=n;this.getOid=(t,e)=>{let n=this.schema.collections[t].primaryKey,i=e[n];return L(i,`Document must have a primary key: ${n.toString()} (got: ${JSON.stringify(e)})`),Z(t,i)};this.addDefaults=(t,e)=>{let n=this.schema.collections[t];return Pe(n,e)};this.create=(t,e,n={})=>{let i=this.addDefaults(t,e),o=this.getOid(t,i);return this.entities.create(i,o,n)};this.delete=async(t,e,n={})=>{let i=Z(t,e);return this.entities.delete(i,n)};this.deleteAll=async(t,e={})=>this.entities.deleteAll(t.map(([n,i])=>Z(n,i)),e);this.deleteAllFromCollection=async(t,e,n={})=>this.entities.deleteAll(e.map(i=>Z(t,i)),n)}};var et=Symbol("entity-file-update"),xt=Symbol("entity-file-mark-failed"),Xs,Zs,de=class extends V{constructor(e,{downloadRemote:n=!1}={}){super();this.id=e;this._objectUrl=null;this._fileData=null;this._loading=!0;this._failed=!1;this._downloadRemote=!1;this[Xs]=e=>{this._loading=!1,this._failed=!1,this._fileData=e,e.file&&(this._objectUrl&&URL.revokeObjectURL(this._objectUrl),this._objectUrl=URL.createObjectURL(e.file)),this.emit("change")};this[Zs]=()=>{this._failed=!0,this._loading=!1,this.emit("change")};this.destroy=()=>{this._objectUrl&&URL.revokeObjectURL(this._objectUrl),this.dispose()};this._downloadRemote=n}static{Xs=et,Zs=xt}get downloadRemote(){return this._downloadRemote}get url(){return this.loading?null:this._objectUrl?this._objectUrl:this._fileData?.url??null}get name(){return this._fileData?.name??null}get type(){return this._fileData?.type??null}get loading(){return this._loading}get failed(){return this._failed}getSnapshot(){return{id:this.id,url:this.loading||this.failed?void 0:this.url}}};var Xi=Qe(at(),1);function ea(r){return{id:(0,Xi.default)(),file:r,url:void 0,remote:!1,name:r.name,type:r.type}}function Er(r){return r instanceof File||typeof Blob<"u"&&r instanceof Blob}function tt(r,t){if(typeof window<"u"&&Er(r)){let e=ea(r);return t(e),Mt(e.id)}if(Array.isArray(r)){for(let e=0;e<r.length;e++)r[e]=tt(r[e],t);return r}if(typeof r=="object"){for(let e in r)r[e]=tt(r[e],t);return r}return r}function Zi(r){return new Promise((t,e)=>{let n=new FileReader;n.onload=()=>{t(n.result)},n.onerror=e,n.readAsArrayBuffer(r)})}var fn=class extends se{constructor(){super(...arguments);this.addFile=async(e,{transaction:n,downloadRemote:i=!1}={})=>{let o=e.file?await Zi(e.file):void 0;if(!o&&i&&e.url)try{o=await fetch(e.url,{method:"GET",credentials:"include"}).then(s=>s.arrayBuffer())}catch(s){console.error("Failed to download file to cache it locally. The file will still be available using its URL. Check the file server's CORS configuration.",s)}return this.run("files",s=>s.put({id:e.id,remote:e.remote?"true":"false",deletedAt:null,name:e.name,type:e.type,url:e.url,buffer:o}),{mode:"readwrite",transaction:n})};this.hydrateFileData=e=>{e.remote=e.remote==="true";let n=e.buffer;return delete e.buffer,e.file=n?ta(n,e.type):void 0,e};this.markUploaded=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(!i)throw new Error("File is not in local database");return this.run("files",o=>o.put({...i,remote:"true"}),{mode:"readwrite",transaction:n})};this.getFileRaw=async(e,{transaction:n}={})=>{let i=await this.run("files",o=>o.get(e),{mode:"readonly",transaction:n});if(i)return i};this.getFile=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(i)return this.hydrateFileData(i)};this.markPendingDelete=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(!i)throw new Error("File is not in local database");return this.run("files",o=>o.put({...i,deletedAt:Date.now()}),{mode:"readwrite",transaction:n})};this.listUnsynced=async()=>(await this.run("files",n=>n.index("remote").getAll("false"),{mode:"readonly"})).map(this.hydrateFileData);this.iterateOverPendingDelete=(e,n)=>this.iterate("files",i=>i.index("deletedAt").openCursor(IDBKeyRange.lowerBound(0,!0)),(i,o)=>{e(this.hydrateFileData(i),o)},{mode:"readwrite",transaction:n})}deleteFile(e,{transaction:n}={}){return this.run("files",i=>i.delete(e),{mode:"readwrite",transaction:n})}};function ta(r,t){return new Blob([r],{type:t})}function na(r){return r.deletedAt!==null&&r.deletedAt<Date.now()-1e3*60*24*3}var pn=class{constructor({db:t,sync:e,context:n,meta:i,config:o={}}){this.files=new Map;this.add=async t=>{let e=t;if(e.remote=!1,this.files.has(e.id))this.files.get(e.id)[et](e);else{let n=new de(e.id);n[et](e),this.files.set(e.id,n)}await this.storage.addFile(e),e.file&&((await this.sync.uploadFile(e)).success?await this.storage.markUploaded(e.id):this.context.log("error","Failed to upload file"))};this.uploadFile=async(t,e=0)=>{let n=await this.sync.uploadFile(t);n.success?await this.storage.markUploaded(t.id):n.retry&&e<5?(this.context.log("error","Error uploading file, retrying..."),setTimeout(this.uploadFile,1e3,t,e+1)):this.context.log("error","Failed to upload file. Not retrying until next sync.")};this.get=(t,e)=>{if(this.files.has(t))return this.files.get(t);let n=new de(t,e);return this.files.set(t,n),this.load(n),n};this.load=async(t,e=0)=>{if(e>5){this.context.log("error","Failed to load file after 5 retries"),t[xt]();return}let n=await this.storage.getFile(t.id);if(n)t[et](n);else try{let i=await this.sync.getFile(t.id);i.success?(t[et](i.data),await this.storage.addFile(i.data,{downloadRemote:t.downloadRemote})):(this.context.log("error","Failed to load file",i),t[xt](),i.retry&&setTimeout(this.load,1e3,t,e+1))}catch(i){this.context.log("error","Failed to load file",i),t[xt](),setTimeout(this.load,1e3,t,e+1)}};this.listUnsynced=async()=>this.storage.listUnsynced();this.onOnlineChange=async t=>{if(t){let e=await this.listUnsynced();await Promise.all(e.map(this.uploadFile))}};this.tryCleanupDeletedFiles=async()=>{let t=0,e=0;await this.storage.iterateOverPendingDelete((n,i)=>{this.config.canCleanupDeletedFile(n)?(t++,i.delete(n.id)):e++}),this.context.log("info",`Cleaned up ${t} files, skipped ${e} files`)};this.handleFileRefsDeleted=async t=>{let e=this.storage.createTransaction(["files"],{mode:"readwrite"});await Promise.all(t.map(async n=>{try{await this.storage.markPendingDelete(n.id,{transaction:e})}catch(i){this.context.log("error","Failed to mark file for deletion",i)}})),this.context.log("info",`Marked ${t.length} files as pending delete`)};this.storage=new fn(t),this.sync=e,this.context=n,this.meta=i,this.config={canCleanupDeletedFile:na,...o},this.sync.subscribe("onlineChange",this.onOnlineChange),this.meta.subscribe("filesDeleted",this.handleFileRefsDeleted),this.tryCleanupDeletedFiles()}};var hn=class{constructor({initial:t}={}){this.cache=new Map;this.get=t=>{if(this.cache.has(t.oid))return this.cache.get(t.oid);let e=new ue(t);return this.cache.set(t.oid,e),e};this.has=t=>this.cache.has(t);this.getFile=(t,e)=>{if(this.cache.has(t))return this.cache.get(t);let n=new de(t,e);return this.cache.set(t,n),n};this.getCached=t=>this.cache.get(t);if(t)for(let e of t)this.cache.set(e.oid,e)}};var ue=class r extends V{constructor({oid:e,schema:n,entityFamily:i,parent:o,ctx:s,metadataFamily:c,readonlyKeys:p,files:u,patchCreator:m,events:S}){super();this.fieldPath=[];this._viewData=void 0;this.validationError=void 0;this.cachedDeepUpdatedAt=null;this.wasDeletedLastChange=!1;this.cachedView=void 0;this.onAdd=(e,n)=>{n.oid===this.oid&&this.addConfirmedData(n)};this.onReplace=(e,n)=>{n.oid===this.oid&&this.replaceAllData(n)};this.onResetAll=()=>{this.resetAllData()};this.childIsNull=e=>{if(e instanceof r){let n=e.view;return n==null}return e==null};this.validate=Ni(()=>(this.validationError=Re({field:this.schema,value:this.rawView,fieldPath:this.fieldPath,depth:1})??void 0,this.validationError),()=>[this.viewData]);this.viewWithMappedChildren=e=>{let n=this.view;if(!n)return null;if(Array.isArray(n)){let i=n.map(o=>o instanceof r||o instanceof de?e(o):o);return K(i,this.oid),i}else{let i=Object.entries(n).reduce((o,[s,c])=>(c instanceof r||c instanceof de?o[s]=e(c):o[s]=c,o),{});return K(i,this.oid),i}};this.getSnapshot=()=>this.viewWithMappedChildren(e=>e.getSnapshot());this.addPendingOperations=e=>{this.ctx.log("debug","Entity: adding pending operations",this.oid);let n=this.metadataFamily.addPendingData(e);for(let i of n)this.change(i)};this.addConfirmedData=e=>{this.ctx.log("debug","Entity: adding confirmed data",this.oid);let n=this.metadataFamily.addConfirmedData(e);for(let i of n)this.change(i)};this.replaceAllData=e=>{this.ctx.log("debug","Entity: replacing all data",this.oid);let n=this.metadataFamily.replaceAllData(e);for(let i of n)this.change(i)};this.resetAllData=()=>{this.ctx.log("debug","Entity: resetting all data",this.oid),this.cachedDeepUpdatedAt=null,this.cachedView=void 0,this._viewData=void 0;let e=this.metadataFamily.replaceAllData({});for(let n of e)this.change(n)};this.change=e=>{if(e.oid===this.oid)this._viewData=void 0,this.cachedView=void 0,this.deepChange(this,e),this.ctx.log("Emitting change event",this.oid),this.emit("change",{isLocal:e.isLocal}),this.parent||(this.deleted&&!this.wasDeletedLastChange?(this.ctx.log("debug","Entity deleted",this.oid),this.emit("delete",{isLocal:e.isLocal}),this.wasDeletedLastChange=!0):!this.deleted&&this.wasDeletedLastChange&&(this.ctx.log("debug","Entity restored",this.oid),this.emit("restore",{isLocal:e.isLocal}),this.wasDeletedLastChange=!1));else{let n=this.entityFamily.getCached(e.oid);n&&n instanceof r&&n.change(e)}};this.deepChange=(e,n)=>{this.cachedDeepUpdatedAt=null,this.cachedView=void 0,this.ctx.log("debug","Deep change detected at",this.oid,"reset cached view"),this.ctx.log("debug","Emitting deep change event",this.oid),this.emit("changeDeep",e,n),this.parent?.deepChange(e,n)};this.getChild=(e,n)=>{let i=Ne(this.schema,e);if(!i)throw new Error(`No schema for key ${String(e)} in ${JSON.stringify(this.schema)}`);return this.entityFamily.get({oid:n,schema:i,entityFamily:this.entityFamily,metadataFamily:this.metadataFamily,parent:this,ctx:this.ctx,files:this.files,fieldPath:[...this.fieldPath,e],patchCreator:this.patchCreator,events:this.events})};this.get=e=>{eo(e);let n=this.rawView;if(!n)throw new Error(`Cannot access data at key ${e} on deleted entity ${this.oid}`);let i=n[e],o=Ne(this.schema,e);if(!o)throw new Error(`No schema for key ${String(e)} in ${JSON.stringify(this.schema)}`);if(Q(i))if(be(i)){if(o.type!=="file")throw new Error(`Expected file schema for key ${String(e)}, got ${o.type}`);let s=this.files.get(i.id,{downloadRemote:!!o.downloadRemote});return s.subscribe("change",()=>{this.deepChange(this,{isLocal:!1,oid:this.oid})}),s}else return this.getChild(e,i.id);else return Re({field:o,value:i,fieldPath:[...this.fieldPath,e],depth:1,requireDefaults:!0})?_e(o)?ur(o):we(o)?null:void 0:i};this.processInputValue=(e,n)=>{if(this.readonlyKeys.includes(n))throw new Error(`Cannot set readonly key ${n.toString()}`);Er(e)||(e=ae(e,!1));let i=Ne(this.schema,n);if(i){Le(e,i);let o=Re({field:i,value:e,fieldPath:[...this.fieldPath,n]});if(o)throw new Error(o.message)}return tt(e,this.files.add)};this.getDeleteMode=e=>{if(this.readonlyKeys.includes(e))return!1;if(this.schema.type==="any"||this.schema.type==="map")return"delete";if(this.schema.type==="object"){let n=this.schema.properties[e];if(!n||n.type==="any")return"delete";if(n.type==="map")return!1;if(n.nullable)return"null"}return!1};this.getItemRefValue=e=>{if(e instanceof r)return he(e.oid);if(e instanceof de)return Mt(e.id);if(typeof e=="object"){let n=pe(e);if(!n||!this.entityFamily.has(n))throw new Error(`Cannot move object ${JSON.stringify(e)} which does not exist in this list`);return he(n)}else return e};this.set=(e,n)=>{eo(e),this.addPendingOperations(this.patchCreator.createSet(this.oid,e,this.processInputValue(n,e)))};this.getAll=()=>this.view;this.delete=e=>{if(this.isList)ra(e),this.addPendingOperations(this.patchCreator.createListDelete(this.oid,e));else{let n=this.getDeleteMode(e);if(!n)throw new Error(`Cannot delete key ${e.toString()} - the property is not marked as optional in the schema.`);n==="delete"?this.addPendingOperations(this.patchCreator.createRemove(this.oid,e)):this.addPendingOperations(this.patchCreator.createSet(this.oid,e,null))}};this.keys=()=>this.view?Object.keys(this.view):[];this.entries=()=>this.view?Object.entries(this.view):[];this.values=()=>this.view?Object.values(this.view):[];this.update=(e,{merge:n=!0,replaceSubObjects:i=!1}={})=>{if(!n&&this.schema.type!=="any"&&this.schema.type!=="map")throw new Error('Cannot use .update without merge if the field has a strict schema type. merge: false is only available on "any" or "map" types.');let o={};K(o,this.oid);for(let[s,c]of Object.entries(e)){if(this.readonlyKeys.includes(s))throw new Error(`Cannot set readonly key ${s.toString()}`);let p=Ne(this.schema,s);p&&Le(c,p),o[s]=this.processInputValue(c,s)}this.addPendingOperations(this.patchCreator.createDiff(this.getSnapshot(),o,{mergeUnknownObjects:!i,defaultUndefined:n}))};this.push=e=>{this.addPendingOperations(this.patchCreator.createListPush(this.oid,this.processInputValue(e,this.view.length)))};this.insert=(e,n)=>{this.addPendingOperations(this.patchCreator.createListInsert(this.oid,e,this.processInputValue(n,e)))};this.move=(e,n)=>{this.addPendingOperations(this.patchCreator.createListMoveByIndex(this.oid,e,n))};this.moveItem=(e,n)=>{let i=this.getItemRefValue(e);if(Q(i))this.addPendingOperations(this.patchCreator.createListMoveByRef(this.oid,i,n));else{let o=this.view.indexOf(e);if(o===-1)throw new Error(`Cannot move item ${JSON.stringify(e)} which does not exist in this list`);this.move(o,n)}};this.add=e=>{this.addPendingOperations(this.patchCreator.createListAdd(this.oid,this.processInputValue(e,this.view.length)))};this.removeAll=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e)))};this.removeFirst=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e),"first"))};this.removeLast=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e),"last"))};this.map=e=>this.view.map(e);this.filter=e=>this.view.filter(e);this.has=e=>{if(!this.isList)throw new Error("has() is only available on list entities");let n=this.getItemRefValue(e);return Q(n)?this.view.some(i=>{if(Q(i))return Ye(i,n)}):this.view.includes(e)};this.forEach=e=>{this.view.forEach(e)};this.some=e=>this.view.some(e);this.every=e=>this.view.every(e);this.find=e=>this.view.find(e);this.includes=this.has;this.__getViewData__=(e,n)=>this.metadataFamily.get(e).computeView(n==="confirmed");this.__getFamilyOids__=()=>this.metadataFamily.getAllOids();L(!!e,"oid is required"),this.oid=e,this.readonlyKeys=p||[],this.ctx=s,this.files=u,this.schema=n,this.entityFamily=i||new hn({initial:[this]}),this.patchCreator=m,this.metadataFamily=c,this.events=S,this.parent=o,this.parent||(S.add.attach(this.onAdd),S.replace.attach(this.onReplace),S.resetAll.attach(this.onResetAll))}get metadata(){return this.metadataFamily.get(this.oid)}get viewData(){return this._viewData===void 0&&(this._viewData=this.metadata.computeView(),this.validate()),this._viewData}get rawView(){return this.viewData.view}get view(){if(this.cachedView!==void 0)return this.cachedView;if(this.viewData.deleted)return null;let e=this.rawView;if(!e&&!we(this.schema)||this.schema.type==="array"&&!Array.isArray(e)||(this.schema.type==="object"||this.schema.type==="map")&&!U(e))return _e(this.schema)?ur(this.schema):null;if(this.cachedView=this.isList?[]:{},K(this.cachedView,this.oid),Array.isArray(e)){let i=Ne(this.schema,0);if(!i)this.ctx.log("error","No child field schema for list entity.",this.oid);else for(let o=0;o<e.length;o++){let s=this.get(o);this.childIsNull(s)&&!we(i)?this.ctx.log("error","Child missing in non-nullable field",this.oid,"index:",o):this.cachedView.push(s)}}else if(U(e)){let i=this.schema.type==="object"?Object.keys(this.schema.properties):Object.keys(e);for(let o of i){let s=Ne(this.schema,o);if(!s){this.ctx.log("error","No child field schema for object entity at key",o),this.schema.type==="map"?this.cachedView={}:this.cachedView=null;break}let c=this.get(o);if(this.childIsNull(c)&&!we(s)){if(this.ctx.log("error","Child entity is missing for non-nullable field",this.oid,"key:",o),this.schema.type!=="map"){this.cachedView=null;break}}else this.cachedView[o]=c}}return this.cachedView}get uid(){return this.oid}get deleted(){return this.viewData.deleted||this.view===null}get invalid(){return!!this.validate()}get isList(){return this.schema.type==="array"||Array.isArray(this.viewData.view)}get updatedAt(){return this.viewData.updatedAt}get deepUpdatedAt(){if(this.cachedDeepUpdatedAt)return this.cachedDeepUpdatedAt;let e=this.updatedAt;return this.isList?this.forEach(n=>{if(n instanceof r){let i=n.deepUpdatedAt;i&&(!e||i>e)&&(e=i)}}):this.values().forEach(n=>{if(n instanceof r){let i=n.deepUpdatedAt;i&&(!e||i>e)&&(e=i)}}),this.cachedDeepUpdatedAt=e,e}get isOutdatedVersion(){return this.parent?this.parent.isOutdatedVersion:this.viewData.fromOlderVersion}get length(){return this.view.length}[Symbol.iterator](){let e=0,n=this.view?.length;return{next:()=>e<n?{value:this.get(e++),done:!1}:{value:void 0,done:!0}}}};function eo(r){if(typeof r=="symbol")throw new Error("Symbol keys aren't supported")}function ra(r){if(typeof r!="number")throw new Error("Only number keys are supported in list entities")}var Cr=class{constructor({oid:t,ctx:e,confirmedOperations:n,pendingOperations:i,baseline:o}){this.baseline=null;this.confirmedOperations=[];this.pendingOperations=[];this.computeView=(t=!1)=>{let e=ae(this.baseline?.snapshot??void 0),n=this.baseline?.timestamp??null,i=this.applyOperations(e,!e,this.confirmedOperations,n,n);i.futureSeen&&this.ctx.globalEvents.emit("futureSeen",i.futureSeen);let o=t?i:this.applyOperations(i.view,i.deleted,this.pendingOperations,i.latestTimestamp,null);o.view&&K(o.view,this.oid);let s=!!i.latestTimestamp&&Xn(i.latestTimestamp,this.ctx.getNow())<0,c=!this.baseline&&!this.pendingOperations.length&&!this.confirmedOperations.length;c&&this.ctx.log("warn",`Tried to load Entity ${this.oid} with no data`);let p=o.latestTimestamp??i.latestTimestamp??n,u=p?Zn(p):0;if(!o.view&&!o.deleted&&!c){this.ctx.log("warn",`Entity ${this.oid} has no view, no deleted flag, and not empty`);debugger}return{view:o.view??void 0,deleted:o.deleted,empty:c,fromOlderVersion:s,updatedAt:u}};this.addBaseline=t=>{if(!(this.baseline&&this.baseline.timestamp>=t.timestamp))for(this.baseline=t;this.confirmedOperations[0]?.timestamp<t.timestamp;)this.confirmedOperations.shift()};this.addConfirmedOperations=t=>{let e=0;for(let n of t){let i=this.confirmedOperations.findIndex(s=>s.timestamp>=n.timestamp);i!==-1?this.confirmedOperations[i].timestamp!==n.timestamp&&(this.confirmedOperations.splice(i,0,n),e++):(this.confirmedOperations.push(n),e++);let o=this.pendingOperations.length;this.pendingOperations=this.pendingOperations.filter(s=>n.timestamp!==s.timestamp),e-=o-this.pendingOperations.length}return e};this.addPendingOperation=t=>{this.pendingOperations.push(t)};this.applyOperations=(t,e,n,i,o)=>{let s,c=this.ctx.getNow();for(let p of n)if(!(o&&p.timestamp<=o)){if(Xn(p.timestamp,c)>0){s=p.timestamp;continue}p.data.op==="delete"?e=!0:(t=je(t,p.data),p.data.op==="initialize"&&(e=!1)),(!i||p.timestamp>i)&&(i=p.timestamp)}return{view:t,latestTimestamp:i??null,deleted:e,futureSeen:s}};L(t,"oid is required"),this.ctx=e,this.oid=t,n&&(this.confirmedOperations=n),i&&(this.pendingOperations=i),o&&(this.baseline=o)}},mn=class{constructor({ctx:t,onPendingOperations:e,rootOid:n}){this.entities=new Map;this.get=t=>(L(t,"oid is required"),this.entities.has(t)||this.entities.set(t,new Cr({oid:t,ctx:this.ctx})),this.entities.get(t));this.getAllOids=()=>Array.from(this.entities.keys());this.addConfirmedData=({baselines:t=[],operations:e={},isLocal:n=!1})=>{let i={};for(let o of t){if(!Ce(this.rootOid,o.oid))throw new Error(`Invalid baseline for entity ${this.rootOid}: `+JSON.stringify(o));this.get(o.oid).addBaseline(o)}for(let[o,s]of Object.entries(e)){if(!Ce(this.rootOid,o))throw new Error(`Invalid operations for entity ${this.rootOid}: `+JSON.stringify(s));this.get(o).addConfirmedOperations(s)!==0&&(i[o]??={oid:o,isLocal:n})}return Object.values(i)};this.addPendingData=t=>{let e={};for(let n of t)this.get(n.oid).addPendingOperation(n),e[n.oid]??={oid:n.oid,isLocal:!0};return this.onPendingOperations(t),Object.values(e)};this.replaceAllData=({operations:t={},baselines:e=[]})=>{let n=Array.from(this.entities.keys());this.entities.clear();let i={};for(let o of n)i[o]={oid:o,isLocal:!1};for(let o of e){if(!Ce(this.rootOid,o.oid))throw new Error(`Invalid baseline for entity ${this.rootOid}: `+JSON.stringify(o));this.get(o.oid).addBaseline(o),i[o.oid]??={oid:o.oid,isLocal:!1}}for(let[o,s]of Object.entries(t)){if(!Ce(this.rootOid,o))throw new Error(`Invalid operations for entity ${this.rootOid}: `+JSON.stringify(s));this.get(o).addConfirmedOperations(s),i[o]??={oid:o,isLocal:!1}}return Object.values(i)};this.ctx=t,this.rootOid=n,this.onPendingOperations=e}};var Ot="@@default",gn=class{constructor({batchTimeout:t=200,meta:e,ctx:n,entities:i}){this.currentBatchKey=Ot;this.flushOperations=async(t,e,n)=>{if(this.ctx.log("debug","Flushing",t.length,"operations from batch",e,"to storage / sync"),!!t.length){for(let i of t)i.timestamp=this.meta.now;await this.commitOperations(t,n)}};this.commitOperations=async(t,e)=>{if(t.length){if(e.undoable){let n=await this.createUndo({ops:t,source:e.source});n&&this.ctx.undoHistory.addUndo(n)}await this.entities.addData({operations:t,baselines:[],isLocal:!0})}};this.addOperations=t=>{t.length&&(this.batcher.add({key:this.currentBatchKey,items:t}),this.ctx.log("debug","added",t.length,"ops to batch",this.currentBatchKey,", size = ",this.batcher.getSize(this.currentBatchKey)))};this.batch=({undoable:t=!0,batchName:e=Nt(),max:n=null,timeout:i=this.defaultBatchTimeout}={})=>{let o=this.batcher.add({key:e,max:n,timeout:i,items:[],userData:{undoable:t}}),s={run:c=>(this.currentBatchKey=e,c(),this.currentBatchKey=Ot,s),commit:async()=>(await this.batcher.flush(Ot),o.flush()),flush:()=>s.commit(),discard:()=>{this.batcher.discard(e)}};return s};this.flushAll=()=>Promise.all(this.batcher.flushAll());this.createUndo=async t=>{let e=await this.getInverseOperations(t);return e.length?async()=>{let n=await this.createUndo({ops:e,source:t.source});for(let i of e)i.timestamp=this.meta.now;return await this.commitOperations(e,{undoable:!1}),n}:null};this.getInverseOperations=async({ops:t,source:e})=>{let n=mt(t),i=[],o=()=>this.meta.now;return await Promise.all(Object.entries(n).map(async([s,c])=>{let u=(e??await this.entities.hydrate($(s)))?.__getViewData__(s,"confirmed");if(!u){this.ctx.log("warn","could not find entity",s,"for undo operation",t);return}let m=Li(s,u.view,c,o);i.unshift(...m)})),i};this.meta=e,this.ctx=n,this.entities=i,this.defaultBatchTimeout=t,this.batcher=new Xe(this.flushOperations),this.batcher.add({key:Ot,items:[],max:100,timeout:t,userData:{undoable:!0}})}get isDefaultBatch(){return this.currentBatchKey===Ot}};var yn=class extends se{constructor({ctx:e}){super(e.documentDb,{log:e.log});this.reset=async()=>{let e=Object.keys(this.ctx.schema.collections),n=this.ctx.documentDb.transaction(e,"readwrite");await Promise.all(e.map(i=>{let o=n.objectStore(i);return J(o.clear())})),this.ctx.entityEvents.emit("collectionsChanged",e),this.ctx.log("info","\u{1F4A8} Reset queryable storage")};this.saveEntities=async(e,n)=>{if(e.length===0)return;let i=Array.from(new Set(e.map(s=>me(s.oid).collection))),o={transaction:this.createTransaction(i,{mode:"readwrite",abort:n?.abort})};await Promise.all(e.map(async s=>{let c=s.getSnapshot();try{await this.saveDocument(s.oid,c,o)}catch(p){throw this.ctx.log("error",`Error saving document ${s.oid} (${JSON.stringify(c)})`,p),p instanceof Error?p:new Error("Unknown error saving document")}})),o.transaction.commit(),this.ctx.entityEvents.emit("collectionsChanged",i);for(let s of e)this.ctx.entityEvents.emit("documentChanged",s.oid)};this.saveDocument=async(e,n,{transaction:i})=>{this.ctx.log("debug",`Saving document indexes for querying ${e}`,n);let{collection:o,id:s}=me(e);if(!n)await this.run(o,c=>c.delete(s),{mode:"readwrite",transaction:i}),this.ctx.log("debug",`Deleted document indexes for querying ${e}`);else{let c=this.ctx.schema.collections[o],p=Ht(c,n);await this.run(o,u=>u.put(p),{mode:"readwrite",transaction:i}),this.ctx.log("debug",`Saved document indexes for querying ${e}`,n)}};this.ctx=e,this.addDispose(this.ctx.internalEvents.subscribe("documentDbChanged",n=>{this.db=n}))}};var En=Qe(Bo(),1);var Cn=class extends Ie{constructor({ctx:e,meta:n,files:i}){super();this.events={add:new En.WeakEvent,replace:new En.WeakEvent,resetAll:new En.WeakEvent};this.cache=new Map;this.pendingEntityPromises=new Map;this.abortDataQueueController=new AbortController;this.ongoingResetPromise=null;this.entityFinalizationRegistry=new FinalizationRegistry(e=>{this.ctx.log("debug","Entity GC",e)});this.addData=async e=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not adding incoming data");return}e.reset&&(this.ctx.log("info","Resetting local store to replicate remote synced data - dropping any current transactions"),this.abortDataQueueController.abort(0),this.abortDataQueueController=new AbortController,this.ongoingResetPromise=this.resetData().finally(()=>{this.ongoingResetPromise=null})),this.ongoingResetPromise&&(this.ctx.log("debug","Waiting for ongoing reset to complete"),await this.ongoingResetPromise,this.ctx.log("debug","Ongoing reset complete")),await this.processData(e)};this.resetData=async()=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not resetting local data");return}await this.meta.reset(),await this.queryableStorage.reset(),this.events.resetAll.invoke(this)};this.processData=async e=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not processing incoming data");return}let n=e?.baselines??[],i=e?.operations??[];this.ctx.log("debug","Processing incoming data",{operations:i.length,baselines:n.length,reset:!!e.reset});let o=Array.from(new Set(n.map(m=>$(m.oid)).concat(i.map(m=>$(m.oid))))),s=Fi(n),c=Ti(i);this.ctx.log("debug","Applying data to live entities");for(let m of o){let S=s[m],g=c[m]??[],_=mt(g),w=e.reset?this.events.replace:this.events.add,v=this.pendingEntityPromises.get(m);v?v.then(()=>{w.invoke(this,{oid:m,baselines:S,operations:_,isLocal:!1})}):(this.cache.has(m)&&this.ctx.log("debug","Cache has",m,", an event should follow."),w.invoke(this,{oid:m,baselines:S,operations:_,isLocal:!1}))}let p={abort:this.abortDataQueueController.signal};await this.meta.insertData(e,p);let u=await Promise.all(o.map(async m=>await this.hydrate(m,p)??{oid:m,getSnapshot(){return null}}));try{await this.queryableStorage.saveEntities(u,p)}catch(m){this.disposed?this.ctx.log("warn","Error saving entities to queryable storage - EntityStore is disposed",m):this.ctx.log("error","Error saving entities to queryable storage",m)}};this.hydrate=async(e,n)=>{if(!Pi(e))throw new Error("Cannot hydrate non-root entity");if(this.cache.has(e)){this.ctx.log("debug","Hydrating entity from cache",e);let o=this.cache.get(e);if(o){let s=o.deref();if(s)return s.deleted?null:s;this.ctx.log("debug","Removing GC'd entity from cache",e),this.cache.delete(e)}}let i=this.pendingEntityPromises.get(e);if(i)return this.ctx.log("debug","Waiting for entity hydration",e),i;{this.ctx.log("debug","Hydrating entity from storage",e);let o=this.constructEntity(e);if(!o)return null;let s=this.loadEntity(o,n);return s.finally(()=>{this.pendingEntityPromises.delete(e)}),this.pendingEntityPromises.set(e,s),s}};this.destroy=async()=>{this.dispose(),await this.batcher.flushAll()};this.create=async(e,n,{undoable:i=!0}={})=>{this.ctx.log("debug","Creating new entity",n);let{collection:o}=me(n);Vt(e);let s=tt(e,this.files.add);K(s,n);let c=this.constructEntity(n);if(!c)throw new Error(`Could not put new document: no schema exists for collection ${o}`);let p=this.meta.patchCreator.createInitialize(s,n);await this.batcher.commitOperations(p,{undoable:!!i,source:c});let u=mt(p);return this.events.add.invoke(this,{operations:u,isLocal:!0,oid:n}),this.cache.set(n,this.ctx.weakRef(c)),c};this.deleteAll=async(e,n)=>{this.ctx.log("info","Deleting documents",e),L(e.every(s=>s===$(s)),"Only root documents may be deleted via client methods");let i=await Promise.all(e.flatMap(async s=>(await this.hydrate(s))?.__getFamilyOids__()??[]));e.forEach(s=>{this.cache.delete(s),this.ctx.log("debug","Deleted document from cache",s)});let o=this.meta.patchCreator.createDeleteAll(i.flat());await this.batcher.commitOperations(o,{undoable:n?.undoable===void 0?!0:n.undoable})};this.delete=async(e,n)=>this.deleteAll([e],n);this.getCollectionSchema=e=>{let n=this.ctx.schema.collections[e];return n?{schema:{type:"object",nullable:!1,properties:n.fields},readonlyKeys:[n.primaryKey]}:(this.ctx.log("warn",`Missing schema for collection: ${e}`),{schema:null,readonlyKeys:[]})};this.constructEntity=e=>{let{collection:n}=me(e),{schema:i,readonlyKeys:o}=this.getCollectionSchema(n);if(!i)return null;if(this.disposed)throw new Error("Cannot hydrate entity after store has been disposed");let s=new mn({ctx:this.ctx,onPendingOperations:this.onPendingOperations,rootOid:e});return new ue({ctx:this.ctx,oid:e,schema:i,readonlyKeys:o,files:this.files,metadataFamily:s,patchCreator:this.meta.patchCreator,events:this.events})};this.onPendingOperations=e=>{this.batcher.addOperations(e)};this.loadEntity=async(e,n)=>{let{operations:i,baselines:o}=await this.meta.getDocumentData(e.oid,n);return!o.length&&!Object.keys(i).length?(this.ctx.log("debug","No data found for entity",e.oid),null):(this.ctx.log("debug","Loaded entity from storage",e.oid),this.events.replace.invoke(this,{oid:e.oid,baselines:o,operations:i,isLocal:!1}),this.cache.set(e.oid,this.ctx.weakRef(e)),this.entityFinalizationRegistry.register(e,e.oid),e)};this.ctx=e,this.meta=n,this.files=i,this.queryableStorage=new yn({ctx:e}),this.batcher=new gn({ctx:e,meta:n,entities:this})}get batch(){return this.batcher.batch}get flushAllBatches(){return this.batcher.flushAll}};var Kr=Symbol("handleMessage"),wa,Dt=class extends V{constructor({initialPresence:e,updateBatchTimeout:n=200,defaultProfile:i}){super();this._peers={};this._self={profile:{}};this._selfReplicaIds=new Set;this._peerIds=new Array;this.isSelf=(e,n)=>e.id===n.replicaId||this._selfReplicaIds.has(n.replicaId)||this._self.id===n.id;this[wa]=async(e,n)=>{let i=!1,o=new Set(this.peerIds);if(n.type==="presence-changed")this.isSelf(e,n.userInfo)?(this._self=n.userInfo,this._selfReplicaIds.add(n.userInfo.replicaId),this.emit("selfChanged",n.userInfo)):(o.add(n.userInfo.id),this._peers[n.userInfo.id]=n.userInfo,i=!0,this.emit("peerChanged",n.userInfo.id,n.userInfo));else if(n.type==="sync-resp"){this._peers={},o.clear();for(let[s,c]of Object.entries(n.peerPresence))this.isSelf(e,c)?(this._self=c,this._selfReplicaIds.add(c.replicaId),this.emit("selfChanged",c)):(i=!0,o.add(s),this._peers[s]=c,this.emit("peerChanged",s,c))}else if(n.type==="presence-offline"){o.delete(n.userId),this._selfReplicaIds.delete(n.replicaId);let s=this._peers[n.userId];delete this._peers[n.userId],i=!0,this.emit("peerLeft",n.userId,s)}i&&(this._peerIds=Array.from(o),this.emit("peersChanged",this._peers))};this.update=async e=>{this._updateBatch.update({items:[e]}),this.self.presence={...this.self.presence,...e},this.emit("selfChanged",this.self)};this.flushPresenceUpdates=e=>{let n=e.reduce((i,o)=>({...i,...o}),this.self.presence);this.emit("update",n)};this.self.presence=e,this.self.profile=i,this._updateBatcher=new Xe(this.flushPresenceUpdates),this._updateBatch=this._updateBatcher.add({max:25,timeout:n,items:[],key:"default"})}static{wa=Kr}get self(){return this._self}get peers(){return this._peers}get peerIds(){return this._peerIds}get everyone(){let e={...this._peers};return e[this.self.id]=this.self,e}get selfReplicaIds(){return this._selfReplicaIds}};var _n=class{constructor({endpointProvider:t,log:e}){this.uploadFile=async t=>{let e=t.file;if(!e)throw new Error("Cannot upload a non-local file");let{files:n,token:i}=await this.endpointProvider.getEndpoints(),o=new window.FormData;o.append("file",e);try{let s=await fetch(n+`/${t.id}`,{method:"POST",body:o,credentials:"include",headers:{Authorization:`Bearer ${i}`}});return s.ok?{success:!0,retry:!1}:(this.log("error","File upload failed",s.status,await s.text()),{success:!1,retry:s.status>=500})}catch(s){return this.log("error","File upload failed",s),{success:!1,retry:!0}}};this.getFile=async t=>{let{files:e,token:n}=await this.endpointProvider.getEndpoints();try{let i=await fetch(e+`/${t}`,{method:"GET",credentials:"include",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});return i.ok?{success:!0,data:await i.json()}:(this.log("error","File information fetch failed",i.status,await i.text()),{success:!1,retry:i.status>=500||i.status===404})}catch(i){return this.log("error","File information fetch failed",i),{success:!1,error:i,retry:!0}}};this.endpointProvider=t,this.log=e}};var rt=class extends V{constructor({interval:e=15*1e3,deadlineLength:n=3*1e3,restartOnTabFocus:i=!0}={}){super();this.nextBeat=null;this.deadline=null;this.keepAlive=()=>{this.deadline&&(clearTimeout(this.deadline),this.deadline=null,this.start())};this.start=(e=!1)=>{this.stop(),e?this.beat():this.nextBeat=setTimeout(this.beat,this._interval)};this.stop=()=>{this.nextBeat&&clearTimeout(this.nextBeat),this.deadline&&clearTimeout(this.deadline)};this.beat=async()=>{this.emit("beat"),this.deadline=setTimeout(this.onDeadline,this.deadlineLength)};this.onDeadline=()=>{this.deadline=null,this.emit("missed")};this.setInterval=e=>{this._interval=e};this._interval=e,this.deadlineLength=n,typeof window<"u"&&i&&(window.addEventListener("pageshow",()=>this.start(!0)),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&this.start(!0)}))}get interval(){return this._interval}};var Pn=class extends V{constructor({endpointProvider:e,meta:n,presence:i,interval:o=15*1e3,log:s=()=>{}}){super();this.mode="pull";this._isConnected=!1;this._status="paused";this._hasSynced=!1;this.setInterval=e=>{this.heartbeat.setInterval(e)};this.sendRequest=async e=>{this.log("Sending sync request",e);try{let{http:n,token:i}=await this.endpointProvider.getEndpoints(),o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({messages:e}),credentials:"include"});if(o.ok){this.heartbeat.keepAlive();let s=await o.json();for(let c of s.messages)this.handleServerMessage(c);this._isConnected||(this._isConnected=!0,this.emit("onlineChange",!0))}else{this.log("Sync request failed",o.status,await o.text()),this._isConnected&&(this._isConnected=!1,this.emit("onlineChange",!1));let s=await o.json();Ui(s)&&s.code===4012&&(this.endpointProvider.clearCache(),this.heartbeat.keepAlive()),o.status>=500&&this.heartbeat.keepAlive()}}catch(n){this._isConnected&&(this._isConnected=!1,this.emit("onlineChange",!1)),this.log(n),this.heartbeat.keepAlive()}};this.handleServerMessage=async e=>{e.type==="sync-resp"&&(e.ackThisNonce&&(this.log("Sending sync ack",e.ackThisNonce),this.sendRequest([await this.meta.messageCreator.createAck(e.ackThisNonce)])),this._hasSynced=!0),this.emit("message",e)};this.send=e=>{switch(e.type){case"presence-update":case"sync":case"heartbeat":return this.sendRequest([e]);case"op":if(this._hasSynced)return this.sendRequest([e]);break}};this.destroy=()=>{this.dispose(),this.stop()};this.onHeartbeat=async()=>{this.sendRequest([await this.meta.messageCreator.createPresenceUpdate(this.presence.self.presence),await this.meta.messageCreator.createSyncStep1()])};this.onHeartbeatMissed=async()=>{this.emit("onlineChange",!1),this.log("Missed heartbeat"),this._isConnected=!1};this.log=s,this.meta=n,this.presence=i,this.endpointProvider=e,this.heartbeat=new rt({interval:o}),this.heartbeat.subscribe("beat",this.onHeartbeat),this.heartbeat.subscribe("missed",this.onHeartbeatMissed)}get interval(){return this.heartbeat.interval}start(){this.status!=="active"&&(this.heartbeat.start(!0),this._status="active")}stop(){this.heartbeat.stop(),this._status="paused"}reconnect(){this.heartbeat.start(!0)}ignoreIncoming(){this.stop()}get isConnected(){return this._isConnected}get status(){return this._status}};function $r(r){this.message=r}$r.prototype=new Error,$r.prototype.name="InvalidCharacterError";var Mo=typeof window<"u"&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new $r("'atob' failed: The string to be decoded is not correctly encoded.");for(var e,n,i=0,o=0,s="";n=t.charAt(o++);~n&&(e=i%4?64*e+n:n,i++%4)?s+=String.fromCharCode(255&e>>(-2*i&6)):0)n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(n);return s};function va(r){var t=r.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw"Illegal base64url string!"}try{return function(e){return decodeURIComponent(Mo(e).replace(/(.)/g,function(n,i){var o=i.charCodeAt(0).toString(16).toUpperCase();return o.length<2&&(o="0"+o),"%"+o}))}(t)}catch{return Mo(t)}}function An(r){this.message=r}function Sa(r,t){if(typeof r!="string")throw new An("Invalid token specified");var e=(t=t||{}).header===!0?0:1;try{return JSON.parse(va(r.split(".")[e]))}catch(n){throw new An("Invalid token specified: "+n.message)}}An.prototype=new Error,An.prototype.name="InvalidTokenError";var jo=Sa;var Tn=class{constructor(t){this.config=t;this.cached=null;this.type=0;this.getEndpoints=async()=>{if(this.cached)return this.cached;let t;this.config.fetchAuth?t=await this.config.fetchAuth():t=await fetch(this.config.authEndpoint,{credentials:"include"}).then(c=>{if(c.ok)return c.json();throw new Error(`Auth endpoint returned non-200 response: ${c.status}`)}),L(t.accessToken,"No access token provided from auth endpoint");let e=jo(t.accessToken);L(e.url,"No sync endpoint provided from auth endpoint"),L(e.type!==void 0,"No replica type provided from auth endpoint"),this.type=parseInt(e.type+"");let n=new URL(e.url);n.protocol=n.protocol.replace("ws","http");let i=n.toString();n.protocol=n.protocol.replace("http","ws");let o=n.toString(),s=e.file;if(!s){let c=new URL(i);c.pathname=c.pathname+"/files",s=c.toString()}return this.cached={http:i,websocket:o,files:s,token:t.accessToken},this.cached};this.clearCache=()=>{this.cached=null};if(!t.authEndpoint&&!t.fetchAuth)throw new Error("Either authEndpoint or fetchAuth must be provided to ServerSyncEndpointProvider")}};var Fn=class extends V{constructor(e){super();this.timer=null;this.isScheduled=!1;this.next=()=>{this.isScheduled||(this.isScheduled=!0,this.timer=setTimeout(()=>{this.emit("trigger"),this.isScheduled=!1,this.backoff.next()},this.backoff.current))};this.reset=()=>{this.backoff.reset(),this.timer&&(clearTimeout(this.timer),this.timer=null)};this.backoff=e}},Rn=class{constructor(t,e){this.current=0;this.next=()=>{this.current=Math.min(this.max,this.current*this.factor)};this.reset=()=>{this.current=0};this.max=t,this.factor=e}};var kn=class extends V{constructor({endpointProvider:e,meta:n,presence:i,log:o}){super();this.socket=null;this.connectQueue=[];this.syncQueue=[];this.incomingQueue=[];this._status="paused";this.synced=!1;this.hasStartedSync=!1;this._ignoreIncoming=!1;this.mode="realtime";this.log=(...e)=>{};this.heartbeat=new rt;this.reconnectScheduler=new Fn(new Rn(60*1e3,1.5));this.onOpen=()=>{if(!this.socket)throw new Error("Invalid sync state: online but socket is null");if(this.synced=!1,this.connectQueue.length){for(let e of this.connectQueue)this.log("Sending queued message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e));this.connectQueue=[]}this.log("Sync connected"),this.onOnlineChange(!0),this.reconnectScheduler.reset()};this.onOnlineChange=async e=>{this.log("Socket online change",e),!this.disposed&&(e?(this.log("Starting sync"),this.hasStartedSync=!0,this.synced=!1,this.send(await this.meta.messageCreator.createPresenceUpdate(this.presence.self.presence)),this.send(await this.meta.messageCreator.createSyncStep1()),this.heartbeat.start()):(this.hasStartedSync=!1,this.synced=!1,this.heartbeat.stop()),this.emit("onlineChange",e))};this.onMessage=async e=>{if(this._ignoreIncoming){this.log("Ignoring incoming message (ignore incoming flag set)",e.data);return}let n=JSON.parse(e.data);switch(n.type){case"sync-resp":if(n.ackThisNonce&&this.send(await this.meta.messageCreator.createAck(n.ackThisNonce)),this.hasStartedSync=!0,this.synced=!0,this.syncQueue.length)if(n.overwriteLocalData)this.log("warn","Overwriting local data - dropping outgoing message queue"),this.syncQueue=[];else{for(let i of this.syncQueue)this.send(i);this.syncQueue=[]}if(this.emit("message",n),this.incomingQueue.length){for(let i of this.incomingQueue)this.emit("message",i);this.incomingQueue=[]}break;case"need-since":case"presence-changed":case"presence-offline":this.emit("message",n);break;case"op-re":if(!this.synced){this.log("Enqueueing op-re message because sync hasn't finished yet",n),this.incomingQueue.push(n);break}this.emit("message",n);break;case"heartbeat-response":this.heartbeat.keepAlive(),this.emit("message",n);break;default:this.synced&&this.emit("message",n);break}};this.onError=e=>{this.log(e),this.reconnectScheduler.next(),this.log("Attempting reconnect to websocket sync")};this.onClose=e=>{this.log("Sync disconnected"),this.onOnlineChange(!1),this.onError(e)};this.initializeSocket=async()=>{let e=await this.endpointProvider.getEndpoints();return this.socket=new WebSocket(e.websocket,["Bearer",e.token]),this.socket.addEventListener("message",this.onMessage),this.socket.addEventListener("open",this.onOpen),this.socket.addEventListener("error",this.onError),this.socket.addEventListener("close",this.onClose),this.socket};this.sendHeartbeat=async()=>{this.send(await this.meta.messageCreator.createHeartbeat())};this.reconnect=()=>{this.stop(),this.start()};this.canSkipSyncWait=e=>e.type==="sync"||e.type==="presence-update"||e.type==="sync-ack"||e.type==="heartbeat";this.send=e=>{this.status==="active"&&(!this.hasStartedSync&&!this.canSkipSyncWait(e)||(this.canSkipSyncWait(e)?this.socket?.readyState===WebSocket.OPEN?(this.log("Sending message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e))):(this.log("Enqueueing message until socket is open",JSON.stringify(e,null,2)),this.connectQueue.push(e)):this.synced?this.socket?.readyState===WebSocket.OPEN&&(this.log("Sending message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e))):this.hasStartedSync&&(this.log("Enqueueing message until synced",JSON.stringify(e,null,2)),this.syncQueue.push(e))))};this.destroy=()=>{this.dispose(),this.stop()};this.start=()=>{this.socket||(this.initializeSocket(),this._status="active")};this.stop=()=>{this.socket?.removeEventListener("message",this.onMessage),this.socket?.removeEventListener("close",this.onClose),this.socket?.close(),this.socket=null,this._status="paused"};this.log=o||this.log,this.endpointProvider=e,this.meta=n,this.presence=i,this.reconnectScheduler.subscribe("trigger",this.initializeSocket),this.heartbeat.subscribe("beat",this.sendHeartbeat)}ignoreIncoming(){this.incomingQueue=[],this._ignoreIncoming=!0}get isConnected(){return this.socket?.readyState===WebSocket.OPEN}get status(){return this._status}};var Bn=class extends V{constructor(){super(...arguments);this.mode="pull";this.destroy=()=>{};this.isConnected=!1;this.status="paused";this.pullInterval=0;this.presence=new Dt({initialPresence:{},defaultProfile:{}});this.uploadFile=async()=>({success:!1,retry:!1});this.getFile=async()=>({success:!1,retry:!1})}send(){}start(){}stop(){}ignoreIncoming(){}reconnect(){}setMode(){}setPullInterval(){}},it=class extends V{constructor({authEndpoint:e,fetchAuth:n,initialPresence:i,automaticTransportSelection:o=!0,autoStart:s,initialTransport:c,pullInterval:p,presenceUpdateBatchTimeout:u,defaultProfile:m,useBroadcastChannel:S},{meta:g,log:_,onData:w}){super();this.broadcastChannel=null;this._activelySyncing=!1;this.handleBroadcastChannelMessage=e=>{e.data.type==="sync"&&this.handleMessage(e.data.message,{source:"broadcastChannel"})};this.onTokenExpired=()=>{this.endpointProvider.clearCache()};this.handleMessage=async(e,{source:n}={source:"network"})=>{if(e.type==="op-re"||e.type==="sync-resp")for(let i of e.operations)this.meta.time.update(i.timestamp);switch(this.log("sync message",JSON.stringify(e,null,2)),e.type){case"op-re":await this.onData({operations:e.operations,baselines:e.baselines}),e.globalAckTimestamp&&await this.meta.setGlobalAck(e.globalAckTimestamp);break;case"global-ack":await this.meta.setGlobalAck(e.timestamp);break;case"sync-resp":this._activelySyncing=!0,this.emit("syncingChange",!0),await this.onData({operations:e.operations,baselines:e.baselines,reset:e.overwriteLocalData}),e.globalAckTimestamp&&await this.meta.setGlobalAck(e.globalAckTimestamp),await this.meta.updateLastSynced(e.ackedTimestamp),this._activelySyncing=!1,this.emit("syncingChange",!1);break;case"need-since":this.activeSync.send(await this.meta.messageCreator.createSyncStep1(e.since));break;case"server-ack":await this.meta.updateLastSynced(e.timestamp)}n==="network"&&this.broadcastChannel?.postMessage({type:"sync",message:e}),this.presence[Kr](await this.meta.localReplica.get(),e)};this.handleOnlineChange=e=>{this.emit("onlineChange",e)};this.handlePresenceUpdate=async e=>{this.send(await this.meta.messageCreator.createPresenceUpdate(e))};this.setMode=e=>{if(e==="realtime"&&!this.canDoRealtime)throw new Error("Cannot switch to realtime mode, because the current auth token does not allow it");let n;e==="realtime"?n=this.webSocketSync:n=this.pushPullSync,n!==this.activeSync&&(this.log("switching to",e,"mode"),this.activeSync.status==="active"&&n.start(),this.activeSync.stop(),this.activeSync=n)};this.setPullInterval=e=>{this.pushPullSync.setInterval(e)};this.send=e=>{if(this.activeSync.status==="active")return this.activeSync.send(e)};this.uploadFile=async e=>this.activeSync.status==="active"?this.fileSync.uploadFile(e):{success:!1,retry:!1};this.getFile=async e=>{if(this.activeSync.status==="active")return this.fileSync.getFile(e);throw new Error("Offline, cannot retrieve remote file details")};this.start=()=>this.activeSync.start();this.stop=()=>this.activeSync.stop();this.destroy=()=>{this.dispose(),this.webSocketSync.destroy(),this.pushPullSync.destroy()};this.reconnect=()=>this.activeSync.reconnect();if(this.meta=g,this.onData=w,this.log=_||(()=>{}),this.presence=new Dt({initialPresence:i,defaultProfile:m,updateBatchTimeout:u}),this.endpointProvider=new Tn({authEndpoint:e,fetchAuth:n}),this.webSocketSync=new kn({endpointProvider:this.endpointProvider,meta:g,presence:this.presence,log:this.log}),this.pushPullSync=new Pn({endpointProvider:this.endpointProvider,meta:g,presence:this.presence,log:this.log,interval:p}),this.fileSync=new _n({endpointProvider:this.endpointProvider,log:this.log}),S&&"BroadcastChannel"in window&&(this.broadcastChannel=new BroadcastChannel("verdant"),this.broadcastChannel.addEventListener("message",this.handleBroadcastChannelMessage)),c==="realtime"?this.activeSync=this.webSocketSync:this.activeSync=this.pushPullSync,this.presence.subscribe("update",this.handlePresenceUpdate),this.meta.subscribe("message",this.send),this.webSocketSync.subscribe("message",this.handleMessage),this.webSocketSync.subscribe("onlineChange",this.handleOnlineChange),this.pushPullSync.subscribe("message",this.handleMessage),this.pushPullSync.subscribe("onlineChange",this.handleOnlineChange),o&&this.canDoRealtime){let v=()=>{I&&clearTimeout(I);let D=Object.keys(this.presence.peers).length>0||o!=="peers-only"&&this.presence.selfReplicaIds.size>1;D&&this.mode==="pull"?this.setMode("realtime"):!D&&this.mode==="realtime"&&(I=setTimeout(()=>{Object.keys(this.presence.peers).length===0&&this.setMode("pull")},1e3))},I;this.presence.subscribe("peersChanged",v),o!=="peers-only"&&this.presence.subscribe("selfChanged",v)}s&&this.start()}get canDoRealtime(){return this.endpointProvider.type===0||this.endpointProvider.type===2||this.endpointProvider.type===5}get syncing(){return this._activelySyncing}get pullInterval(){return this.pushPullSync.interval}ignoreIncoming(){this.activeSync.ignoreIncoming()}get isConnected(){return this.activeSync.isConnected}get status(){return this.activeSync.status}get mode(){return this.activeSync.mode}};function Oa(r){return r!==null}function zr(r){return Array.isArray(r)?r.map(zr).filter(Oa):r instanceof ue&&r.deleted?null:r}function ke(r,t){return!r&&!t||r&&t&&Te(r)===Te(t)}var qr=Symbol("ON_ALL_UNSUBSCRIBED"),fe=Symbol("UPDATE"),Ia,ge=class extends Ie{constructor({initial:e,context:n,collection:i,key:o,shouldUpdate:s}){super();this._internalUnsubscribes=[];this._status="initial";this._executionPromise=null;this.setValue=e=>{if(this._rawValue=e,this.subscribeToDeleteAndRestore(this._rawValue),this._value=zr(e),Array.isArray(this._value)&&this._value.some(n=>n.getSnapshot()===null))debugger;this._status="ready",this._events.emit("change",this._value)};this.refreshValue=()=>{this.setValue(this._rawValue)};this.subscribeToDeleteAndRestore=e=>{for(;this._internalUnsubscribes.length;)this._internalUnsubscribes.pop()?.();Array.isArray(e)?e.forEach(n=>{n instanceof ue&&(this._internalUnsubscribes.push(n.subscribe("delete",this.refreshValue)),this._internalUnsubscribes.push(n.subscribe("restore",this.refreshValue)))}):e instanceof ue&&(this._internalUnsubscribes.push(e.subscribe("delete",this.refreshValue)),this._internalUnsubscribes.push(e.subscribe("restore",()=>{this.refreshValue()})))};this.execute=()=>(this.context.log("debug","Executing query",this.key),this._status==="initial"?this._status="initializing":this._status==="ready"&&(this._status="revalidating"),this._executionPromise=this.run().then(()=>this._value).catch(e=>{if(e instanceof Error){if(e.name==="InvalidStateError"||e.name==="InvalidAccessError")return this._value;throw e}else throw new Error("Unknown error executing query")}),this._executionPromise);this[Ia]=e=>{this._allUnsubscribedHandler=e};this._rawValue=e,this._value=e,this._events=new V(p=>{p==="change"&&this._allUnsubscribedHandler?.(this)}),this.context=n,this.key=o,this.collection=i;let c=s||(p=>p.includes(i));this.addDispose(this.context.entityEvents.subscribe("collectionsChanged",p=>{c(p)&&(this.context.log("info","Updating query",this.key),this.execute())}))}static{Ia=qr}get current(){return this._value}get resolved(){return this.status==="ready"?Promise.resolve(this._value):this._executionPromise??this.execute()}get subscribed(){return this._events.totalSubscriberCount()>0}get status(){return this._status}subscribe(e,n){if(n===void 0&&typeof e=="function")return this.resolved,this._events.subscribe("change",e);if(e==="change"&&n!==void 0)return this.resolved,this._events.subscribe("change",n);if(e==="statusChange"&&typeof n=="function")return this._events.subscribe(e,n);throw new Error("Invalid invocation of Query.subscribe")}};var Mn=class extends ge{constructor({id:e,hydrate:n,...i}){super({initial:null,...i});this.run=async()=>{let e=await this.hydrate(this.oid);this.setValue(e)};this.oid=Z(i.collection,e),this.hydrate=n}};var Da,jn=class extends ge{constructor({index:e,hydrate:n,...i}){super({initial:null,...i});this.run=async()=>{let e=await an({collection:this.collection,index:this.index,context:this.context});this.setValue(e?await this.hydrate(e):null)};this[Da]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n}static{Da=fe}};var Ea,Ln=class extends ge{constructor({index:e,hydrate:n,pageSize:i,page:o,...s}){super({initial:[],...s});this._hasNextPage=!1;this.run=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,index:this.index,context:this.context,limit:this._pageSize,offset:this._page*this._pageSize});this._hasNextPage=n,this.setValue(await Promise.all(e.map(this.hydrate)))};this.nextPage=async()=>{this.hasNextPage&&(this._page++,await this.run())};this.previousPage=async()=>{this._page!==0&&(this._page--,await this.run())};this.setPage=async e=>{this._page=e,await this.run()};this[Ea]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n,this._pageSize=i,this._page=o}static{Ea=fe}get pageSize(){return this._pageSize}get page(){return this._page}get hasNextPage(){return this._hasNextPage}get hasPreviousPage(){return this._page>0}};var Ca,Nn=class extends ge{constructor({hydrate:e,pageSize:n,index:i,...o}){super({initial:[],...o});this._upToPage=1;this._hasNextPage=!1;this.run=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,context:this.context,limit:this._pageSize*this._upToPage,offset:0,index:this.index});this._hasNextPage=n,this.setValue(await Promise.all(e.map(this.hydrate)))};this.loadMore=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,context:this.context,limit:this._pageSize,offset:this._pageSize*this._upToPage,index:this.index});this._hasNextPage=n,this._upToPage++,this.setValue([...this.current,...await Promise.all(e.map(this.hydrate))])};this[Ca]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=i,this.hydrate=e,this._pageSize=n}static{Ca=fe}get pageSize(){return this._pageSize}get hasMore(){return this._hasNextPage}};var _a,Vn=class extends ge{constructor({index:e,hydrate:n,...i}){super({initial:[],...i});this.run=async()=>{let e=await cn({collection:this.collection,index:this.index,context:this.context});this.context.log("debug",`FindAllQuery: ${e.length} oids found: ${e}`),this.setValue(await Promise.all(e.map(this.hydrate)))};this[_a]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n}static{_a=fe}};var Un=class{constructor({collection:t,cache:e,entities:n,context:i,documentManager:o}){this.serializeIndex=t=>t?Te(t):"";this.get=t=>{let e=`get:${this.collection}:${t}`;return this.cache.getOrSet(e,()=>new Mn({id:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:e}))};this.findOne=({index:t,key:e}={})=>{let n=e||`findOne:${this.collection}:${this.serializeIndex(t)}`;return this.cache.getOrSet(n,()=>new jn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:n}),i=>{i[fe](t)})};this.findAll=({index:t,key:e}={})=>{let n=e||`findAll:${this.collection}:${this.serializeIndex(t)}`;return this.cache.getOrSet(n,()=>new Vn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:n}),i=>{i[fe](t)})};this.findPage=({index:t,pageSize:e,page:n,key:i})=>{let o=i||`findPage:${this.collection}:${this.serializeIndex(t)}:${e}`;return this.cache.getOrSet(o,()=>new Ln({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:o,pageSize:e,page:n}),s=>{s[fe](t)})};this.findAllInfinite=({index:t,pageSize:e,key:n})=>{let i=n||`findAllInfinite:${this.collection}:${this.serializeIndex(t)}:${e}`;return this.cache.getOrSet(i,()=>new Nn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:i,pageSize:e}),o=>{o[fe](t)})};this.cache=e,this.collection=t,this.hydrate=n.hydrate,this.context=i,this.documentManager=o,this.put=this.documentManager.create.bind(this.documentManager,this.collection),this.delete=this.documentManager.delete.bind(this.documentManager,this.collection),this.deleteAll=this.documentManager.deleteAllFromCollection.bind(this.documentManager,this.collection)}};var Kn=class extends Ie{constructor({evictionTime:e=5*1e3,context:n}){super();this._cache=new Map;this.onQueryUnsubscribed=e=>{setTimeout(()=>{e.subscribed||this._cache.get(e.key)===e&&this._cache.delete(e.key)},this._evictionTime)};this.dropAll=()=>{this._cache.forEach(e=>e.dispose()),this._cache.clear()};this._evictionTime=e,this.context=n}get(e){return this._cache.get(e)||null}set(e){return this._cache.set(e.key,e),e[qr](this.onQueryUnsubscribed),e}getOrSet(e,n,i){let o=this.get(e);return o?(i?.(o),o):this.set(n())}};var He=class extends V{constructor(e,n,i){super();this.config=e;this.context=n;this._closed=!1;this.addData=e=>this._entities.addData(e);this.stats=async()=>{let e=Object.keys(this.schema.collections),n={};for(let u of e)try{n[u]=await yt(this.documentDb,u)}catch(m){this.context.log?.("error",m)}let i=await this.meta.stats(),o=typeof navigator<"u"&&typeof navigator.storage<"u"&&"estimate"in navigator.storage?await navigator.storage.estimate():void 0,s=Object.values(n).reduce((u,{size:m})=>u+m,0),c=i.baselinesSize.size+i.operationsSize.size,p=c/s;return{collections:n,meta:i,storage:o,totalMetaSize:c,totalCollectionsSize:s,metaToDataRatio:p,quotaUsage:o?.usage&&o?.quota?o.usage/o.quota:void 0}};this.close=async()=>{this._closed=!0,this.sync.ignoreIncoming(),await this._entities.flushAllBatches(),this.sync.stop(),this.sync.destroy(),await this._entities.destroy(),this.meta.close(),await new Promise(async e=>{await Ke(this.documentDb),await Ke(this.metaDb),e()}),this.context.log?.("Client closed")};this.__dangerous__resetLocal=async()=>{this.sync.stop(),await Yt(this.namespace,indexedDB)};this.export=async()=>{let e=await this.meta.export();return Buffer.from(JSON.stringify(e))};this.import=async e=>{this.context.log("Importing data..."),await Ke(this.context.documentDb);let n=JSON.parse(e.toString());await this.meta.resetFrom(n);let i=n.schema.version,o=indexedDB.deleteDatabase([this.namespace,"collections"].join("_"));await new Promise((c,p)=>{o.onsuccess=c,o.onerror=p});let s=this.context.schema;this.context.schema=n.schema,this.context.documentDb=await vt({meta:this.meta,migrations:this.config.migrations,context:this.context,version:i}),this.context.internalEvents.emit("documentDbChanged",this.documentDb),this.context.log("Re-initializing data from imported data..."),await this._entities.addData({operations:n.operations,baselines:n.baselines,reset:!0}),await Ke(this.context.documentDb),this.context.log("Migrating up to latest schema..."),this.context.schema=s,this.context.documentDb=await vt({meta:this.meta,migrations:this.config.migrations,context:this.context,version:s.version}),this.context.internalEvents.emit("documentDbChanged",this.documentDb)};this.meta=i.meta,this.collectionNames=Object.keys(n.schema.collections),this._sync=this.config.syncConfig&&!n.schema.wip?new it(this.config.syncConfig,{meta:this.meta,onData:this.addData,log:this.context.log}):new Bn,n.schema.wip&&this.config.syncConfig&&n.log("warn","\u26A0\uFE0F\u26A0\uFE0F Sync is disabled for WIP schemas. Commit your schema changes to start syncing again. \u26A0\uFE0F\u26A0\uFE0F"),this._fileManager=new pn({db:this.metaDb,sync:this.sync,context:this.context,config:this.config.files,meta:this.meta}),this._entities=new Cn({ctx:this.context,meta:this.meta,files:this._fileManager}),this._queryCache=new Kn({context:n}),this._documentManager=new un(this.meta,this.schema,this._entities);let o=Di(()=>{this.emit("futureSeen")},300);this.context.globalEvents.subscribe("futureSeen",o),this.documentDb.addEventListener("versionchange",()=>{this.context.log?.(`Another tab has requested a version change for ${this.namespace}`),this.documentDb.close(),typeof window<"u"&&window.location.reload()}),this.metaDb.addEventListener("versionchange",()=>{this.context.log?.(`Another tab has requested a version change for ${this.namespace}`),this.metaDb.close(),typeof window<"u"&&window.location.reload()});for(let[s,c]of Object.entries(n.schema.collections)){let p=s;this[p]=new Un({collection:p,cache:this._queryCache,context:this.context,entities:this.entities,documentManager:this.documentManager})}}get sync(){return this._sync}get entities(){return this._entities}get documentManager(){return this._documentManager}get documentDb(){return this.context.documentDb}get metaDb(){return this.context.metaDb}get schema(){return this.context.schema}get namespace(){return this.context.namespace}get undoHistory(){return this.context.undoHistory}get presence(){return this.sync.presence}get batch(){return this.entities.batch}};var Et=class{constructor(t){this.value=t}deref(){return this.value}};var Lo=Symbol("metadataVersion");var $n=class{constructor(t){this.init=t;this._initializing=!1;this.initialize=async t=>{if(typeof window>"u"&&!t.indexedDb)throw new Error("A verdant client was initialized in an environment without IndexedDB. If you are using verdant in a server-rendered framework, you must enforce that all clients are initialized on the client-side, or you must provide some mock interface of IDBFactory to the ClientDescriptor options.");if(this._initializing||this._resolvedValue)return this._readyPromise;this._initializing=!0;try{let e;return t.schema.wip?e=await this.initializeWIPDatabases(t):(e=await this.initializeDatabases(t),this.cleanupWIPDatabases(t)),this.resolveReady(e),this._resolvedValue=e,e}catch(e){throw e instanceof Error?(this.rejectReady(e),e):new Error("Unknown error initializing storage")}finally{this._initializing=!1}};this.initializeDatabases=async t=>{let e=t[Lo],{db:n}=await on({indexedDB:t.indexedDb,log:t.log,namespace:t.namespace,metadataVersion:e}),i={namespace:this._namespace,metaDb:n,schema:t.schema,log:t.log||(()=>{}),undoHistory:t.undoHistory||new St,entityEvents:new V,globalEvents:new V,internalEvents:new V,weakRef:m=>t.EXPERIMENTAL_weakRefs?new WeakRef(m):new Et(m),migrations:t.migrations},o=new bt({context:i,disableRebasing:t.disableRebasing});await o.updateSchema(t.schema,t.overrideSchemaConflict);let s=Object.assign(i,{getNow:()=>o.now}),c=await vt({context:s,version:t.schema.version,meta:o,migrations:t.migrations,indexedDB:t.indexedDb}),p=Object.assign(s,{documentDb:c});return new He({syncConfig:t.sync,migrations:t.migrations,files:t.files},p,{meta:o})};this.initializeWIPDatabases=async t=>{let e=Te(t.schema);console.info(`WIP schema in use. Opening database with hash ${e}`);let n=`@@wip_${t.namespace}_${e}`,{db:i}=await Hi({indexedDB:t.indexedDb,log:t.log,namespace:t.namespace,wipNamespace:n}),o={namespace:this._namespace,metaDb:i,schema:t.schema,log:t.log||(()=>{}),undoHistory:t.undoHistory||new St,entityEvents:new V,globalEvents:new V,internalEvents:new V,weakRef:S=>t.EXPERIMENTAL_weakRefs?new WeakRef(S):new Et(S),migrations:t.migrations},s=new bt({context:o,disableRebasing:t.disableRebasing}),c=Object.assign(o,{getNow:()=>s.now});await s.updateSchema(t.schema,t.overrideSchemaConflict);let p=await Yi({context:c,version:t.schema.version,meta:s,migrations:t.migrations,indexedDB:t.indexedDb,wipNamespace:n}),u=Object.assign(c,{documentDb:p});return new He({syncConfig:t.sync,migrations:t.migrations,files:t.files},u,{meta:s})};this.cleanupWIPDatabases=async t=>{let i=(await zi(t.indexedDb)).filter(o=>o.name?.startsWith("@@wip_")).map(o=>o.name).filter(o=>!o.startsWith(`@@wip_${t.namespace}_${Te(t.schema)}`));for(let o of i)await $i(o,t.indexedDb)};this.open=()=>this.initialize(this.init);this.close=async()=>{this._resolvedValue&&this._resolvedValue.close(),this._initializing&&(await this._readyPromise).close()};this.__dangerous__resetLocal=async()=>{await Yt(this.namespace)};this._readyPromise=new Promise((e,n)=>{this.resolveReady=e,this.rejectReady=n}),this._namespace=t.namespace}get namespace(){return this._namespace}get current(){return this._resolvedValue}get readyPromise(){return this._readyPromise}get schema(){return this.init.schema}};window.Verdant=Hr;
15
+ `)}})}function Gi({migration:r,meta:t,getMigrationNow:e,newOids:n}){return r.allCollections.reduce((i,o)=>(i[o]={put:async s=>{Pe(r.newSchema.collections[o],s);let c=s[r.newSchema.collections[o].primaryKey],p=Z(o,c);return n.push(p),await t.insertLocalOperations(Fe(s,p,e)),s},delete:async s=>{let c=Z(o,s),p=await t.getAllDocumentRelatedOids(c);return t.insertLocalOperations(p.map(u=>({oid:u,timestamp:e(),data:{op:"delete"}})))}},i),{})}function qs({migration:r,context:t,meta:e}){return r.oldCollections.reduce((n,i)=>(n[i]={get:async o=>{let s=Z(i,o);return await e.getDocumentSnapshot(s,{to:e.time.now(r.oldSchema.version)})},findOne:async o=>{let s=await an({collection:i,index:o,context:t});return s?await e.getDocumentSnapshot(s,{to:e.time.now(r.oldSchema.version)}):null},findAll:async o=>{let s=await cn({collection:i,index:o,context:t});return await Promise.all(s.map(p=>e.getDocumentSnapshot(p,{to:e.time.now(r.oldSchema.version)})))}},n),{})}function Hs({meta:r,migration:t,context:e}){function n(){return r.time.zero(t.version)}let i=new Array,o=qs({migration:t,context:e,meta:r}),s=Gi({migration:t,getMigrationNow:n,newOids:i,meta:r}),c=async m=>{let S=await r.getAllCollectionRelatedOids(m);return r.insertLocalOperations(S.map(g=>({oid:g,timestamp:n(),data:{op:"delete"}})))},p=new Array;return{log:e.log,newOids:i,deleteCollection:c,migrate:async(m,S)=>{let g=await o[m].findAll();await Promise.all(g.filter(Boolean).map(async _=>{let w=ne(_);L(!!w,`Document is missing an OID: ${JSON.stringify(_)}`);let v=ae(_),I=await S(_);if(I){ft(v),ft(I),Ge(I);let x=ht(v,I,n,void 0,[],{mergeUnknownObjects:!0});x.length>0&&await r.insertLocalOperations(x)}}))},queries:o,mutations:s,awaitables:p}}function Ws({meta:r,migration:t,context:e}){function n(){return r.time.zero(t.version)}let i=new Array,o=new Proxy({},{get(){throw new Error("Queries are not available in initial migrations; there is no database yet!")}}),s=Gi({migration:t,getMigrationNow:n,newOids:i,meta:r});return{log:e.log,newOids:i,deleteCollection:()=>{throw new Error("Calling deleteCollection() in initial migrations is not supported! Use initial migrations to seed initial data using mutations.")},migrate:()=>{throw new Error("Calling migrate() in initial migrations is not supported! Use initial migrations to seed initial data using mutations.")},queries:o,mutations:s,awaitables:[]}}async function Qs(r){return new Promise((t,e)=>{let n=r.getAllKeys();n.onsuccess=i=>{t(n.result)},n.onerror=i=>{e(n.error)}})}async function Js(r,t){let e=r.delete(t);return new Promise((n,i)=>{e.onsuccess=o=>{n()},e.onerror=o=>{i(e.error)}})}async function Ys(r,t){let e=r.put(t);return new Promise((n,i)=>{e.onsuccess=o=>{n()},e.onerror=o=>{i(e.error)}})}async function Gs({meta:r,currentVersion:t,newVersion:e}){let n=[];return await r.operations.iterateOverAllOperations(i=>n.push(i),{from:r.time.zero(t+1)}),Array.from(new Set(n.map(i=>$(i.oid))))}var St=class extends V{constructor(){super(...arguments);this._undoable=[];this._undone=[];this.undo=async()=>{let e=this._undoable.pop();if(e){let n=await e();return n&&this._undone.push(n),this.emit("change"),!0}return!1};this.redo=async()=>{let e=this._undone.pop();if(e){let n=await e();return n&&this._undoable.push(n),this.emit("change"),!0}return!1};this.addUndo=e=>{this._undoable.push(e),this._undone=[],this.emit("change")};this.addRedo=e=>{this._undone.push(e),this.emit("change")};this.clear=()=>{this._undoable=[],this._undone=[],this.emit("change")}}get canUndo(){return this._undoable.length>0}get canRedo(){return this._undone.length>0}};var un=class{constructor(t,e,n){this.meta=t;this.schema=e;this.entities=n;this.getOid=(t,e)=>{let n=this.schema.collections[t].primaryKey,i=e[n];return L(i,`Document must have a primary key: ${n.toString()} (got: ${JSON.stringify(e)})`),Z(t,i)};this.addDefaults=(t,e)=>{let n=this.schema.collections[t];return Pe(n,e)};this.create=(t,e,n={})=>{let i=this.addDefaults(t,e),o=this.getOid(t,i);return this.entities.create(i,o,n)};this.delete=async(t,e,n={})=>{let i=Z(t,e);return this.entities.delete(i,n)};this.deleteAll=async(t,e={})=>this.entities.deleteAll(t.map(([n,i])=>Z(n,i)),e);this.deleteAllFromCollection=async(t,e,n={})=>this.entities.deleteAll(e.map(i=>Z(t,i)),n)}};var et=Symbol("entity-file-update"),xt=Symbol("entity-file-mark-failed"),Xs,Zs,de=class extends V{constructor(e,{downloadRemote:n=!1}={}){super();this.id=e;this._objectUrl=null;this._fileData=null;this._loading=!0;this._failed=!1;this._downloadRemote=!1;this[Xs]=e=>{this._loading=!1,this._failed=!1,this._fileData=e,e.file&&(this._objectUrl&&URL.revokeObjectURL(this._objectUrl),this._objectUrl=URL.createObjectURL(e.file)),this.emit("change")};this[Zs]=()=>{this._failed=!0,this._loading=!1,this.emit("change")};this.destroy=()=>{this._objectUrl&&URL.revokeObjectURL(this._objectUrl),this.dispose()};this._downloadRemote=n}static{Xs=et,Zs=xt}get downloadRemote(){return this._downloadRemote}get url(){return this.loading?null:this._objectUrl?this._objectUrl:this._fileData?.url??null}get name(){return this._fileData?.name??null}get type(){return this._fileData?.type??null}get loading(){return this._loading}get failed(){return this._failed}getSnapshot(){return{id:this.id,url:this.loading||this.failed?void 0:this.url}}};var Xi=Qe(at(),1);function ea(r){return{id:(0,Xi.default)(),file:r,url:void 0,remote:!1,name:r.name,type:r.type}}function Er(r){return r instanceof File||typeof Blob<"u"&&r instanceof Blob}function tt(r,t){if(typeof window<"u"&&Er(r)){let e=ea(r);return t(e),Mt(e.id)}if(Array.isArray(r)){for(let e=0;e<r.length;e++)r[e]=tt(r[e],t);return r}if(typeof r=="object"){for(let e in r)r[e]=tt(r[e],t);return r}return r}function Zi(r){return new Promise((t,e)=>{let n=new FileReader;n.onload=()=>{t(n.result)},n.onerror=e,n.readAsArrayBuffer(r)})}var fn=class extends se{constructor(){super(...arguments);this.addFile=async(e,{transaction:n,downloadRemote:i=!1}={})=>{let o=e.file?await Zi(e.file):void 0;if(!o&&i&&e.url)try{o=await fetch(e.url,{method:"GET",credentials:"include"}).then(s=>s.arrayBuffer())}catch(s){console.error("Failed to download file to cache it locally. The file will still be available using its URL. Check the file server's CORS configuration.",s)}return this.run("files",s=>s.put({id:e.id,remote:e.remote?"true":"false",deletedAt:null,name:e.name,type:e.type,url:e.url,buffer:o}),{mode:"readwrite",transaction:n})};this.hydrateFileData=e=>{e.remote=e.remote==="true";let n=e.buffer;return delete e.buffer,e.file=n?ta(n,e.type):void 0,e};this.markUploaded=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(!i)throw new Error("File is not in local database");return this.run("files",o=>o.put({...i,remote:"true"}),{mode:"readwrite",transaction:n})};this.getFileRaw=async(e,{transaction:n}={})=>{let i=await this.run("files",o=>o.get(e),{mode:"readonly",transaction:n});if(i)return i};this.getFile=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(i)return this.hydrateFileData(i)};this.markPendingDelete=async(e,{transaction:n}={})=>{let i=await this.getFileRaw(e,{transaction:n});if(!i)throw new Error("File is not in local database");return this.run("files",o=>o.put({...i,deletedAt:Date.now()}),{mode:"readwrite",transaction:n})};this.listUnsynced=async()=>(await this.run("files",n=>n.index("remote").getAll("false"),{mode:"readonly"})).map(this.hydrateFileData);this.iterateOverPendingDelete=(e,n)=>this.iterate("files",i=>i.index("deletedAt").openCursor(IDBKeyRange.lowerBound(0,!0)),(i,o)=>{e(this.hydrateFileData(i),o)},{mode:"readwrite",transaction:n})}deleteFile(e,{transaction:n}={}){return this.run("files",i=>i.delete(e),{mode:"readwrite",transaction:n})}};function ta(r,t){return new Blob([r],{type:t})}function na(r){return r.deletedAt!==null&&r.deletedAt<Date.now()-1e3*60*24*3}var pn=class{constructor({db:t,sync:e,context:n,meta:i,config:o={}}){this.files=new Map;this.add=async t=>{let e=t;if(e.remote=!1,this.files.has(e.id))this.files.get(e.id)[et](e);else{let n=new de(e.id);n[et](e),this.files.set(e.id,n)}await this.storage.addFile(e),e.file&&((await this.sync.uploadFile(e)).success?await this.storage.markUploaded(e.id):this.context.log("error","Failed to upload file"))};this.uploadFile=async(t,e=0)=>{let n=await this.sync.uploadFile(t);n.success?await this.storage.markUploaded(t.id):n.retry&&e<5?(this.context.log("error","Error uploading file, retrying..."),setTimeout(this.uploadFile,1e3,t,e+1)):this.context.log("error","Failed to upload file. Not retrying until next sync.")};this.get=(t,e)=>{if(this.files.has(t))return this.files.get(t);let n=new de(t,e);return this.files.set(t,n),this.load(n),n};this.load=async(t,e=0)=>{if(e>5){this.context.log("error","Failed to load file after 5 retries"),t[xt]();return}let n=await this.storage.getFile(t.id);if(n)t[et](n);else try{let i=await this.sync.getFile(t.id);i.success?(t[et](i.data),await this.storage.addFile(i.data,{downloadRemote:t.downloadRemote})):(this.context.log("error","Failed to load file",i),t[xt](),i.retry&&setTimeout(this.load,1e3,t,e+1))}catch(i){this.context.log("error","Failed to load file",i),t[xt](),setTimeout(this.load,1e3,t,e+1)}};this.listUnsynced=async()=>this.storage.listUnsynced();this.onOnlineChange=async t=>{if(t){let e=await this.listUnsynced();await Promise.all(e.map(this.uploadFile))}};this.tryCleanupDeletedFiles=async()=>{let t=0,e=0;await this.storage.iterateOverPendingDelete((n,i)=>{this.config.canCleanupDeletedFile(n)?(t++,i.delete(n.id)):e++}),this.context.log("info",`Cleaned up ${t} files, skipped ${e} files`)};this.handleFileRefsDeleted=async t=>{let e=this.storage.createTransaction(["files"],{mode:"readwrite"});await Promise.all(t.map(async n=>{try{await this.storage.markPendingDelete(n.id,{transaction:e})}catch(i){this.context.log("error","Failed to mark file for deletion",i)}})),this.context.log("info",`Marked ${t.length} files as pending delete`)};this.storage=new fn(t),this.sync=e,this.context=n,this.meta=i,this.config={canCleanupDeletedFile:na,...o},this.sync.subscribe("onlineChange",this.onOnlineChange),this.meta.subscribe("filesDeleted",this.handleFileRefsDeleted),this.tryCleanupDeletedFiles()}};var hn=class{constructor({initial:t}={}){this.cache=new Map;this.get=t=>{if(this.cache.has(t.oid))return this.cache.get(t.oid);let e=new ue(t);return this.cache.set(t.oid,e),e};this.has=t=>this.cache.has(t);this.getFile=(t,e)=>{if(this.cache.has(t))return this.cache.get(t);let n=new de(t,e);return this.cache.set(t,n),n};this.getCached=t=>this.cache.get(t);if(t)for(let e of t)this.cache.set(e.oid,e)}};var ue=class r extends V{constructor({oid:e,schema:n,entityFamily:i,parent:o,ctx:s,metadataFamily:c,readonlyKeys:p,files:u,patchCreator:m,events:S}){super();this.fieldPath=[];this._viewData=void 0;this.validationError=void 0;this.cachedDeepUpdatedAt=null;this.wasDeletedLastChange=!1;this.cachedView=void 0;this.onAdd=(e,n)=>{n.oid===this.oid&&this.addConfirmedData(n)};this.onReplace=(e,n)=>{n.oid===this.oid&&this.replaceAllData(n)};this.onResetAll=()=>{this.resetAllData()};this.childIsNull=e=>{if(e instanceof r){let n=e.view;return n==null}return e==null};this.validate=Ni(()=>(this.validationError=Re({field:this.schema,value:this.rawView,fieldPath:this.fieldPath,depth:1})??void 0,this.validationError),()=>[this.viewData]);this.viewWithMappedChildren=e=>{let n=this.view;if(!n)return null;if(Array.isArray(n)){let i=n.map(o=>o instanceof r||o instanceof de?e(o):o);return K(i,this.oid),i}else{let i=Object.entries(n).reduce((o,[s,c])=>(c instanceof r||c instanceof de?o[s]=e(c):o[s]=c,o),{});return K(i,this.oid),i}};this.getSnapshot=()=>this.viewWithMappedChildren(e=>e.getSnapshot());this.addPendingOperations=e=>{this.ctx.log("debug","Entity: adding pending operations",this.oid);let n=this.metadataFamily.addPendingData(e);for(let i of n)this.change(i)};this.addConfirmedData=e=>{this.ctx.log("debug","Entity: adding confirmed data",this.oid);let n=this.metadataFamily.addConfirmedData(e);for(let i of n)this.change(i)};this.replaceAllData=e=>{this.ctx.log("debug","Entity: replacing all data",this.oid);let n=this.metadataFamily.replaceAllData(e);for(let i of n)this.change(i)};this.resetAllData=()=>{this.ctx.log("debug","Entity: resetting all data",this.oid),this.cachedDeepUpdatedAt=null,this.cachedView=void 0,this._viewData=void 0;let e=this.metadataFamily.replaceAllData({});for(let n of e)this.change(n)};this.change=e=>{if(e.oid===this.oid)this._viewData=void 0,this.cachedView=void 0,this.deepChange(this,e),this.ctx.log("Emitting change event",this.oid),this.emit("change",{isLocal:e.isLocal}),this.parent||(this.deleted&&!this.wasDeletedLastChange?(this.ctx.log("debug","Entity deleted",this.oid),this.emit("delete",{isLocal:e.isLocal}),this.wasDeletedLastChange=!0):!this.deleted&&this.wasDeletedLastChange&&(this.ctx.log("debug","Entity restored",this.oid),this.emit("restore",{isLocal:e.isLocal}),this.wasDeletedLastChange=!1));else{let n=this.entityFamily.getCached(e.oid);n&&n instanceof r&&n.change(e)}};this.deepChange=(e,n)=>{this.cachedDeepUpdatedAt=null,this.cachedView=void 0,this.ctx.log("debug","Deep change detected at",this.oid,"reset cached view"),this.ctx.log("debug","Emitting deep change event",this.oid),this.emit("changeDeep",e,n),this.parent?.deepChange(e,n)};this.getChild=(e,n)=>{let i=Ne(this.schema,e);if(!i)throw new Error(`No schema for key ${String(e)} in ${JSON.stringify(this.schema)}`);return this.entityFamily.get({oid:n,schema:i,entityFamily:this.entityFamily,metadataFamily:this.metadataFamily,parent:this,ctx:this.ctx,files:this.files,fieldPath:[...this.fieldPath,e],patchCreator:this.patchCreator,events:this.events})};this.get=e=>{eo(e);let n=this.rawView;if(!n)throw new Error(`Cannot access data at key ${e} on deleted entity ${this.oid}`);let i=n[e],o=Ne(this.schema,e);if(!o)throw new Error(`No schema for key ${String(e)} in ${JSON.stringify(this.schema)}`);if(Q(i))if(be(i)){if(o.type!=="file")throw new Error(`Expected file schema for key ${String(e)}, got ${o.type}`);let s=this.files.get(i.id,{downloadRemote:!!o.downloadRemote});return s.subscribe("change",()=>{this.deepChange(this,{isLocal:!1,oid:this.oid})}),s}else return this.getChild(e,i.id);else return Re({field:o,value:i,fieldPath:[...this.fieldPath,e],depth:1,requireDefaults:!0})?_e(o)?ur(o):we(o)?null:void 0:i};this.processInputValue=(e,n)=>{if(this.readonlyKeys.includes(n))throw new Error(`Cannot set readonly key ${n.toString()}`);Er(e)||(e=ae(e,!1));let i=Ne(this.schema,n);if(i){Le(e,i);let o=Re({field:i,value:e,fieldPath:[...this.fieldPath,n]});if(o)throw new Error(o.message)}return tt(e,this.files.add)};this.getDeleteMode=e=>{if(this.readonlyKeys.includes(e))return!1;if(this.schema.type==="any"||this.schema.type==="map")return"delete";if(this.schema.type==="object"){let n=this.schema.properties[e];if(!n||n.type==="any")return"delete";if(n.type==="map")return!1;if(n.nullable)return"null"}return!1};this.getItemRefValue=e=>{if(e instanceof r)return he(e.oid);if(e instanceof de)return Mt(e.id);if(typeof e=="object"){let n=pe(e);if(!n||!this.entityFamily.has(n))throw new Error(`Cannot move object ${JSON.stringify(e)} which does not exist in this list`);return he(n)}else return e};this.set=(e,n)=>{eo(e),this.addPendingOperations(this.patchCreator.createSet(this.oid,e,this.processInputValue(n,e)))};this.getAll=()=>this.view;this.delete=e=>{if(this.isList)ra(e),this.addPendingOperations(this.patchCreator.createListDelete(this.oid,e));else{let n=this.getDeleteMode(e);if(!n)throw new Error(`Cannot delete key ${e.toString()} - the property is not marked as optional in the schema.`);n==="delete"?this.addPendingOperations(this.patchCreator.createRemove(this.oid,e)):this.addPendingOperations(this.patchCreator.createSet(this.oid,e,null))}};this.keys=()=>this.view?Object.keys(this.view):[];this.entries=()=>this.view?Object.entries(this.view):[];this.values=()=>this.view?Object.values(this.view):[];this.update=(e,{merge:n=!0,replaceSubObjects:i=!1}={})=>{if(!n&&this.schema.type!=="any"&&this.schema.type!=="map")throw new Error('Cannot use .update without merge if the field has a strict schema type. merge: false is only available on "any" or "map" types.');let o={};K(o,this.oid);for(let[s,c]of Object.entries(e)){if(this.readonlyKeys.includes(s))throw new Error(`Cannot set readonly key ${s.toString()}`);let p=Ne(this.schema,s);p&&Le(c,p),o[s]=this.processInputValue(c,s)}this.addPendingOperations(this.patchCreator.createDiff(this.getSnapshot(),o,{mergeUnknownObjects:!i,defaultUndefined:n}))};this.push=e=>{this.addPendingOperations(this.patchCreator.createListPush(this.oid,this.processInputValue(e,this.view.length)))};this.insert=(e,n)=>{this.addPendingOperations(this.patchCreator.createListInsert(this.oid,e,this.processInputValue(n,e)))};this.move=(e,n)=>{this.addPendingOperations(this.patchCreator.createListMoveByIndex(this.oid,e,n))};this.moveItem=(e,n)=>{let i=this.getItemRefValue(e);if(Q(i))this.addPendingOperations(this.patchCreator.createListMoveByRef(this.oid,i,n));else{let o=this.view.indexOf(e);if(o===-1)throw new Error(`Cannot move item ${JSON.stringify(e)} which does not exist in this list`);this.move(o,n)}};this.add=e=>{this.addPendingOperations(this.patchCreator.createListAdd(this.oid,this.processInputValue(e,this.view.length)))};this.removeAll=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e)))};this.removeFirst=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e),"first"))};this.removeLast=e=>{this.addPendingOperations(this.patchCreator.createListRemove(this.oid,this.getItemRefValue(e),"last"))};this.map=e=>this.view.map(e);this.filter=e=>this.view.filter(e);this.has=e=>{if(!this.isList)throw new Error("has() is only available on list entities");let n=this.getItemRefValue(e);return Q(n)?this.view.some(i=>{if(Q(i))return Ye(i,n)}):this.view.includes(e)};this.forEach=e=>{this.view.forEach(e)};this.some=e=>this.view.some(e);this.every=e=>this.view.every(e);this.find=e=>this.view.find(e);this.includes=this.has;this.__getViewData__=(e,n)=>this.metadataFamily.get(e).computeView(n==="confirmed");this.__getFamilyOids__=()=>this.metadataFamily.getAllOids();L(!!e,"oid is required"),this.oid=e,this.readonlyKeys=p||[],this.ctx=s,this.files=u,this.schema=n,this.entityFamily=i||new hn({initial:[this]}),this.patchCreator=m,this.metadataFamily=c,this.events=S,this.parent=o,this.parent||(S.add.attach(this.onAdd),S.replace.attach(this.onReplace),S.resetAll.attach(this.onResetAll))}get metadata(){return this.metadataFamily.get(this.oid)}get viewData(){return this._viewData===void 0&&(this._viewData=this.metadata.computeView(),this.validate()),this._viewData}get rawView(){return this.viewData.view}get view(){if(this.cachedView!==void 0)return this.cachedView;if(this.viewData.deleted)return null;let e=this.rawView;if(!e&&!we(this.schema)||this.schema.type==="array"&&!Array.isArray(e)||(this.schema.type==="object"||this.schema.type==="map")&&!U(e))return _e(this.schema)?ur(this.schema):null;if(this.cachedView=this.isList?[]:{},K(this.cachedView,this.oid),Array.isArray(e)){let i=Ne(this.schema,0);if(!i)this.ctx.log("error","No child field schema for list entity.",this.oid);else for(let o=0;o<e.length;o++){let s=this.get(o);this.childIsNull(s)&&!we(i)?this.ctx.log("error","Child missing in non-nullable field",this.oid,"index:",o):this.cachedView.push(s)}}else if(U(e)){let i=this.schema.type==="object"?Object.keys(this.schema.properties):Object.keys(e);for(let o of i){let s=Ne(this.schema,o);if(!s){this.ctx.log("error","No child field schema for object entity at key",o),this.schema.type==="map"?this.cachedView={}:this.cachedView=null;break}let c=this.get(o);if(this.childIsNull(c)&&!we(s)){if(this.ctx.log("error","Child entity is missing for non-nullable field",this.oid,"key:",o),this.schema.type!=="map"){this.cachedView=null;break}}else this.cachedView[o]=c}}return this.cachedView}get uid(){return this.oid}get deleted(){return this.viewData.deleted||this.view===null}get invalid(){return!!this.validate()}get isList(){return this.schema.type==="array"||Array.isArray(this.viewData.view)}get updatedAt(){return this.viewData.updatedAt}get deepUpdatedAt(){if(this.cachedDeepUpdatedAt)return this.cachedDeepUpdatedAt;let e=this.updatedAt;return this.isList?this.forEach(n=>{if(n instanceof r){let i=n.deepUpdatedAt;i&&(!e||i>e)&&(e=i)}}):this.values().forEach(n=>{if(n instanceof r){let i=n.deepUpdatedAt;i&&(!e||i>e)&&(e=i)}}),this.cachedDeepUpdatedAt=e,e}get isOutdatedVersion(){return this.parent?this.parent.isOutdatedVersion:this.viewData.fromOlderVersion}get length(){return this.view.length}[Symbol.iterator](){let e=0,n=this.view?.length;return{next:()=>e<n?{value:this.get(e++),done:!1}:{value:void 0,done:!0}}}};function eo(r){if(typeof r=="symbol")throw new Error("Symbol keys aren't supported")}function ra(r){if(typeof r!="number")throw new Error("Only number keys are supported in list entities")}var Cr=class{constructor({oid:t,ctx:e,confirmedOperations:n,pendingOperations:i,baseline:o}){this.baseline=null;this.confirmedOperations=[];this.pendingOperations=[];this.computeView=(t=!1)=>{let e=ae(this.baseline?.snapshot??void 0),n=this.baseline?.timestamp??null,i=this.applyOperations(e,!e,this.confirmedOperations,n,n);i.futureSeen&&this.ctx.globalEvents.emit("futureSeen",i.futureSeen);let o=t?i:this.applyOperations(i.view,i.deleted,this.pendingOperations,i.latestTimestamp,null);o.view&&K(o.view,this.oid);let s=!!i.latestTimestamp&&Xn(i.latestTimestamp,this.ctx.getNow())<0,c=!this.baseline&&!this.pendingOperations.length&&!this.confirmedOperations.length;c&&this.ctx.log("warn",`Tried to load Entity ${this.oid} with no data`);let p=o.latestTimestamp??i.latestTimestamp??n,u=p?Zn(p):0;if(!o.view&&!o.deleted&&!c){this.ctx.log("warn",`Entity ${this.oid} has no view, no deleted flag, and not empty`);debugger}return{view:o.view??void 0,deleted:o.deleted,empty:c,fromOlderVersion:s,updatedAt:u}};this.addBaseline=t=>{if(!(this.baseline&&this.baseline.timestamp>=t.timestamp))for(this.baseline=t;this.confirmedOperations[0]?.timestamp<t.timestamp;)this.confirmedOperations.shift()};this.addConfirmedOperations=t=>{let e=0;for(let n of t){let i=this.confirmedOperations.findIndex(s=>s.timestamp>=n.timestamp);i!==-1?this.confirmedOperations[i].timestamp!==n.timestamp&&(this.confirmedOperations.splice(i,0,n),e++):(this.confirmedOperations.push(n),e++);let o=this.pendingOperations.length;this.pendingOperations=this.pendingOperations.filter(s=>n.timestamp!==s.timestamp),e-=o-this.pendingOperations.length}return e};this.addPendingOperation=t=>{this.pendingOperations.push(t)};this.applyOperations=(t,e,n,i,o)=>{let s,c=this.ctx.getNow();for(let p of n)if(!(o&&p.timestamp<=o)){if(Xn(p.timestamp,c)>0){s=p.timestamp;continue}p.data.op==="delete"?e=!0:(t=je(t,p.data),p.data.op==="initialize"&&(e=!1)),(!i||p.timestamp>i)&&(i=p.timestamp)}return{view:t,latestTimestamp:i??null,deleted:e,futureSeen:s}};L(t,"oid is required"),this.ctx=e,this.oid=t,n&&(this.confirmedOperations=n),i&&(this.pendingOperations=i),o&&(this.baseline=o)}},mn=class{constructor({ctx:t,onPendingOperations:e,rootOid:n}){this.entities=new Map;this.get=t=>(L(t,"oid is required"),this.entities.has(t)||this.entities.set(t,new Cr({oid:t,ctx:this.ctx})),this.entities.get(t));this.getAllOids=()=>Array.from(this.entities.keys());this.addConfirmedData=({baselines:t=[],operations:e={},isLocal:n=!1})=>{let i={};for(let o of t){if(!Ce(this.rootOid,o.oid))throw new Error(`Invalid baseline for entity ${this.rootOid}: `+JSON.stringify(o));this.get(o.oid).addBaseline(o)}for(let[o,s]of Object.entries(e)){if(!Ce(this.rootOid,o))throw new Error(`Invalid operations for entity ${this.rootOid}: `+JSON.stringify(s));this.get(o).addConfirmedOperations(s)!==0&&(i[o]??={oid:o,isLocal:n})}return Object.values(i)};this.addPendingData=t=>{let e={};for(let n of t)this.get(n.oid).addPendingOperation(n),e[n.oid]??={oid:n.oid,isLocal:!0};return this.onPendingOperations(t),Object.values(e)};this.replaceAllData=({operations:t={},baselines:e=[]})=>{let n=Array.from(this.entities.keys());this.entities.clear();let i={};for(let o of n)i[o]={oid:o,isLocal:!1};for(let o of e){if(!Ce(this.rootOid,o.oid))throw new Error(`Invalid baseline for entity ${this.rootOid}: `+JSON.stringify(o));this.get(o.oid).addBaseline(o),i[o.oid]??={oid:o.oid,isLocal:!1}}for(let[o,s]of Object.entries(t)){if(!Ce(this.rootOid,o))throw new Error(`Invalid operations for entity ${this.rootOid}: `+JSON.stringify(s));this.get(o).addConfirmedOperations(s),i[o]??={oid:o,isLocal:!1}}return Object.values(i)};this.ctx=t,this.rootOid=n,this.onPendingOperations=e}};var Ot="@@default",gn=class{constructor({batchTimeout:t=200,meta:e,ctx:n,entities:i}){this.currentBatchKey=Ot;this.flushOperations=async(t,e,n)=>{if(this.ctx.log("debug","Flushing",t.length,"operations from batch",e,"to storage / sync"),!!t.length){for(let i of t)i.timestamp=this.meta.now;await this.commitOperations(t,n)}};this.commitOperations=async(t,e)=>{if(t.length){if(e.undoable){let n=await this.createUndo({ops:t,source:e.source});n&&this.ctx.undoHistory.addUndo(n)}await this.entities.addData({operations:t,baselines:[],isLocal:!0})}};this.addOperations=t=>{t.length&&(this.batcher.add({key:this.currentBatchKey,items:t}),this.ctx.log("debug","added",t.length,"ops to batch",this.currentBatchKey,", size = ",this.batcher.getSize(this.currentBatchKey)))};this.batch=({undoable:t=!0,batchName:e=Nt(),max:n=null,timeout:i=this.defaultBatchTimeout}={})=>{let o=this.batcher.add({key:e,max:n,timeout:i,items:[],userData:{undoable:t}}),s={run:c=>(this.currentBatchKey=e,c(),this.currentBatchKey=Ot,s),commit:async()=>(await this.batcher.flush(Ot),o.flush()),flush:()=>s.commit(),discard:()=>{this.batcher.discard(e)}};return s};this.flushAll=()=>Promise.all(this.batcher.flushAll());this.createUndo=async t=>{let e=await this.getInverseOperations(t);return e.length?async()=>{let n=await this.createUndo({ops:e,source:t.source});for(let i of e)i.timestamp=this.meta.now;return await this.commitOperations(e,{undoable:!1}),n}:null};this.getInverseOperations=async({ops:t,source:e})=>{let n=mt(t),i=[],o=()=>this.meta.now;return await Promise.all(Object.entries(n).map(async([s,c])=>{let u=(e??await this.entities.hydrate($(s)))?.__getViewData__(s,"confirmed");if(!u){this.ctx.log("warn","could not find entity",s,"for undo operation",t);return}let m=Li(s,u.view,c,o);i.unshift(...m)})),i};this.meta=e,this.ctx=n,this.entities=i,this.defaultBatchTimeout=t,this.batcher=new Xe(this.flushOperations),this.batcher.add({key:Ot,items:[],max:100,timeout:t,userData:{undoable:!0}})}get isDefaultBatch(){return this.currentBatchKey===Ot}};var yn=class extends se{constructor({ctx:e}){super(e.documentDb,{log:e.log});this.reset=async()=>{let e=Object.keys(this.ctx.schema.collections),n=this.ctx.documentDb.transaction(e,"readwrite");await Promise.all(e.map(i=>{let o=n.objectStore(i);return J(o.clear())})),this.ctx.entityEvents.emit("collectionsChanged",e),this.ctx.log("info","\u{1F4A8} Reset queryable storage")};this.saveEntities=async(e,n)=>{if(e.length===0)return;let i=Array.from(new Set(e.map(s=>me(s.oid).collection))),o={transaction:this.createTransaction(i,{mode:"readwrite",abort:n?.abort})};await Promise.all(e.map(async s=>{let c=s.getSnapshot();try{await this.saveDocument(s.oid,c,o)}catch(p){throw this.ctx.log("error",`Error saving document ${s.oid} (${JSON.stringify(c)})`,p),p instanceof Error?p:new Error("Unknown error saving document")}})),o.transaction.commit(),this.ctx.entityEvents.emit("collectionsChanged",i);for(let s of e)this.ctx.entityEvents.emit("documentChanged",s.oid)};this.saveDocument=async(e,n,{transaction:i})=>{this.ctx.log("debug",`Saving document indexes for querying ${e}`,n);let{collection:o,id:s}=me(e);if(!n)await this.run(o,c=>c.delete(s),{mode:"readwrite",transaction:i}),this.ctx.log("debug",`Deleted document indexes for querying ${e}`);else{let c=this.ctx.schema.collections[o],p=Ht(c,n);await this.run(o,u=>u.put(p),{mode:"readwrite",transaction:i}),this.ctx.log("debug",`Saved document indexes for querying ${e}`,n)}};this.ctx=e,this.addDispose(this.ctx.internalEvents.subscribe("documentDbChanged",n=>{this.db=n}))}};var En=Qe(Bo(),1);var Cn=class extends Ie{constructor({ctx:e,meta:n,files:i}){super();this.events={add:new En.WeakEvent,replace:new En.WeakEvent,resetAll:new En.WeakEvent};this.cache=new Map;this.pendingEntityPromises=new Map;this.abortDataQueueController=new AbortController;this.ongoingResetPromise=null;this.entityFinalizationRegistry=new FinalizationRegistry(e=>{this.ctx.log("debug","Entity GC",e)});this.addData=async e=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not adding incoming data");return}e.reset&&(this.ctx.log("info","Resetting local store to replicate remote synced data - dropping any current transactions"),this.abortDataQueueController.abort(0),this.abortDataQueueController=new AbortController,this.ongoingResetPromise=this.resetData().finally(()=>{this.ongoingResetPromise=null})),this.ongoingResetPromise&&(this.ctx.log("debug","Waiting for ongoing reset to complete"),await this.ongoingResetPromise,this.ctx.log("debug","Ongoing reset complete")),await this.processData(e)};this.resetData=async()=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not resetting local data");return}await this.meta.reset(),await this.queryableStorage.reset(),this.events.resetAll.invoke(this)};this.processData=async e=>{if(this.disposed){this.ctx.log("warn","EntityStore is disposed, not processing incoming data");return}let n=e?.baselines??[],i=e?.operations??[];this.ctx.log("debug","Processing incoming data",{operations:i.length,baselines:n.length,reset:!!e.reset});let o=Array.from(new Set(n.map(m=>$(m.oid)).concat(i.map(m=>$(m.oid))))),s=Fi(n),c=Ti(i);this.ctx.log("debug","Applying data to live entities");for(let m of o){let S=s[m],g=c[m]??[],_=mt(g),w=e.reset?this.events.replace:this.events.add,v=this.pendingEntityPromises.get(m);v?v.then(()=>{w.invoke(this,{oid:m,baselines:S,operations:_,isLocal:!1})}):(this.cache.has(m)&&this.ctx.log("debug","Cache has",m,", an event should follow."),w.invoke(this,{oid:m,baselines:S,operations:_,isLocal:!1}))}let p={abort:this.abortDataQueueController.signal};await this.meta.insertData(e,p);let u=await Promise.all(o.map(async m=>await this.hydrate(m,p)??{oid:m,getSnapshot(){return null}}));try{await this.queryableStorage.saveEntities(u,p)}catch(m){this.disposed?this.ctx.log("warn","Error saving entities to queryable storage - EntityStore is disposed",m):this.ctx.log("error","Error saving entities to queryable storage",m)}};this.hydrate=async(e,n)=>{if(!Pi(e))throw new Error("Cannot hydrate non-root entity");if(this.cache.has(e)){this.ctx.log("debug","Hydrating entity from cache",e);let o=this.cache.get(e);if(o){let s=o.deref();if(s)return s.deleted?null:s;this.ctx.log("debug","Removing GC'd entity from cache",e),this.cache.delete(e)}}let i=this.pendingEntityPromises.get(e);if(i)return this.ctx.log("debug","Waiting for entity hydration",e),i;{this.ctx.log("debug","Hydrating entity from storage",e);let o=this.constructEntity(e);if(!o)return null;let s=this.loadEntity(o,n);return s.finally(()=>{this.pendingEntityPromises.delete(e)}),this.pendingEntityPromises.set(e,s),s}};this.destroy=async()=>{this.dispose(),await this.batcher.flushAll()};this.create=async(e,n,{undoable:i=!0}={})=>{this.ctx.log("debug","Creating new entity",n);let{collection:o}=me(n);Vt(e);let s=tt(e,this.files.add);K(s,n);let c=this.constructEntity(n);if(!c)throw new Error(`Could not put new document: no schema exists for collection ${o}`);let p=this.meta.patchCreator.createInitialize(s,n);await this.batcher.commitOperations(p,{undoable:!!i,source:c});let u=mt(p);return this.events.add.invoke(this,{operations:u,isLocal:!0,oid:n}),this.cache.set(n,this.ctx.weakRef(c)),c};this.deleteAll=async(e,n)=>{this.ctx.log("info","Deleting documents",e),L(e.every(s=>s===$(s)),"Only root documents may be deleted via client methods");let i=await Promise.all(e.flatMap(async s=>(await this.hydrate(s))?.__getFamilyOids__()??[]));e.forEach(s=>{this.cache.delete(s),this.ctx.log("debug","Deleted document from cache",s)});let o=this.meta.patchCreator.createDeleteAll(i.flat());await this.batcher.commitOperations(o,{undoable:n?.undoable===void 0?!0:n.undoable})};this.delete=async(e,n)=>this.deleteAll([e],n);this.getCollectionSchema=e=>{let n=this.ctx.schema.collections[e];return n?{schema:{type:"object",nullable:!1,properties:n.fields},readonlyKeys:[n.primaryKey]}:(this.ctx.log("warn",`Missing schema for collection: ${e}`),{schema:null,readonlyKeys:[]})};this.constructEntity=e=>{let{collection:n}=me(e),{schema:i,readonlyKeys:o}=this.getCollectionSchema(n);if(!i)return null;if(this.disposed)throw new Error("Cannot hydrate entity after store has been disposed");let s=new mn({ctx:this.ctx,onPendingOperations:this.onPendingOperations,rootOid:e});return new ue({ctx:this.ctx,oid:e,schema:i,readonlyKeys:o,files:this.files,metadataFamily:s,patchCreator:this.meta.patchCreator,events:this.events})};this.onPendingOperations=e=>{this.batcher.addOperations(e)};this.loadEntity=async(e,n)=>{let{operations:i,baselines:o}=await this.meta.getDocumentData(e.oid,n);return!o.length&&!Object.keys(i).length?(this.ctx.log("debug","No data found for entity",e.oid),null):(this.ctx.log("debug","Loaded entity from storage",e.oid),this.events.replace.invoke(this,{oid:e.oid,baselines:o,operations:i,isLocal:!1}),this.cache.set(e.oid,this.ctx.weakRef(e)),this.entityFinalizationRegistry.register(e,e.oid),e)};this.ctx=e,this.meta=n,this.files=i,this.queryableStorage=new yn({ctx:e}),this.batcher=new gn({ctx:e,meta:n,entities:this})}get batch(){return this.batcher.batch}get flushAllBatches(){return this.batcher.flushAll}};var Kr=Symbol("handleMessage"),wa,Dt=class extends V{constructor({initialPresence:e,updateBatchTimeout:n=200,defaultProfile:i,replicaStore:o}){super();this._peers={};this._self={profile:{}};this._selfReplicaIds=new Set;this._peerIds=new Array;this.isSelf=(e,n)=>e.id===n.replicaId||this._selfReplicaIds.has(n.replicaId)||this._self.id===n.id;this[wa]=async(e,n)=>{let i=!1,o=new Set(this.peerIds);if(n.type==="presence-changed")this.isSelf(e,n.userInfo)?(this._self=n.userInfo,this._selfReplicaIds.add(n.userInfo.replicaId),this.emit("selfChanged",n.userInfo)):(o.add(n.userInfo.id),this._peers[n.userInfo.id]=n.userInfo,i=!0,this.emit("peerChanged",n.userInfo.id,n.userInfo));else if(n.type==="sync-resp"){this._peers={},o.clear();for(let[s,c]of Object.entries(n.peerPresence))this.isSelf(e,c)?(this._self=c,this._selfReplicaIds.add(c.replicaId),this.emit("selfChanged",c)):(i=!0,o.add(s),this._peers[s]=c,this.emit("peerChanged",s,c))}else if(n.type==="presence-offline"){o.delete(n.userId),this._selfReplicaIds.delete(n.replicaId);let s=this._peers[n.userId];delete this._peers[n.userId],i=!0,this.emit("peerLeft",n.userId,s)}i&&(this._peerIds=Array.from(o),this.emit("peersChanged",this._peers))};this.update=async e=>{this._updateBatch.update({items:[e]}),this.self.presence={...this.self.presence,...e},this.emit("selfChanged",this.self)};this.flushPresenceUpdates=e=>{let n=e.reduce((i,o)=>({...i,...o}),this.self.presence);this.emit("update",n)};this.self.presence=e,this.self.profile=i,this.self.id="",this.self.replicaId="",o.get().then(s=>{this.self.replicaId=s.id}),this._updateBatcher=new Xe(this.flushPresenceUpdates),this._updateBatch=this._updateBatcher.add({max:25,timeout:n,items:[],key:"default"})}static{wa=Kr}get self(){return this._self}get peers(){return this._peers}get peerIds(){return this._peerIds}get everyone(){let e={...this._peers};return e[this.self.id]=this.self,e}get selfReplicaIds(){return this._selfReplicaIds}};var _n=class{constructor({endpointProvider:t,log:e}){this.uploadFile=async t=>{let e=t.file;if(!e)throw new Error("Cannot upload a non-local file");let{files:n,token:i}=await this.endpointProvider.getEndpoints(),o=new window.FormData;o.append("file",e);try{let s=await fetch(n+`/${t.id}`,{method:"POST",body:o,credentials:"include",headers:{Authorization:`Bearer ${i}`}});return s.ok?{success:!0,retry:!1}:(this.log("error","File upload failed",s.status,await s.text()),{success:!1,retry:s.status>=500})}catch(s){return this.log("error","File upload failed",s),{success:!1,retry:!0}}};this.getFile=async t=>{let{files:e,token:n}=await this.endpointProvider.getEndpoints();try{let i=await fetch(e+`/${t}`,{method:"GET",credentials:"include",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}});return i.ok?{success:!0,data:await i.json()}:(this.log("error","File information fetch failed",i.status,await i.text()),{success:!1,retry:i.status>=500||i.status===404})}catch(i){return this.log("error","File information fetch failed",i),{success:!1,error:i,retry:!0}}};this.endpointProvider=t,this.log=e}};var rt=class extends V{constructor({interval:e=15*1e3,deadlineLength:n=3*1e3,restartOnTabFocus:i=!0}={}){super();this.nextBeat=null;this.deadline=null;this.keepAlive=()=>{this.deadline&&(clearTimeout(this.deadline),this.deadline=null,this.start())};this.start=(e=!1)=>{this.stop(),e?this.beat():this.nextBeat=setTimeout(this.beat,this._interval)};this.stop=()=>{this.nextBeat&&clearTimeout(this.nextBeat),this.deadline&&clearTimeout(this.deadline)};this.beat=async()=>{this.emit("beat"),this.deadline=setTimeout(this.onDeadline,this.deadlineLength)};this.onDeadline=()=>{this.deadline=null,this.emit("missed")};this.setInterval=e=>{this._interval=e};this._interval=e,this.deadlineLength=n,typeof window<"u"&&i&&(window.addEventListener("pageshow",()=>this.start(!0)),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&this.start(!0)}))}get interval(){return this._interval}};var Pn=class extends V{constructor({endpointProvider:e,meta:n,presence:i,interval:o=15*1e3,log:s=()=>{}}){super();this.mode="pull";this._isConnected=!1;this._status="paused";this._hasSynced=!1;this.setInterval=e=>{this.heartbeat.setInterval(e)};this.sendRequest=async e=>{this.log("Sending sync request",e);try{let{http:n,token:i}=await this.endpointProvider.getEndpoints(),o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({messages:e}),credentials:"include"});if(o.ok){this.heartbeat.keepAlive();let s=await o.json();for(let c of s.messages)this.handleServerMessage(c);this._isConnected||(this._isConnected=!0,this.emit("onlineChange",!0))}else{this.log("Sync request failed",o.status,await o.text()),this._isConnected&&(this._isConnected=!1,this.emit("onlineChange",!1));let s=await o.json();Ui(s)&&s.code===4012&&(this.endpointProvider.clearCache(),this.heartbeat.keepAlive()),o.status>=500&&this.heartbeat.keepAlive()}}catch(n){this._isConnected&&(this._isConnected=!1,this.emit("onlineChange",!1)),this.log(n),this.heartbeat.keepAlive()}};this.handleServerMessage=async e=>{e.type==="sync-resp"&&(e.ackThisNonce&&(this.log("Sending sync ack",e.ackThisNonce),this.sendRequest([await this.meta.messageCreator.createAck(e.ackThisNonce)])),this._hasSynced=!0),this.emit("message",e)};this.send=e=>{switch(e.type){case"presence-update":case"sync":case"heartbeat":return this.sendRequest([e]);case"op":if(this._hasSynced)return this.sendRequest([e]);break}};this.destroy=()=>{this.dispose(),this.stop()};this.onHeartbeat=async()=>{this.sendRequest([await this.meta.messageCreator.createPresenceUpdate(this.presence.self.presence),await this.meta.messageCreator.createSyncStep1()])};this.onHeartbeatMissed=async()=>{this.emit("onlineChange",!1),this.log("Missed heartbeat"),this._isConnected=!1};this.log=s,this.meta=n,this.presence=i,this.endpointProvider=e,this.heartbeat=new rt({interval:o}),this.heartbeat.subscribe("beat",this.onHeartbeat),this.heartbeat.subscribe("missed",this.onHeartbeatMissed)}get interval(){return this.heartbeat.interval}start(){this.status!=="active"&&(this.heartbeat.start(!0),this._status="active")}stop(){this.heartbeat.stop(),this._status="paused"}reconnect(){this.heartbeat.start(!0)}ignoreIncoming(){this.stop()}get isConnected(){return this._isConnected}get status(){return this._status}};function $r(r){this.message=r}$r.prototype=new Error,$r.prototype.name="InvalidCharacterError";var Mo=typeof window<"u"&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,"");if(t.length%4==1)throw new $r("'atob' failed: The string to be decoded is not correctly encoded.");for(var e,n,i=0,o=0,s="";n=t.charAt(o++);~n&&(e=i%4?64*e+n:n,i++%4)?s+=String.fromCharCode(255&e>>(-2*i&6)):0)n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(n);return s};function va(r){var t=r.replace(/-/g,"+").replace(/_/g,"/");switch(t.length%4){case 0:break;case 2:t+="==";break;case 3:t+="=";break;default:throw"Illegal base64url string!"}try{return function(e){return decodeURIComponent(Mo(e).replace(/(.)/g,function(n,i){var o=i.charCodeAt(0).toString(16).toUpperCase();return o.length<2&&(o="0"+o),"%"+o}))}(t)}catch{return Mo(t)}}function An(r){this.message=r}function Sa(r,t){if(typeof r!="string")throw new An("Invalid token specified");var e=(t=t||{}).header===!0?0:1;try{return JSON.parse(va(r.split(".")[e]))}catch(n){throw new An("Invalid token specified: "+n.message)}}An.prototype=new Error,An.prototype.name="InvalidTokenError";var jo=Sa;var Tn=class{constructor(t){this.config=t;this.cached=null;this.type=0;this.getEndpoints=async()=>{if(this.cached)return this.cached;let t;this.config.fetchAuth?t=await this.config.fetchAuth():t=await fetch(this.config.authEndpoint,{credentials:"include"}).then(c=>{if(c.ok)return c.json();throw new Error(`Auth endpoint returned non-200 response: ${c.status}`)}),L(t.accessToken,"No access token provided from auth endpoint");let e=jo(t.accessToken);L(e.url,"No sync endpoint provided from auth endpoint"),L(e.type!==void 0,"No replica type provided from auth endpoint"),this.type=parseInt(e.type+"");let n=new URL(e.url);n.protocol=n.protocol.replace("ws","http");let i=n.toString();n.protocol=n.protocol.replace("http","ws");let o=n.toString(),s=e.file;if(!s){let c=new URL(i);c.pathname=c.pathname+"/files",s=c.toString()}return this.cached={http:i,websocket:o,files:s,token:t.accessToken},this.cached};this.clearCache=()=>{this.cached=null};if(!t.authEndpoint&&!t.fetchAuth)throw new Error("Either authEndpoint or fetchAuth must be provided to ServerSyncEndpointProvider")}};var Fn=class extends V{constructor(e){super();this.timer=null;this.isScheduled=!1;this.next=()=>{this.isScheduled||(this.isScheduled=!0,this.timer=setTimeout(()=>{this.emit("trigger"),this.isScheduled=!1,this.backoff.next()},this.backoff.current))};this.reset=()=>{this.backoff.reset(),this.timer&&(clearTimeout(this.timer),this.timer=null)};this.backoff=e}},Rn=class{constructor(t,e){this.current=0;this.next=()=>{this.current=Math.min(this.max,this.current*this.factor)};this.reset=()=>{this.current=0};this.max=t,this.factor=e}};var kn=class extends V{constructor({endpointProvider:e,meta:n,presence:i,log:o}){super();this.socket=null;this.connectQueue=[];this.syncQueue=[];this.incomingQueue=[];this._status="paused";this.synced=!1;this.hasStartedSync=!1;this._ignoreIncoming=!1;this.mode="realtime";this.log=(...e)=>{};this.heartbeat=new rt;this.reconnectScheduler=new Fn(new Rn(60*1e3,1.5));this.onOpen=()=>{if(!this.socket)throw new Error("Invalid sync state: online but socket is null");if(this.synced=!1,this.connectQueue.length){for(let e of this.connectQueue)this.log("Sending queued message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e));this.connectQueue=[]}this.log("Sync connected"),this.onOnlineChange(!0),this.reconnectScheduler.reset()};this.onOnlineChange=async e=>{this.log("Socket online change",e),!this.disposed&&(e?(this.log("Starting sync"),this.hasStartedSync=!0,this.synced=!1,this.send(await this.meta.messageCreator.createPresenceUpdate(this.presence.self.presence)),this.send(await this.meta.messageCreator.createSyncStep1()),this.heartbeat.start()):(this.hasStartedSync=!1,this.synced=!1,this.heartbeat.stop()),this.emit("onlineChange",e))};this.onMessage=async e=>{if(this._ignoreIncoming){this.log("Ignoring incoming message (ignore incoming flag set)",e.data);return}let n=JSON.parse(e.data);switch(n.type){case"sync-resp":if(n.ackThisNonce&&this.send(await this.meta.messageCreator.createAck(n.ackThisNonce)),this.hasStartedSync=!0,this.synced=!0,this.syncQueue.length)if(n.overwriteLocalData)this.log("warn","Overwriting local data - dropping outgoing message queue"),this.syncQueue=[];else{for(let i of this.syncQueue)this.send(i);this.syncQueue=[]}if(this.emit("message",n),this.incomingQueue.length){for(let i of this.incomingQueue)this.emit("message",i);this.incomingQueue=[]}break;case"need-since":case"presence-changed":case"presence-offline":this.emit("message",n);break;case"op-re":if(!this.synced){this.log("Enqueueing op-re message because sync hasn't finished yet",n),this.incomingQueue.push(n);break}this.emit("message",n);break;case"heartbeat-response":this.heartbeat.keepAlive(),this.emit("message",n);break;default:this.synced&&this.emit("message",n);break}};this.onError=e=>{this.log(e),this.reconnectScheduler.next(),this.log("Attempting reconnect to websocket sync")};this.onClose=e=>{this.log("Sync disconnected"),this.onOnlineChange(!1),this.onError(e)};this.initializeSocket=async()=>{let e=await this.endpointProvider.getEndpoints();return this.socket=new WebSocket(e.websocket,["Bearer",e.token]),this.socket.addEventListener("message",this.onMessage),this.socket.addEventListener("open",this.onOpen),this.socket.addEventListener("error",this.onError),this.socket.addEventListener("close",this.onClose),this.socket};this.sendHeartbeat=async()=>{this.send(await this.meta.messageCreator.createHeartbeat())};this.reconnect=()=>{this.stop(),this.start()};this.canSkipSyncWait=e=>e.type==="sync"||e.type==="presence-update"||e.type==="sync-ack"||e.type==="heartbeat";this.send=e=>{this.status==="active"&&(!this.hasStartedSync&&!this.canSkipSyncWait(e)||(this.canSkipSyncWait(e)?this.socket?.readyState===WebSocket.OPEN?(this.log("Sending message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e))):(this.log("Enqueueing message until socket is open",JSON.stringify(e,null,2)),this.connectQueue.push(e)):this.synced?this.socket?.readyState===WebSocket.OPEN&&(this.log("Sending message",JSON.stringify(e,null,2)),this.socket.send(JSON.stringify(e))):this.hasStartedSync&&(this.log("Enqueueing message until synced",JSON.stringify(e,null,2)),this.syncQueue.push(e))))};this.destroy=()=>{this.dispose(),this.stop()};this.start=()=>{this.socket||(this.initializeSocket(),this._status="active")};this.stop=()=>{this.socket?.removeEventListener("message",this.onMessage),this.socket?.removeEventListener("close",this.onClose),this.socket?.close(),this.socket=null,this._status="paused"};this.log=o||this.log,this.endpointProvider=e,this.meta=n,this.presence=i,this.reconnectScheduler.subscribe("trigger",this.initializeSocket),this.heartbeat.subscribe("beat",this.sendHeartbeat)}ignoreIncoming(){this.incomingQueue=[],this._ignoreIncoming=!0}get isConnected(){return this.socket?.readyState===WebSocket.OPEN}get status(){return this._status}};var Bn=class extends V{constructor({meta:e}){super();this.mode="pull";this.destroy=()=>{};this.isConnected=!1;this.status="paused";this.pullInterval=0;this.uploadFile=async()=>({success:!1,retry:!1});this.getFile=async()=>({success:!1,retry:!1});this.presence=new Dt({initialPresence:null,defaultProfile:null,replicaStore:e.localReplica})}send(){}start(){}stop(){}ignoreIncoming(){}reconnect(){}setMode(){}setPullInterval(){}},it=class extends V{constructor({authEndpoint:e,fetchAuth:n,initialPresence:i,automaticTransportSelection:o=!0,autoStart:s,initialTransport:c,pullInterval:p,presenceUpdateBatchTimeout:u,defaultProfile:m,useBroadcastChannel:S},{meta:g,log:_,onData:w}){super();this.broadcastChannel=null;this._activelySyncing=!1;this.handleBroadcastChannelMessage=e=>{e.data.type==="sync"&&this.handleMessage(e.data.message,{source:"broadcastChannel"})};this.onTokenExpired=()=>{this.endpointProvider.clearCache()};this.handleMessage=async(e,{source:n}={source:"network"})=>{if(e.type==="op-re"||e.type==="sync-resp")for(let i of e.operations)this.meta.time.update(i.timestamp);switch(this.log("sync message",JSON.stringify(e,null,2)),e.type){case"op-re":await this.onData({operations:e.operations,baselines:e.baselines}),e.globalAckTimestamp&&await this.meta.setGlobalAck(e.globalAckTimestamp);break;case"global-ack":await this.meta.setGlobalAck(e.timestamp);break;case"sync-resp":this._activelySyncing=!0,this.emit("syncingChange",!0),await this.onData({operations:e.operations,baselines:e.baselines,reset:e.overwriteLocalData}),e.globalAckTimestamp&&await this.meta.setGlobalAck(e.globalAckTimestamp),await this.meta.updateLastSynced(e.ackedTimestamp),this._activelySyncing=!1,this.emit("syncingChange",!1);break;case"need-since":this.activeSync.send(await this.meta.messageCreator.createSyncStep1(e.since));break;case"server-ack":await this.meta.updateLastSynced(e.timestamp)}n==="network"&&this.broadcastChannel?.postMessage({type:"sync",message:e}),this.presence[Kr](await this.meta.localReplica.get(),e)};this.handleOnlineChange=e=>{this.emit("onlineChange",e)};this.handlePresenceUpdate=async e=>{this.send(await this.meta.messageCreator.createPresenceUpdate(e))};this.setMode=e=>{if(e==="realtime"&&!this.canDoRealtime)throw new Error("Cannot switch to realtime mode, because the current auth token does not allow it");let n;e==="realtime"?n=this.webSocketSync:n=this.pushPullSync,n!==this.activeSync&&(this.log("switching to",e,"mode"),this.activeSync.status==="active"&&n.start(),this.activeSync.stop(),this.activeSync=n)};this.setPullInterval=e=>{this.pushPullSync.setInterval(e)};this.send=e=>{if(this.activeSync.status==="active")return this.activeSync.send(e)};this.uploadFile=async e=>this.activeSync.status==="active"?this.fileSync.uploadFile(e):{success:!1,retry:!1};this.getFile=async e=>{if(this.activeSync.status==="active")return this.fileSync.getFile(e);throw new Error("Offline, cannot retrieve remote file details")};this.start=()=>this.activeSync.start();this.stop=()=>this.activeSync.stop();this.destroy=()=>{this.dispose(),this.webSocketSync.destroy(),this.pushPullSync.destroy()};this.reconnect=()=>this.activeSync.reconnect();if(this.meta=g,this.onData=w,this.log=_||(()=>{}),this.presence=new Dt({initialPresence:i,defaultProfile:m,updateBatchTimeout:u,replicaStore:g.localReplica}),this.endpointProvider=new Tn({authEndpoint:e,fetchAuth:n}),this.webSocketSync=new kn({endpointProvider:this.endpointProvider,meta:g,presence:this.presence,log:this.log}),this.pushPullSync=new Pn({endpointProvider:this.endpointProvider,meta:g,presence:this.presence,log:this.log,interval:p}),this.fileSync=new _n({endpointProvider:this.endpointProvider,log:this.log}),S&&"BroadcastChannel"in window&&(this.broadcastChannel=new BroadcastChannel("verdant"),this.broadcastChannel.addEventListener("message",this.handleBroadcastChannelMessage)),c==="realtime"?this.activeSync=this.webSocketSync:this.activeSync=this.pushPullSync,this.presence.subscribe("update",this.handlePresenceUpdate),this.meta.subscribe("message",this.send),this.webSocketSync.subscribe("message",this.handleMessage),this.webSocketSync.subscribe("onlineChange",this.handleOnlineChange),this.pushPullSync.subscribe("message",this.handleMessage),this.pushPullSync.subscribe("onlineChange",this.handleOnlineChange),o&&this.canDoRealtime){let v=()=>{I&&clearTimeout(I);let D=Object.keys(this.presence.peers).length>0||o!=="peers-only"&&this.presence.selfReplicaIds.size>1;D&&this.mode==="pull"?this.setMode("realtime"):!D&&this.mode==="realtime"&&(I=setTimeout(()=>{Object.keys(this.presence.peers).length===0&&this.setMode("pull")},1e3))},I;this.presence.subscribe("peersChanged",v),o!=="peers-only"&&this.presence.subscribe("selfChanged",v)}s&&this.start()}get canDoRealtime(){return this.endpointProvider.type===0||this.endpointProvider.type===2||this.endpointProvider.type===5}get syncing(){return this._activelySyncing}get pullInterval(){return this.pushPullSync.interval}ignoreIncoming(){this.activeSync.ignoreIncoming()}get isConnected(){return this.activeSync.isConnected}get status(){return this.activeSync.status}get mode(){return this.activeSync.mode}};function Oa(r){return r!==null}function zr(r){return Array.isArray(r)?r.map(zr).filter(Oa):r instanceof ue&&r.deleted?null:r}function ke(r,t){return!r&&!t||r&&t&&Te(r)===Te(t)}var qr=Symbol("ON_ALL_UNSUBSCRIBED"),fe=Symbol("UPDATE"),Ia,ge=class extends Ie{constructor({initial:e,context:n,collection:i,key:o,shouldUpdate:s}){super();this._internalUnsubscribes=[];this._status="initial";this._executionPromise=null;this.setValue=e=>{if(this._rawValue=e,this.subscribeToDeleteAndRestore(this._rawValue),this._value=zr(e),Array.isArray(this._value)&&this._value.some(n=>n.getSnapshot()===null))debugger;this._status="ready",this._events.emit("change",this._value)};this.refreshValue=()=>{this.setValue(this._rawValue)};this.subscribeToDeleteAndRestore=e=>{for(;this._internalUnsubscribes.length;)this._internalUnsubscribes.pop()?.();Array.isArray(e)?e.forEach(n=>{n instanceof ue&&(this._internalUnsubscribes.push(n.subscribe("delete",this.refreshValue)),this._internalUnsubscribes.push(n.subscribe("restore",this.refreshValue)))}):e instanceof ue&&(this._internalUnsubscribes.push(e.subscribe("delete",this.refreshValue)),this._internalUnsubscribes.push(e.subscribe("restore",()=>{this.refreshValue()})))};this.execute=()=>(this.context.log("debug","Executing query",this.key),this._status==="initial"?this._status="initializing":this._status==="ready"&&(this._status="revalidating"),this._executionPromise=this.run().then(()=>this._value).catch(e=>{if(e instanceof Error){if(e.name==="InvalidStateError"||e.name==="InvalidAccessError")return this._value;throw e}else throw new Error("Unknown error executing query")}),this._executionPromise);this[Ia]=e=>{this._allUnsubscribedHandler=e};this._rawValue=e,this._value=e,this._events=new V(p=>{p==="change"&&this._allUnsubscribedHandler?.(this)}),this.context=n,this.key=o,this.collection=i;let c=s||(p=>p.includes(i));this.addDispose(this.context.entityEvents.subscribe("collectionsChanged",p=>{c(p)&&(this.context.log("info","Updating query",this.key),this.execute())}))}static{Ia=qr}get current(){return this._value}get resolved(){return this.status==="ready"?Promise.resolve(this._value):this._executionPromise??this.execute()}get subscribed(){return this._events.totalSubscriberCount()>0}get status(){return this._status}subscribe(e,n){if(n===void 0&&typeof e=="function")return this.resolved,this._events.subscribe("change",e);if(e==="change"&&n!==void 0)return this.resolved,this._events.subscribe("change",n);if(e==="statusChange"&&typeof n=="function")return this._events.subscribe(e,n);throw new Error("Invalid invocation of Query.subscribe")}};var Mn=class extends ge{constructor({id:e,hydrate:n,...i}){super({initial:null,...i});this.run=async()=>{let e=await this.hydrate(this.oid);this.setValue(e)};this.oid=Z(i.collection,e),this.hydrate=n}};var Da,jn=class extends ge{constructor({index:e,hydrate:n,...i}){super({initial:null,...i});this.run=async()=>{let e=await an({collection:this.collection,index:this.index,context:this.context});this.setValue(e?await this.hydrate(e):null)};this[Da]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n}static{Da=fe}};var Ea,Ln=class extends ge{constructor({index:e,hydrate:n,pageSize:i,page:o,...s}){super({initial:[],...s});this._hasNextPage=!1;this.run=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,index:this.index,context:this.context,limit:this._pageSize,offset:this._page*this._pageSize});this._hasNextPage=n,this.setValue(await Promise.all(e.map(this.hydrate)))};this.nextPage=async()=>{this.hasNextPage&&(this._page++,await this.run())};this.previousPage=async()=>{this._page!==0&&(this._page--,await this.run())};this.setPage=async e=>{this._page=e,await this.run()};this[Ea]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n,this._pageSize=i,this._page=o}static{Ea=fe}get pageSize(){return this._pageSize}get page(){return this._page}get hasNextPage(){return this._hasNextPage}get hasPreviousPage(){return this._page>0}};var Ca,Nn=class extends ge{constructor({hydrate:e,pageSize:n,index:i,...o}){super({initial:[],...o});this._upToPage=1;this._hasNextPage=!1;this.run=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,context:this.context,limit:this._pageSize*this._upToPage,offset:0,index:this.index});this._hasNextPage=n,this.setValue(await Promise.all(e.map(this.hydrate)))};this.loadMore=async()=>{let{result:e,hasNextPage:n}=await wt({collection:this.collection,context:this.context,limit:this._pageSize,offset:this._pageSize*this._upToPage,index:this.index});this._hasNextPage=n,this._upToPage++,this.setValue([...this.current,...await Promise.all(e.map(this.hydrate))])};this[Ca]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=i,this.hydrate=e,this._pageSize=n}static{Ca=fe}get pageSize(){return this._pageSize}get hasMore(){return this._hasNextPage}};var _a,Vn=class extends ge{constructor({index:e,hydrate:n,...i}){super({initial:[],...i});this.run=async()=>{let e=await cn({collection:this.collection,index:this.index,context:this.context});this.context.log("debug",`FindAllQuery: ${e.length} oids found: ${e}`),this.setValue(await Promise.all(e.map(this.hydrate)))};this[_a]=e=>{ke(this.index,e)||(this.index=e,this.execute())};this.index=e,this.hydrate=n}static{_a=fe}};var Un=class{constructor({collection:t,cache:e,entities:n,context:i,documentManager:o}){this.serializeIndex=t=>t?Te(t):"";this.get=t=>{let e=`get:${this.collection}:${t}`;return this.cache.getOrSet(e,()=>new Mn({id:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:e}))};this.findOne=({index:t,key:e}={})=>{let n=e||`findOne:${this.collection}:${this.serializeIndex(t)}`;return this.cache.getOrSet(n,()=>new jn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:n}),i=>{i[fe](t)})};this.findAll=({index:t,key:e}={})=>{let n=e||`findAll:${this.collection}:${this.serializeIndex(t)}`;return this.cache.getOrSet(n,()=>new Vn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:n}),i=>{i[fe](t)})};this.findPage=({index:t,pageSize:e,page:n,key:i})=>{let o=i||`findPage:${this.collection}:${this.serializeIndex(t)}:${e}`;return this.cache.getOrSet(o,()=>new Ln({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:o,pageSize:e,page:n}),s=>{s[fe](t)})};this.findAllInfinite=({index:t,pageSize:e,key:n})=>{let i=n||`findAllInfinite:${this.collection}:${this.serializeIndex(t)}:${e}`;return this.cache.getOrSet(i,()=>new Nn({index:t,collection:this.collection,hydrate:this.hydrate,context:this.context,key:i,pageSize:e}),o=>{o[fe](t)})};this.cache=e,this.collection=t,this.hydrate=n.hydrate,this.context=i,this.documentManager=o,this.put=this.documentManager.create.bind(this.documentManager,this.collection),this.delete=this.documentManager.delete.bind(this.documentManager,this.collection),this.deleteAll=this.documentManager.deleteAllFromCollection.bind(this.documentManager,this.collection)}};var Kn=class extends Ie{constructor({evictionTime:e=5*1e3,context:n}){super();this._cache=new Map;this.onQueryUnsubscribed=e=>{setTimeout(()=>{e.subscribed||this._cache.get(e.key)===e&&this._cache.delete(e.key)},this._evictionTime)};this.dropAll=()=>{this._cache.forEach(e=>e.dispose()),this._cache.clear()};this._evictionTime=e,this.context=n}get(e){return this._cache.get(e)||null}set(e){return this._cache.set(e.key,e),e[qr](this.onQueryUnsubscribed),e}getOrSet(e,n,i){let o=this.get(e);return o?(i?.(o),o):this.set(n())}};var He=class extends V{constructor(e,n,i){super();this.config=e;this.context=n;this._closed=!1;this.addData=e=>this._entities.addData(e);this.stats=async()=>{let e=Object.keys(this.schema.collections),n={};for(let u of e)try{n[u]=await yt(this.documentDb,u)}catch(m){this.context.log?.("error",m)}let i=await this.meta.stats(),o=typeof navigator<"u"&&typeof navigator.storage<"u"&&"estimate"in navigator.storage?await navigator.storage.estimate():void 0,s=Object.values(n).reduce((u,{size:m})=>u+m,0),c=i.baselinesSize.size+i.operationsSize.size,p=c/s;return{collections:n,meta:i,storage:o,totalMetaSize:c,totalCollectionsSize:s,metaToDataRatio:p,quotaUsage:o?.usage&&o?.quota?o.usage/o.quota:void 0}};this.close=async()=>{this._closed=!0,this.sync.ignoreIncoming(),await this._entities.flushAllBatches(),this.sync.stop(),this.sync.destroy(),await this._entities.destroy(),this.meta.close(),await new Promise(async e=>{await Ke(this.documentDb),await Ke(this.metaDb),e()}),this.context.log?.("Client closed")};this.__dangerous__resetLocal=async()=>{this.sync.stop(),await Yt(this.namespace,indexedDB)};this.export=async()=>{let e=await this.meta.export();return Buffer.from(JSON.stringify(e))};this.import=async e=>{this.context.log("Importing data..."),await Ke(this.context.documentDb);let n=JSON.parse(e.toString());await this.meta.resetFrom(n);let i=n.schema.version,o=indexedDB.deleteDatabase([this.namespace,"collections"].join("_"));await new Promise((c,p)=>{o.onsuccess=c,o.onerror=p});let s=this.context.schema;this.context.schema=n.schema,this.context.documentDb=await vt({meta:this.meta,migrations:this.config.migrations,context:this.context,version:i}),this.context.internalEvents.emit("documentDbChanged",this.documentDb),this.context.log("Re-initializing data from imported data..."),await this._entities.addData({operations:n.operations,baselines:n.baselines,reset:!0}),await Ke(this.context.documentDb),this.context.log("Migrating up to latest schema..."),this.context.schema=s,this.context.documentDb=await vt({meta:this.meta,migrations:this.config.migrations,context:this.context,version:s.version}),this.context.internalEvents.emit("documentDbChanged",this.documentDb)};this.meta=i.meta,this.collectionNames=Object.keys(n.schema.collections),this._sync=this.config.syncConfig&&!n.schema.wip?new it(this.config.syncConfig,{meta:this.meta,onData:this.addData,log:this.context.log}):new Bn({meta:this.meta}),n.schema.wip&&this.config.syncConfig&&n.log("warn","\u26A0\uFE0F\u26A0\uFE0F Sync is disabled for WIP schemas. Commit your schema changes to start syncing again. \u26A0\uFE0F\u26A0\uFE0F"),this._fileManager=new pn({db:this.metaDb,sync:this.sync,context:this.context,config:this.config.files,meta:this.meta}),this._entities=new Cn({ctx:this.context,meta:this.meta,files:this._fileManager}),this._queryCache=new Kn({context:n}),this._documentManager=new un(this.meta,this.schema,this._entities);let o=Di(()=>{this.emit("futureSeen")},300);this.context.globalEvents.subscribe("futureSeen",o),this.documentDb.addEventListener("versionchange",()=>{this.context.log?.(`Another tab has requested a version change for ${this.namespace}`),this.documentDb.close(),typeof window<"u"&&window.location.reload()}),this.metaDb.addEventListener("versionchange",()=>{this.context.log?.(`Another tab has requested a version change for ${this.namespace}`),this.metaDb.close(),typeof window<"u"&&window.location.reload()});for(let[s,c]of Object.entries(n.schema.collections)){let p=s;this[p]=new Un({collection:p,cache:this._queryCache,context:this.context,entities:this.entities,documentManager:this.documentManager})}}get sync(){return this._sync}get entities(){return this._entities}get documentManager(){return this._documentManager}get documentDb(){return this.context.documentDb}get metaDb(){return this.context.metaDb}get schema(){return this.context.schema}get namespace(){return this.context.namespace}get undoHistory(){return this.context.undoHistory}get presence(){return this.sync.presence}get batch(){return this.entities.batch}};var Et=class{constructor(t){this.value=t}deref(){return this.value}};var Lo=Symbol("metadataVersion");var $n=class{constructor(t){this.init=t;this._initializing=!1;this.initialize=async t=>{if(typeof window>"u"&&!t.indexedDb)throw new Error("A verdant client was initialized in an environment without IndexedDB. If you are using verdant in a server-rendered framework, you must enforce that all clients are initialized on the client-side, or you must provide some mock interface of IDBFactory to the ClientDescriptor options.");if(this._initializing||this._resolvedValue)return this._readyPromise;this._initializing=!0;try{let e;return t.schema.wip?e=await this.initializeWIPDatabases(t):(e=await this.initializeDatabases(t),this.cleanupWIPDatabases(t)),this.resolveReady(e),this._resolvedValue=e,e}catch(e){throw e instanceof Error?(this.rejectReady(e),e):new Error("Unknown error initializing storage")}finally{this._initializing=!1}};this.initializeDatabases=async t=>{let e=t[Lo],{db:n}=await on({indexedDB:t.indexedDb,log:t.log,namespace:t.namespace,metadataVersion:e}),i={namespace:this._namespace,metaDb:n,schema:t.schema,log:t.log||(()=>{}),undoHistory:t.undoHistory||new St,entityEvents:new V,globalEvents:new V,internalEvents:new V,weakRef:m=>t.EXPERIMENTAL_weakRefs?new WeakRef(m):new Et(m),migrations:t.migrations},o=new bt({context:i,disableRebasing:t.disableRebasing});await o.updateSchema(t.schema,t.overrideSchemaConflict);let s=Object.assign(i,{getNow:()=>o.now}),c=await vt({context:s,version:t.schema.version,meta:o,migrations:t.migrations,indexedDB:t.indexedDb}),p=Object.assign(s,{documentDb:c});return new He({syncConfig:t.sync,migrations:t.migrations,files:t.files},p,{meta:o})};this.initializeWIPDatabases=async t=>{let e=Te(t.schema);console.info(`WIP schema in use. Opening database with hash ${e}`);let n=`@@wip_${t.namespace}_${e}`,{db:i}=await Hi({indexedDB:t.indexedDb,log:t.log,namespace:t.namespace,wipNamespace:n}),o={namespace:this._namespace,metaDb:i,schema:t.schema,log:t.log||(()=>{}),undoHistory:t.undoHistory||new St,entityEvents:new V,globalEvents:new V,internalEvents:new V,weakRef:S=>t.EXPERIMENTAL_weakRefs?new WeakRef(S):new Et(S),migrations:t.migrations},s=new bt({context:o,disableRebasing:t.disableRebasing}),c=Object.assign(o,{getNow:()=>s.now});await s.updateSchema(t.schema,t.overrideSchemaConflict);let p=await Yi({context:c,version:t.schema.version,meta:s,migrations:t.migrations,indexedDB:t.indexedDb,wipNamespace:n}),u=Object.assign(c,{documentDb:p});return new He({syncConfig:t.sync,migrations:t.migrations,files:t.files},u,{meta:s})};this.cleanupWIPDatabases=async t=>{let i=(await zi(t.indexedDb)).filter(o=>o.name?.startsWith("@@wip_")).map(o=>o.name).filter(o=>!o.startsWith(`@@wip_${t.namespace}_${Te(t.schema)}`));for(let o of i)await $i(o,t.indexedDb)};this.open=()=>this.initialize(this.init);this.close=async()=>{this._resolvedValue&&this._resolvedValue.close(),this._initializing&&(await this._readyPromise).close()};this.__dangerous__resetLocal=async()=>{await Yt(this.namespace)};this._readyPromise=new Promise((e,n)=>{this.resolveReady=e,this.rejectReady=n}),this._namespace=t.namespace}get namespace(){return this._namespace}get current(){return this._resolvedValue}get readyPromise(){return this._readyPromise}get schema(){return this.init.schema}};window.Verdant=Hr;
16
16
  //# sourceMappingURL=index.js.map