← Public packages
@kentcdodds/world-builder
Build a shared 3D voxel world with friends and your AI agents, live.
public/powersync/OPFSCoopSyncVFS-BgTiWPfa.js
2 lines · 7.7 KB · JavaScriptimport{F as e}from"./FacadeVFS-d1ZDvud7.js";import{r as s,f as t,j as a,k as r,S as n,l as i,m as l,n as c,o,p as h,q as d,t as u,u as p,v as g,w as F,e as f,B as w,D as H,d as y}from"./worker.js";const m=["","-journal","-wal"],b=new FinalizationRegistry(e=>e());class k{path;flags;accessHandle;persistentFile;constructor(e,s){this.path=e,this.flags=s}}class L{fileHandle;accessHandle=null;isLockBusy=!1;isFileLocked=!1;isRequestInProgress=!1;handleLockReleaser=null;handleRequestChannel;isHandleRequested=!1;constructor(e){this.fileHandle=e}}class R extends e{mapIdToFile=new Map;lastError=null;log=null;persistentFiles=new Map;boundAccessHandles=new Map;unboundAccessHandles=new Set;accessiblePaths=new Set;releaser=null;static async create(e,s){const t=new R(e,s);return await Promise.all([t.isReady(),t.#e(10)]),t}constructor(e,s){super(e,s)}async#e(e){const s=await navigator.storage.getDirectory();for await(const e of s.values())"directory"===e.kind&&e.name.startsWith(".ahp-")&&await navigator.locks.request(e.name,{ifAvailable:!0},async t=>{t?(this.log?.(`Deleting temporary directory ${e.name}`),await s.removeEntry(e.name,{recursive:!0})):this.log?.(`Temporary directory ${e.name} is in use`)});const t=`.ahp-${Math.random().toString(36).slice(2)}`;this.releaser=await new Promise(e=>{navigator.locks.request(t,()=>new Promise(s=>{e(s)}))}),b.register(this,this.releaser);const a=await s.getDirectoryHandle(t,{create:!0});for(let s=0;s<e;s++){const e=await a.getFileHandle(`${s}.tmp`,{create:!0}),t=await e.createSyncAccessHandle();this.unboundAccessHandles.add(t)}}jOpen(e,i,l,c){try{const o=new URL(e||Math.random().toString(36).slice(2),"file://").pathname;if(l&s){const e=this.persistentFiles.get(o);if(e?.isRequestInProgress)return t;if(!e){this.log?.(`creating persistent file for ${o}`);const e=!!(l&a);return this._module.retryOps.push((async()=>{try{let s=await navigator.storage.getDirectory();const t=o.split("/").filter(e=>e),a=t.pop();for(const a of t)s=await s.getDirectoryHandle(a,{create:e});for(const t of m){const r=await s.getFileHandle(a+t,{create:e});await this.#s(r)}const r=new k(o,l);r.persistentFile=this.persistentFiles.get(o),await this.#t(r)}catch(e){const s=new L(null);this.persistentFiles.set(o,s),console.error(e)}})()),t}if(!e.fileHandle)return this.persistentFiles.delete(o),r;if(!e.accessHandle)return this._module.retryOps.push((async()=>{const e=new k(o,l);e.persistentFile=this.persistentFiles.get(o),await this.#t(e)})()),t}if(!(this.accessiblePaths.has(o)||l&a))throw new Error(`File ${o} not found`);const h=new k(o,l);return this.mapIdToFile.set(i,h),this.persistentFiles.has(o)?h.persistentFile=this.persistentFiles.get(o):this.boundAccessHandles.has(o)?h.accessHandle=this.boundAccessHandles.get(o):this.unboundAccessHandles.size&&(h.accessHandle=this.unboundAccessHandles.values().next().value,h.accessHandle.truncate(0),this.unboundAccessHandles.delete(h.accessHandle),this.boundAccessHandles.set(o,h.accessHandle)),this.accessiblePaths.add(o),c.setInt32(0,l,!0),n}catch(e){return this.lastError=e,r}}jDelete(e,s){try{const s=new URL(e,"file://").pathname;if(this.persistentFiles.has(s)){this.persistentFiles.get(s).accessHandle.truncate(0)}else this.boundAccessHandles.get(s)?.truncate(0);return this.accessiblePaths.delete(s),n}catch(e){return this.lastError=e,i}}jAccess(e,s,t){try{const s=new URL(e,"file://").pathname;return t.setInt32(0,this.accessiblePaths.has(s)?1:0,!0),n}catch(e){return this.lastError=e,l}}jClose(e){try{const t=this.mapIdToFile.get(e);return this.mapIdToFile.delete(e),t?.flags&s?t.persistentFile?.handleLockReleaser&&this.#a(t):t?.flags&c&&(t.accessHandle.truncate(0),this.accessiblePaths.delete(t.path),this.persistentFiles.has(t.path)||(this.boundAccessHandles.delete(t.path),this.unboundAccessHandles.add(t.accessHandle))),n}catch(e){return this.lastError=e,o}}jRead(e,t,a){try{const r=this.mapIdToFile.get(e),i=(r.accessHandle||r.persistentFile.accessHandle).read(t.subarray(),{at:a});return r.flags&s&&!r.persistentFile.isFileLocked&&this.#a(r),i<t.byteLength?(t.fill(0,i),h):n}catch(e){return this.lastError=e,d}}jWrite(e,s,t){try{const a=this.mapIdToFile.get(e),r=a.accessHandle||a.persistentFile.accessHandle;if(r.write(s.subarray(),{at:t})!==s.byteLength)throw new Error("short write");return n}catch(e){return this.lastError=e,u}}jTruncate(e,s){try{const t=this.mapIdToFile.get(e);return(t.accessHandle||t.persistentFile.accessHandle).truncate(s),n}catch(e){return this.lastError=e,p}}jSync(e,s){try{const s=this.mapIdToFile.get(e);return(s.accessHandle||s.persistentFile.accessHandle).flush(),n}catch(e){return this.lastError=e,g}}jFileSize(e,s){try{const t=this.mapIdToFile.get(e),a=(t.accessHandle||t.persistentFile.accessHandle).getSize();return s.setBigInt64(0,BigInt(a),!0),n}catch(e){return this.lastError=e,F}}jLock(e,s){const a=this.mapIdToFile.get(e);return a.persistentFile.isRequestInProgress?(a.persistentFile.isLockBusy=!0,t):(a.persistentFile.isFileLocked=!0,a.persistentFile.handleLockReleaser?(a.persistentFile.isLockBusy=!1,n):(a.persistentFile.handleRequestChannel.onmessage=()=>{this.log?.(`received notification for ${a.path}`),a.persistentFile.isFileLocked?a.persistentFile.isHandleRequested=!0:this.#a(a),a.persistentFile.handleRequestChannel.onmessage=null},this.#t(a),this.log?.("returning SQLITE_BUSY"),a.persistentFile.isLockBusy=!0,t))}jUnlock(e,s){const t=this.mapIdToFile.get(e);return s===f&&(t.persistentFile.isLockBusy||(t.persistentFile.isHandleRequested&&(this.#a(t),t.persistentFile.isHandleRequested=!1),t.persistentFile.isFileLocked=!1)),n}jFileControl(e,s,t){try{const a=this.mapIdToFile.get(e);if(s===w){const e=A(t,4),s=A(t,8);if(this.log?.("xFileControl",a.path,"PRAGMA",e,s),"journal_mode"===e.toLowerCase())if(s&&!["off","memory","delete","wal"].includes(s.toLowerCase()))throw new Error('journal_mode must be "off", "memory", "delete", or "wal"')}}catch(e){return this.lastError=e,H}return y}jGetLastError(e){if(this.lastError){console.error(this.lastError);const s=e.subarray(0,e.byteLength-1),{written:t}=(new TextEncoder).encodeInto(this.lastError.message,s);e[t]=0}return n}async#s(e){const s=new L(e),t=await navigator.storage.getDirectory(),a=`/${(await t.resolve(e)).join("/")}`;s.handleRequestChannel=new BroadcastChannel(`ahp:${a}`),this.persistentFiles.set(a,s);return(await e.getFile()).size&&this.accessiblePaths.add(a),s}#t(e){return console.assert(!e.persistentFile.handleLockReleaser),e.persistentFile.isRequestInProgress?Promise.resolve():(e.persistentFile.isRequestInProgress=!0,this._module.retryOps.push((async()=>{e.persistentFile.handleLockReleaser=await this.#r(e.persistentFile);try{this.log?.(`creating access handles for ${e.path}`),await Promise.all(m.map(async s=>{const t=this.persistentFiles.get(e.path+s);t&&(t.accessHandle=await t.fileHandle.createSyncAccessHandle())}))}catch(s){throw this.log?.(`failed to create access handles for ${e.path}`,s),this.#a(e),s}finally{e.persistentFile.isRequestInProgress=!1}})()),this._module.retryOps.at(-1))}#a(e){m.forEach(s=>{const t=this.persistentFiles.get(e.path+s);t&&(t.accessHandle?.close(),t.accessHandle=null)}),this.log?.(`access handles closed for ${e.path}`),e.persistentFile.handleLockReleaser?.(),e.persistentFile.handleLockReleaser=null,this.log?.(`lock released for ${e.path}`)}#r(e){return new Promise(s=>{const t=e.handleRequestChannel.name,a=()=>{this.log?.(`notifying for ${t}`),e.handleRequestChannel.postMessage(null)},r=setInterval(a,1e3);setTimeout(a),this.log?.(`lock requested: ${t}`),navigator.locks.request(t,e=>(this.log?.(`lock acquired: ${t}`,e),clearInterval(r),new Promise(s)))})}}function A(e,s){const t=e.getUint32(s,!0);if(t){const s=new Uint8Array(e.buffer,t);return(new TextDecoder).decode(s.subarray(0,s.indexOf(0)))}return null}export{R as OPFSCoopSyncVFS};
//# sourceMappingURL=OPFSCoopSyncVFS-BgTiWPfa.js.map