/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const t=Symbol("Comlink.proxy"),e=Symbol("Comlink.endpoint"),n=Symbol("Comlink.releaseProxy"),s=Symbol("Comlink.finalizer"),r=Symbol("Comlink.thrown"),i=t=>"object"==typeof t&&null!==t||"function"==typeof t,o=new Map([["proxy",{canHandle:e=>i(e)&&e[t],serialize(t){const{port1:e,port2:n}=new MessageChannel;return a(t,e),[n,[n]]},deserialize:t=>(t.start(),l(t))}],["throw",{canHandle:t=>i(t)&&r in t,serialize({value:t}){let e;return e=t instanceof Error?{isError:!0,value:{message:t.message,name:t.name,stack:t.stack}}:{isError:!1,value:t},[e,[]]},deserialize(t){if(t.isError)throw Object.assign(new Error(t.value.message),t.value);throw t.value}}]]);function a(t,e=globalThis,n=["*"]){e.addEventListener("message",function i(o){if(!o||!o.data)return;if(!function(t,e){for(const n of t){if(e===n||"*"===n)return!0;if(n instanceof RegExp&&n.test(e))return!0}return!1}(n,o.origin))return void console.warn(`Invalid origin '${o.origin}' for comlink proxy`);const{id:l,type:u,path:h}=Object.assign({path:[]},o.data),d=(o.data.argumentList||[]).map(S);let p;try{const e=h.slice(0,-1).reduce((t,e)=>t[e],t),n=h.reduce((t,e)=>t[e],t);switch(u){case"GET":p=n;break;case"SET":e[h.slice(-1)[0]]=S(o.data.value),p=!0;break;case"APPLY":p=n.apply(e,d);break;case"CONSTRUCT":p=w(new n(...d));break;case"ENDPOINT":{const{port1:e,port2:n}=new MessageChannel;a(t,n),p=y(e,[e])}break;case"RELEASE":p=void 0;break;default:return}}catch(t){p={value:t,[r]:0}}Promise.resolve(p).catch(t=>({value:t,[r]:0})).then(n=>{const[r,o]=b(n);e.postMessage(Object.assign(Object.assign({},r),{id:l}),o),"RELEASE"===u&&(e.removeEventListener("message",i),c(e),s in t&&"function"==typeof t[s]&&t[s]())}).catch(t=>{const[n,s]=b({value:new TypeError("Unserializable return value"),[r]:0});e.postMessage(Object.assign(Object.assign({},n),{id:l}),s)})}),e.start&&e.start()}function c(t){(function(t){return"MessagePort"===t.constructor.name})(t)&&t.close()}function l(t,e){const n=new Map;return t.addEventListener("message",function(t){const{data:e}=t;if(!e||!e.id)return;const s=n.get(e.id);if(s)try{s(e)}finally{n.delete(e.id)}}),g(t,n,[],e)}function u(t){if(t)throw new Error("Proxy has been released and is not useable")}function h(t){return v(t,new Map,{type:"RELEASE"}).then(()=>{c(t)})}const d=new WeakMap,p="FinalizationRegistry"in globalThis&&new FinalizationRegistry(t=>{const e=(d.get(t)||0)-1;d.set(t,e),0===e&&h(t)});function g(t,s,r=[],i=function(){}){let o=!1;const a=new Proxy(i,{get(e,i){if(u(o),i===n)return()=>{!function(t){p&&p.unregister(t)}(a),h(t),s.clear(),o=!0};if("then"===i){if(0===r.length)return{then:()=>a};const e=v(t,s,{type:"GET",path:r.map(t=>t.toString())}).then(S);return e.then.bind(e)}return g(t,s,[...r,i])},set(e,n,i){u(o);const[a,c]=b(i);return v(t,s,{type:"SET",path:[...r,n].map(t=>t.toString()),value:a},c).then(S)},apply(n,i,a){u(o);const c=r[r.length-1];if(c===e)return v(t,s,{type:"ENDPOINT"}).then(S);if("bind"===c)return g(t,s,r.slice(0,-1));const[l,h]=m(a);return v(t,s,{type:"APPLY",path:r.map(t=>t.toString()),argumentList:l},h).then(S)},construct(e,n){u(o);const[i,a]=m(n);return v(t,s,{type:"CONSTRUCT",path:r.map(t=>t.toString()),argumentList:i},a).then(S)}});return function(t,e){const n=(d.get(e)||0)+1;d.set(e,n),p&&p.register(t,e,t)}(a,t),a}function m(t){const e=t.map(b);return[e.map(t=>t[0]),(n=e.map(t=>t[1]),Array.prototype.concat.apply([],n))];var n}const f=new WeakMap;function y(t,e){return f.set(t,e),t}function w(e){return Object.assign(e,{[t]:!0})}function b(t){for(const[e,n]of o)if(n.canHandle(t)){const[s,r]=n.serialize(t);return[{type:"HANDLER",name:e,value:s},r]}return[{type:"RAW",value:t},f.get(t)||[]]}function S(t){switch(t.type){case"HANDLER":return o.get(t.name).deserialize(t.value);case"RAW":return t.value}}function v(t,e,n,s){return new Promise(r=>{const i=new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-");e.set(i,r),t.start&&t.start(),t.postMessage(Object.assign({id:i},n),s)})}const _={trace:10,debug:20,info:30,warn:40,error:50};function C(t){const{prefix:e="PowerSync",minLevel:n=_.info}=t??{};return{prefix:e,minLevel:n,log({level:t,message:n,error:s}){if(t=_.error?r=console.error:t>=_.warn?r=console.warn:t>=_.info&&(r=console.info);const i=`[${e}]: ${n}`;s?r(i,s):r(i)}}}var E,k,A,L,q,T,x,P;!function(t){t.TEXT="TEXT",t.INTEGER="INTEGER",t.REAL="REAL"}(E||(E={})),E.TEXT,E.INTEGER,E.REAL,function(t){t[t.QUEUED_UPLOAD=0]="QUEUED_UPLOAD",t[t.QUEUED_DOWNLOAD=1]="QUEUED_DOWNLOAD",t[t.QUEUED_DELETE=2]="QUEUED_DELETE",t[t.SYNCED=3]="SYNCED",t[t.ARCHIVED=4]="ARCHIVED"}(k||(k={})),function(t){t.UTF8="utf8",t.Base64="base64"}(A||(A={})),function(t){t.PUT="PUT",t.PATCH="PATCH",t.DELETE="DELETE"}(L||(L={})),function(t){t.HTTP="http",t.WEB_SOCKET="web-socket"}(q||(q={})),function(t){t.Buffered="buffered",t.Sequential="sequential"}(T||(T={}));class I{listeners=new Set;constructor(){}dispose(){this.listeners.clear()}registerListener(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}iterateListeners(t){for(const e of this.listeners)t(e)}async iterateAsyncListeners(t){for(let e of Array.from(this.listeners.values()))await t(e)}}function O(t,e){const n={};return t.forEach((t,s)=>n[t]=e[s]),n}function R(t){return{...t,array:[],[Symbol.iterator]:()=>({next:()=>({done:!0,value:void 0})})}}class M{async getAll(t,e){const n=await this.execute(t,e);return Array.from(n)}async getOptional(t,e){const{array:n}=await this.execute(t,e);return n.length>0?n[0]:null}async get(t,e){const n=await this.getOptional(t,e);if(null==n)throw new Error("Result set is empty");return n}async execute(t,e){return function(t){const{insertId:e,rowsAffected:n,columnNames:s,rawRows:r}=t;let i;function o(){return i||(i=r.map(t=>O(s,t)))}function a(t){return i?i[t]:O(s,r[t])}return{insertId:e,rowsAffected:n,get array(){return o()},rows:{length:r.length,get _array(){return o()},item:a},[Symbol.iterator](){let t=0;return{next:function(){if(t>=r.length)return{done:!0,value:void 0};const e=a(t);return t++,{done:!1,value:e}}}}}}(await this.executeRaw(t,e))}async executeBatch(t,e=[]){let n,s=0;for(const r of e){const e=await this.execute(t,r);n=e.insertId,s+=e.rowsAffected??0}return R({rowsAffected:s,insertId:n})}}class F extends I{readTransaction(t,e){return this.readLock(e=>U.runWith(e,t),e)}writeTransaction(t,e){return this.writeLock(e=>U.runWith(e,t),e)}getAll(t,e){return this.readLock(n=>n.getAll(t,e))}getOptional(t,e){return this.readLock(n=>n.getOptional(t,e))}get(t,e){return this.readLock(n=>n.get(t,e))}execute(t,e){return this.writeLock(n=>n.execute(t,e))}executeRaw(t,e){return this.writeLock(n=>n.executeRaw(t,e))}executeBatch(t,e){return this.writeTransaction(n=>n.executeBatch(t,e))}}class U extends M{inner;finalized=!1;constructor(t){super(),this.inner=t}async commit(){this.finalized||(this.finalized=!0,await this.inner.execute("COMMIT"))}async rollback(){this.finalized||(this.finalized=!0,await this.inner.execute("ROLLBACK"))}execute(t,e){return this.inner.execute(t,e)}executeRaw(t,e){return this.inner.executeRaw(t,e)}executeBatch(t,e){return this.inner.executeBatch(t,e)}static async runWith(t,e){let n=new U(t);try{await t.execute("BEGIN IMMEDIATE");const s=await e(n);return await n.commit(),s}catch(t){try{await n.rollback()}catch(t){}throw t}}}!function(t){t.INSERT="INSERT",t.UPDATE="UPDATE",t.DELETE="DELETE"}(x||(x={})),function(t){t.ON_DATA="onData",t.ON_ERROR="onError",t.ON_STATE_CHANGE="onStateChange",t.SETTINGS_WILL_UPDATE="settingsWillUpdate",t.CLOSED="closed"}(P||(P={}));class D{#t;#e=0;#n=new Set;#s;#r=new Set;constructor(t){this.#t=t;const e=t.inner;this.#s=new BroadcastChannel(`${e.options.filename}-table-updates`),this.#s.onmessage=({data:t})=>{this.#i(t)}}#i(t){for(const e of this.#r)e.postMessage(t)}get#o(){return this.#t.inner}get#a(){return this.#t.logger}async connect(t){let e=!0;const n=this.#e++;this.#n.add(n);let s,r=new Map;function i(){if(!e)throw new Error("Client has already been closed")}function o(t){i();const e=r.get(t);if(!e)throw new Error("Attempted to use a connection lease that has already been returned.");return e}const a=async()=>{if(e){e=!1,s&&this.#r.delete(s);for(const{lease:t}of r.values())this.#a.log({level:_.debug,message:"Closing connection lease that hasn't been returned."}),await t.returnLease();this.#n.delete(n),0==this.#n.size?await this.forceClose():this.#a.log({level:_.debug,message:"Keeping underlying connection active since its used by other clients."})}};return t&&navigator.locks.request(t,{},()=>{a()}),{close:a,debugIsAutoCommit:async()=>this.#o.unsafeUseInner().isAutoCommit(),requestAccess:async(t,n)=>{i();const s=await this.#o.acquireConnection(null!=n?AbortSignal.timeout(n):void 0);if(!e)return await s.returnLease(),i();const o=crypto.randomUUID();return r.set(o,{lease:s,write:t}),o},completeAccess:async t=>{const e=o(t);r.delete(t);try{if(e.write){const{rawRows:t}=await e.lease.use(t=>t.execute("SELECT powersync_update_hooks('get')"));if(t.length){const e=JSON.parse(t[0][0]);e.length&&(this.#s.postMessage(e),this.#i(e))}}}finally{await e.lease.returnLease()}},execute:async(t,e,n)=>{const{lease:s}=o(t);return await s.use(t=>t.execute(e,n))},executeBatch:async(t,e,n)=>{const{lease:s}=o(t);return await s.use(t=>t.executeBatch(e,n))},setUpdateListener:async t=>{i(),s&&this.#r.delete(s),s=t,t&&this.#r.add(t)}}}async forceClose(){this.#a.log({level:_.debug,message:`Closing connection to ${JSON.stringify(this.#o.options)}.`});const t=this.#o;this.#t.onClose(),this.#s.close(),await t.close()}}const N=()=>{if("locks"in navigator&&navigator.locks)return navigator.locks;throw new Error("Navigator locks are not available in an insecure context. Use a secure context such as HTTPS or http://localhost.")},$=0,B=1,W=5,j=10,z=12,H=14,V=3338,J=3594,G=4106,K=2570,Q=1802,Y=1034,X=3850,Z=266,tt=522,et=1546,nt=2058,st=778,rt=4,it=8,ot=64,at=256,ct=512,lt=2048,ut=16384,ht=524288,dt=0,pt=1,gt=2,mt=4,ft=2048,yt=16384,wt=11,bt=14,St=21,vt=31,_t=32,Ct=33;void 0===BigInt.prototype.toJSON&&(BigInt.prototype.toJSON=function(){return this.toString()});const Et=0x7fffffffffffffffn,kt=-0x8000000000000000n,At=Object.getPrototypeOf(async function(){}).constructor;class Lt extends Error{constructor(t,e){super(t),this.code=e}}const qt=!0;function Tt(t){const e=[],n=t.match(/([ns@]*):([nsv@])/);switch(n[2]){case"n":e.push("number");break;case"s":e.push("string");break;case"v":e.push(null)}const s=[];for(let t of n[1])switch(t){case"n":s.push("number");break;case"s":s.push("string")}return e.push(s),e}var xt,Pt;async function It(t){if(t){const{default:t}=await import("./mc-wa-sqlite-async-DJG_ANKO.js");return t()}{const{default:t}=await import("./wa-sqlite-async-BxkwNY-2.js");return t()}}async function Ot(t){if(t){const{default:t}=await import("./mc-wa-sqlite-PubB6u8c.js");return t()}{const{default:t}=await import("./wa-sqlite-D1_4mGs8.js");return t()}}!function(t){t.IDBBatchAtomicVFS="IDBBatchAtomicVFS",t.OPFSCoopSyncVFS="OPFSCoopSyncVFS",t.AccessHandlePoolVFS="AccessHandlePoolVFS",t.OPFSWriteAheadVFS="OPFSWriteAheadVFS",t.InMemoryVfs="InMemoryVFS"}(xt||(xt={})),function(t){t.MEMORY="memory",t.FILESYSTEM="file"}(Pt||(Pt={}));class Rt{#c;#l=new Map;constructor(t){this.#c=t}lookup(t){const e=this.#l.get(t);return null!=e?(this.#l.delete(t),this.#l.set(t,e),e):null}addStatement(t,e){if(this.#l.set(t,e),this.#l.size>this.#c)for(const[t,e]of this.#l.entries())return this.#l.delete(t),e;return null}drain(){const t=[...this.#l.values()];return this.#l.clear(),t}}class Mt{options;_sqliteAPI=null;sqlite3_stmt_isexplain;db=0;statementCache;constructor(t){this.options=t,this.statementCache=t.preparedStatementsCache>0?new Rt(t.preparedStatementsCache):null}get isOpen(){return 0!=this.db}async init(){const{module:t,vfs:e}=await async function({vfs:t,filename:e,encryptionKey:n}){let s,r=Ot;switch(t){case xt.IDBBatchAtomicVFS:{r=It;const{IDBBatchAtomicVFS:t}=await import("./IDBBatchAtomicVFS-DbkDb777.js");s=n=>t.create(e,n,{lockPolicy:"exclusive"});break}case xt.AccessHandlePoolVFS:{const{AccessHandlePoolVFS:t}=await import("./AccessHandlePoolVFS-BPUHfZME.js");s=n=>t.create(e,n);break}case xt.OPFSCoopSyncVFS:{const{OPFSCoopSyncVFS:t}=await import("./OPFSCoopSyncVFS-BgTiWPfa.js");s=n=>t.create(e,n);break}case xt.OPFSWriteAheadVFS:{const{OPFSWriteAheadVFS:t}=await import("./OPFSWriteAheadVFS-BW9pqSNn.js");s=n=>t.create(e,n,{});break}case xt.InMemoryVfs:{const{MemoryVFS:t}=await import("./MemoryVFS-DVJL5F8j.js");s=n=>t.create(e,n);break}}const i=await r(n);return{module:i,vfs:await s(i)}}(this.options);await this.initWithModule(t,e)}async initWithModule(t,e){const n=this._sqliteAPI=await this.openSQLiteAPI(t,e);if(this.db=await n.open_v2(this.options.filename,this.options.readonly?1:6),await this.executeRaw(`PRAGMA temp_store = ${this.options.temporaryStorage};`),this.options.encryptionKey){const t=this.options.encryptionKey.replaceAll("'","''");await this.executeRaw(`PRAGMA key = '${t}';`)}await this.executeRaw(`PRAGMA cache_size = -${this.options.cacheSizeKb};`),await this.executeRaw("SELECT powersync_update_hooks('install');")}async openSQLiteAPI(t,e){e.mxPathname=128,this.sqlite3_stmt_isexplain=t.cwrap("sqlite3_stmt_isexplain","int",["int"]);const n=function(t){const e={};t.retryOps=[],t.pendingOps=[];const n=t._getSqliteFree(),s=t._malloc(8),r=[s,s+4],i=new TextEncoder;function o(e){if("string"!=typeof e)return 0;const n=i.encode(e),s=t._sqlite3_malloc(n.byteLength+1);return t.HEAPU8.set(n,s),t.HEAPU8[s+n.byteLength]=0,s}function a(t,e){return BigInt(e)<<32n|0xffffffffn&BigInt(t)}const c=function(){const t=BigInt(Number.MAX_SAFE_INTEGER)>>32n,e=BigInt(Number.MIN_SAFE_INTEGER)>>32n;return function(n,s){return s>t||s2147483647||r<-2147483648)return 25;const i=n(t,s,r);return p(e,i,h.get(t))}}(),e.bind_int64=function(){const e="sqlite3_bind_int64",n=t.cwrap(e,...Tt("nnnn:n"));return function(t,s,r){if(d(t),r>Et||r>32n,o=n(t,s,Number(0xffffffffn&r),Number(i));return p(e,o,h.get(t))}}(),e.bind_null=function(){const e="sqlite3_bind_null",n=t.cwrap(e,...Tt("nn:n"));return function(t,s){d(t);const r=n(t,s);return p(e,r,h.get(t))}}(),e.bind_parameter_name=function(){const e=t.cwrap("sqlite3_bind_parameter_name",...Tt("n:s"));return function(t,n){return d(t),e(t,n)}}(),e.bind_text=function(){const e="sqlite3_bind_text",s=t.cwrap(e,...Tt("nnnnn:n"));return function(t,r,i){d(t);const a=o(i),c=s(t,r,a,-1,n);return p(e,c,h.get(t))}}(),e.changes=function(){const e=t.cwrap("sqlite3_changes",...Tt("n:n"));return function(t){return u(t),e(t)}}(),e.clear_bindings=function(){const e="sqlite3_clear_bindings",n=t.cwrap(e,...Tt("n:n"));return function(t){d(t);const s=n(t);return p(e,s,h.get(t))}}(),e.last_insert_id=function(){const e=t.cwrap("sqlite3_last_insert_rowid",...Tt("n:n"));return function(t){return u(t),e(t)}}(),e.close=function(){const e="sqlite3_close",n=t.cwrap(e,...Tt("n:n"),{async:qt});return async function(t){u(t);const s=await n(t);return l.delete(t),p(e,s,t)}}(),e.column=function(n,s){d(n);const r=e.column_type(n,s);switch(r){case 4:return e.column_blob(n,s);case 2:return e.column_double(n,s);case 1:const i=e.column_int(n,s),o=t.getTempRet0();return c(i,o);case 5:return null;case 3:return e.column_text(n,s);default:throw new Lt("unknown type",r)}},e.column_blob=function(){const n=t.cwrap("sqlite3_column_blob",...Tt("nn:n"));return function(s,r){d(s);const i=e.column_bytes(s,r),o=n(s,r);return t.HEAPU8.subarray(o,o+i)}}(),e.column_bytes=function(){const e=t.cwrap("sqlite3_column_bytes",...Tt("nn:n"));return function(t,n){return d(t),e(t,n)}}(),e.column_count=function(){const e=t.cwrap("sqlite3_column_count",...Tt("n:n"));return function(t){return d(t),e(t)}}(),e.column_double=function(){const e=t.cwrap("sqlite3_column_double",...Tt("nn:n"));return function(t,n){return d(t),e(t,n)}}(),e.column_int=function(){const e=t.cwrap("sqlite3_column_int64",...Tt("nn:n"));return function(t,n){return d(t),e(t,n)}}(),e.column_int64=function(){const e=t.cwrap("sqlite3_column_int64",...Tt("nn:n"));return function(n,s){return d(n),a(e(n,s),t.getTempRet0())}}(),e.column_name=function(){const e=t.cwrap("sqlite3_column_name",...Tt("nn:s"));return function(t,n){return d(t),e(t,n)}}(),e.column_names=function(t){const n=[],s=e.column_count(t);for(let r=0;re(n,t.HEAP32.subarray(r/4,r/4+s)):(n,s,r)=>e(n,t.HEAP32.subarray(r/4,r/4+s))}return u(e),p("sqlite3_create_function",t.create_function(e,n,s,r,i,o&&l(o),a&&l(a),c),e)},e.data_count=function(){const e=t.cwrap("sqlite3_data_count",...Tt("n:n"));return function(t){return d(t),e(t)}}(),e.exec=async function(t,n,s){for await(const r of e.statements(t,n)){let t;for(;100===await e.step(r);)if(s){t=t??e.column_names(r);const n=e.row(r);await s(n,t)}}return 0},e.finalize=function(){const e=t.cwrap("sqlite3_finalize",...Tt("n:n"),{async:qt});return async function(t){const n=await e(t);return h.delete(t),n}}(),e.get_autocommit=function(){const e=t.cwrap("sqlite3_get_autocommit",...Tt("n:n"));return function(t){return e(t)}}(),e.libversion=function(){const e=t.cwrap("sqlite3_libversion",...Tt(":s"));return function(){return e()}}(),e.libversion_number=function(){const e=t.cwrap("sqlite3_libversion_number",...Tt(":n"));return function(){return e()}}(),e.limit=function(){const e=t.cwrap("sqlite3_limit",...Tt("nnn:n"));return function(t,n,s){return e(t,n,s)}}(),e.open_v2=function(){const n="sqlite3_open_v2",s=t.cwrap(n,...Tt("snnn:n"),{async:qt});return async function(i,a,c){a=a||6,c=o(c);try{const o=await g(()=>s(i,r[0],a,c)),u=t.getValue(r[0],"*");if(0!==o){const s=u?t.ccall("sqlite3_errmsg","string",["number"],[u]):n,r=new Lt(s,o);if(u){l.add(u);try{await e.close(u)}catch{}finally{l.delete(u)}}throw r}return l.add(u),t.ccall("RegisterExtensionFunctions","void",["number"],[u]),u}finally{t._sqlite3_free(c)}}}(),e.progress_handler=function(e,n,s,r){u(e),t.progress_handler(e,n,s,r)},e.reset=function(){const e="sqlite3_reset",n=t.cwrap(e,...Tt("n:n"),{async:qt});return async function(t){d(t);const s=await n(t);return p(e,s,h.get(t))}}(),e.result=function(t,n){switch(typeof n){case"number":n===(0|n)?e.result_int(t,n):e.result_double(t,n);break;case"string":e.result_text(t,n);break;default:if(n instanceof Uint8Array||Array.isArray(n))e.result_blob(t,n);else if(null===n)e.result_null(t);else{if("bigint"==typeof n)return e.result_int64(t,n);console.warn("unknown result converted to null",n),e.result_null(t)}}},e.result_blob=function(){const e=t.cwrap("sqlite3_result_blob",...Tt("nnnn:n"));return function(s,r){const i=r.byteLength??r.length,o=t._sqlite3_malloc(i);t.HEAPU8.subarray(o).set(r),e(s,o,i,n)}}(),e.result_double=function(){const e=t.cwrap("sqlite3_result_double",...Tt("nn:n"));return function(t,n){e(t,n)}}(),e.result_int=function(){const e=t.cwrap("sqlite3_result_int",...Tt("nn:n"));return function(t,n){e(t,n)}}(),e.result_int64=function(){const e=t.cwrap("sqlite3_result_int64",...Tt("nnn:n"));return function(t,n){if(n>Et||n>32n;e(t,Number(0xffffffffn&n),Number(s))}}(),e.result_null=function(){const e=t.cwrap("sqlite3_result_null",...Tt("n:n"));return function(t){e(t)}}(),e.result_text=function(){const e=t.cwrap("sqlite3_result_text",...Tt("nnnn:n"));return function(t,s){const r=o(s);e(t,r,-1,n)}}(),e.row=function(n){const s=[],r=e.data_count(n);for(let i=0;ii(...r(t,e,n,s,o,a)):(t,e,n,s,o,a)=>i(...r(t,e,n,s,o,a)),s),e)},e.sql=function(){const e=t.cwrap("sqlite3_sql",...Tt("n:s"));return function(t){return d(t),e(t)}}(),e.statements=function(n,s,r={}){const o=t.cwrap("sqlite3_prepare_v3","number",["number","number","number","number","number","number"],{async:!0});return async function*(){const a=[];try{const c=i.encode(s),l=c.byteLength-c.byteLength%4+12,u=t._sqlite3_malloc(l),d=u+c.byteLength+1;a.push(()=>t._sqlite3_free(u)),t.HEAPU8.set(c,u),t.HEAPU8[d-1]=0;const m=u+l-8,f=u+l-4;let y;function w(){y&&!r.unscoped&&e.finalize(y),y=0}a.push(w),t.setValue(f,u,"*");do{w();const b=t.getValue(f,"*"),S=await g(()=>o(n,b,d-f,r.flags||0,m,f));0!==S&&p("sqlite3_prepare_v3",S,n),y=t.getValue(m,"*"),y&&(h.set(y,n),yield y)}while(y)}finally{for(;a.length;)a.pop()()}}()},e.step=function(){const e="sqlite3_step",n=t.cwrap(e,...Tt("n:n"),{async:qt});return async function(t){d(t);const s=await g(()=>n(t));return p(e,s,h.get(t),[100,101])}}(),e.commit_hook=function(e,n){u(e),t.commit_hook(e,n)},e.update_hook=function(e,n){function s(e,n,s,r,i){return[e,t.UTF8ToString(n),t.UTF8ToString(s),a(r,i)]}var r;u(e),t.update_hook(e,(r=n)instanceof At?async(t,e,n,i,o)=>r(...s(t,e,n,i,o)):(t,e,n,i,o)=>r(...s(t,e,n,i,o)))},e.value=function(n){const s=e.value_type(n);switch(s){case 4:return e.value_blob(n);case 2:return e.value_double(n);case 1:const r=e.value_int(n),i=t.getTempRet0();return c(r,i);case 5:return null;case 3:return e.value_text(n);default:throw new Lt("unknown type",s)}},e.value_blob=function(){const n=t.cwrap("sqlite3_value_blob",...Tt("n:n"));return function(s){const r=e.value_bytes(s),i=n(s);return t.HEAPU8.subarray(i,i+r)}}(),e.value_bytes=function(){const e=t.cwrap("sqlite3_value_bytes",...Tt("n:n"));return function(t){return e(t)}}(),e.value_double=function(){const e=t.cwrap("sqlite3_value_double",...Tt("n:n"));return function(t){return e(t)}}(),e.value_int=function(){const e=t.cwrap("sqlite3_value_int64",...Tt("n:n"));return function(t){return e(t)}}(),e.value_int64=function(){const e=t.cwrap("sqlite3_value_int64",...Tt("n:n"));return function(n){return a(e(n),t.getTempRet0())}}(),e.value_text=function(){const e=t.cwrap("sqlite3_value_text",...Tt("n:s"));return function(t){return e(t)}}(),e.value_type=function(){const e=t.cwrap("sqlite3_value_type",...Tt("n:n"));return function(t){return e(t)}}(),e.vfs_register=function(e,n){return p("sqlite3_vfs_register",t.vfs_register(e,n))},e}(t);if(n.vfs_register(e,!0),t.ccall("powersync_init_static","int",[]),this.options.encryptionKey){if(0!==t.ccall("sqlite3mc_vfs_create","int",["string","int"],[this.options.filename,1]))throw new Error("Failed to create multiple cipher vfs, Database encryption will not work")}return n}requireSqlite(){if(!this._sqliteAPI)throw new Error("Initialization has not completed");return this._sqliteAPI}isAutoCommit(){return 0!=this.requireSqlite().get_autocommit(this.db)}async execute(t,e){const n=await this.executeSingleStatementRaw(t,e);return this.wrapQueryResults(this.requireSqlite(),n)}async executeBatch(t,e){const n=[],s=this.requireSqlite();for await(const r of s.statements(this.db,t)){let t;for(const i of e){const e=await this.stepThroughStatement(s,r,i,t,!1);n.push(this.wrapQueryResults(s,e))}break}return n}wrapQueryResults(t,{rawRows:e,columnNames:n}){return{rowsAffected:t.changes(this.db),insertId:t.last_insert_id(this.db),autocommit:0!=t.get_autocommit(this.db),rawRows:e,columnNames:n}}async executeSingleStatementRaw(t,e){const n=await this.executeRaw(t,e);return n.length?n[0]:{columnNames:[],rawRows:[]}}async executeRaw(t,e){const n=[],s=this.requireSqlite();for await(const r of this.cachedStatements(s,t)){let t;const i=await this.stepThroughStatement(s,r,e??[],t);if(t=i.columnNames,t.length&&n.push(i),e)break}return n}async stepThroughStatement(t,e,n,s,r=!0){n.forEach((t,e,n)=>{"boolean"==typeof t&&(n[e]=t?1:0)}),t.reset(e),n&&t.bind_collection(e,n);const i=[];for(;100===await t.step(e);)if(r){const n=t.row(e);i.push(n)}return s??=t.column_names(e),{columnNames:s,rawRows:i}}async close(){if(this.isOpen){const t=this.requireSqlite();if(this.statementCache)for(const e of this.statementCache.drain())await t.finalize(e);await t.close(this.db),this.db=0}}async*cachedStatements(t,e){{const t=this.statementCache?.lookup(e);if(null!=t)return void(yield t)}const n=t.statements(this.db,e,{unscoped:!0}),s=[];try{for await(const t of n)s.push(t),yield t}finally{if(1===s.length&&this.statementCache){const n=s[0];if(0==this.sqlite3_stmt_isexplain(n)){const s=this.statementCache.addStatement(e,n);return void(null!=s&&await t.finalize(s))}}for(const e of s)await t.finalize(e)}}}var Ft,Ut;async function Dt(t,e,n){const{rawRows:s}=await t.executeRaw("SELECT CAST(powersync_control(?, ?) AS TEXT)",[e,n]);return s[0][0]}function Nt(t,e=null){return Dt(t,"target_checkpoint_request_id",e)}!function(t){t.DATA="ps_data",t.CRUD="ps_crud",t.BUCKETS="ps_buckets",t.OPLOG="ps_oplog",t.UNTYPED="ps_untyped"}(Ft||(Ft={})),function(t){t.PROCESS_TEXT_LINE="line_text",t.PROCESS_BSON_LINE="line_binary",t.STOP="stop",t.START="start",t.NOTIFY_TOKEN_REFRESHED="refreshed_token",t.NOTIFY_CRUD_UPLOAD_COMPLETED="completed_upload",t.UPDATE_SUBSCRIPTIONS="update_subscriptions",t.CONNECTION_STATE="connection"}(Ut||(Ut={}));const $t=2147483647,Bt="9223372036854775807";class Wt{internal;totalOperations;downloadedOperations;downloadedFraction;constructor(t){this.internal=t;const e=this.untilPriority($t);this.totalOperations=e.totalOperations,this.downloadedOperations=e.downloadedOperations,this.downloadedFraction=e.downloadedFraction}untilPriority(t){let e=0,n=0;for(const s of Object.values(this.internal.buckets))s.priority<=t&&(n+=s.since_last,e+=s.target_count-s.at_last);return{totalOperations:e,downloadedOperations:n,downloadedFraction:0==e?0:n/e}}}class jt{core;jsState;constructor(t,e){this.core=t,this.jsState=e}get connected(){return this.core?.connected??!1}get connecting(){return this.core?.connecting??!1}get downloading(){return null!=this.core?.downloading}get uploading(){return this.jsState.uploading??!1}get downloadError(){return this.jsState.downloadError}get uploadError(){return this.jsState.uploadError}get dataFlowStatus(){return{downloading:this.downloading,uploading:this.uploading,downloadError:this.downloadError,uploadError:this.uploadError}}get lastSyncedAt(){return this.statusForPriority($t)?.lastSyncedAt}get hasSynced(){return this.statusForPriority($t)?.hasSynced}get syncStreams(){return this.core?.streams.map(t=>new Ht(this,t))}forStream(t){const e=JSON.stringify(t.parameters),n=this.core?.streams?.find(n=>n.name==t.name&&e==JSON.stringify(n.parameters));return n&&new Ht(this,n)}get priorityStatusEntries(){return this.core?.priority_status.map(zt)}get downloadProgress(){const t=this.core?.downloading;return null==t?null:new Wt(t)}statusForPriority(t){const e=this.core?.priority_status;if(null!=e){for(const n of e)if(n.priority>=t)return zt(n);return{priority:t,lastSyncedAt:void 0,hasSynced:!1}}}isEqual(t){const e=(t,e)=>e instanceof Error?this.serializeError(e):e,n={core:this.core,jsState:this.jsState},s=t,r={core:s.core,jsState:s.jsState};return JSON.stringify(n,e)==JSON.stringify(r,e)}getMessage(){return`SyncStatus`}toJSON(){return{core:this.core,dataFlow:{uploading:this.uploading,uploadError:this.serializeError(this.uploadError),downloadError:this.serializeError(this.downloadError)}}}serializeError(t){if(void 0===t)return;const e={name:t.name,message:t.message,stack:t.stack};return void 0!==t.cause&&(e.cause=t.cause instanceof Error?this.serializeError(t.cause):t.cause),e}}function zt(t){return{priority:t.priority,hasSynced:t.has_synced??void 0,lastSyncedAt:(e=t.last_synced_at,null==e?void 0:new Date(e/1e3))};var e}class Ht{status;core;subscription;constructor(t,e){this.status=t,this.core=e,this.subscription={name:e.name,parameters:e.parameters,active:e.active,isDefault:e.is_default,hasExplicitSubscription:e.has_explicit_subscription,expiresAt:null!=e.expires_at?new Date(1e3*e.expires_at):null,hasSynced:null!=e.last_synced_at,lastSyncedAt:null!=e.last_synced_at?new Date(1e3*e.last_synced_at):null}}get progress(){if(null==this.status.core?.downloading)return null;const{total:t,downloaded:e}=this.core.progress;return{totalOperations:t,downloadedOperations:e,downloadedFraction:0==t?0:e/t}}get priority(){return this.core.priority}}class Vt extends I{options;connectingPromise;syncStreamInitPromise;disconnectingPromise;pendingConnectionOptions;currentOptions;syncStreamImplementation;syncDisposer;locallyActiveSubscriptions=new Map;constructor(t){super(),this.options=t,this.connectingPromise=null,this.syncStreamInitPromise=null,this.disconnectingPromise=null,this.pendingConnectionOptions=null,this.syncStreamImplementation=null,this.currentOptions=null,this.syncDisposer=null}get connector(){return this.pendingConnectionOptions?.connector??null}get connectionOptions(){return this.currentOptions??this.pendingConnectionOptions?.options??null}get logger(){return this.options.logger}async close(){await(this.syncStreamImplementation?.dispose()),await(this.syncDisposer?.())}async connect(t,e,n){const s=!!this.pendingConnectionOptions,r=function(t,e){return{appMetadata:t.appMetadata??{},connectionMethod:t.connectionMethod??e,fetchStrategy:t.fetchStrategy??T.Buffered,params:t.params??{},includeDefaultStreams:t.includeDefaultStreams??!0,retryDelayMs:t.retryDelayMs??5e3,crudUploadThrottleMs:t.crudUploadThrottleMs??1e3,checkpointMode:t.checkpointMode??"legacy"}}(e,this.options.defaultConnectionMethod);this.pendingConnectionOptions={connector:t,options:r,schema:n},t.postCheckpointRequest&&"legacy"==r.checkpointMode&&this.logger.log({level:_.warn,message:"The backend connector implements postCheckpointRequest, but connect() was called without checkpoint requests enabled."}),s&&!this.syncStreamImplementation||await this.disconnectInternal();const i=async()=>this.pendingConnectionOptions?(this.connectingPromise=this.connectInternal().catch(()=>{}).finally(i),this.connectingPromise):void(this.connectingPromise=null);return this.connectingPromise??=this.connectInternal().catch(()=>{}).finally(i),this.connectingPromise}async connectInternal(){let t=null;await this.disconnectInternal(),this.syncStreamInitPromise=new Promise(async(e,n)=>{try{if(!this.pendingConnectionOptions)return this.logger.log({level:_.debug,message:"No pending connection options found, not creating sync stream implementation"}),void e();if(this.disconnectingPromise)return void e();const{connector:n,options:s,schema:r}=this.pendingConnectionOptions;t=s,this.currentOptions=s,this.pendingConnectionOptions=null;const i=this.subscriptionIdentity,{sync:o,onDispose:a}=await this.options.createSyncImplementation(n,{subscriptions:this.activeStreams,serializedSchema:r});this.iterateListeners(t=>t.syncStreamCreated?.(o)),this.syncStreamImplementation=o,this.syncDisposer=a,await this.syncStreamImplementation.waitForReady(),this.subscriptionIdentity!==i&&this.syncStreamImplementation.updateSubscriptions(this.activeStreams),e()}catch(t){n(t)}}),await this.syncStreamInitPromise,this.syncStreamInitPromise=null,t&&(await this.disconnectingPromise,this.logger.log({level:_.debug,message:"Attempting to connect to PowerSync instance"}),await(this.syncStreamImplementation?.connect(t)))}async disconnect(){this.pendingConnectionOptions=null,this.currentOptions=null,await this.disconnectInternal()}async disconnectInternal(){if(this.disconnectingPromise)return this.disconnectingPromise;this.disconnectingPromise=this.performDisconnect(),await this.disconnectingPromise,this.disconnectingPromise=null}async performDisconnect(){await this.syncStreamInitPromise;const t=this.syncStreamImplementation;this.syncStreamImplementation=null;const e=this.syncDisposer;this.syncDisposer=null,await(t?.disconnect()),await(t?.dispose()),await(e?.())}stream(t,e,n){const s={name:e,parameters:n},r=e=>t.firstStatusMatching(t=>t.forStream(s)?.subscription.hasSynced,e);return{...s,subscribe:async s=>{await t.rustSubscriptionsCommand({subscribe:{stream:{name:e,params:n},ttl:s?.ttl,priority:s?.priority}}),this.syncStreamImplementation||await t.resolveOfflineSyncStatus();const i=`${e}|${JSON.stringify(n)}`;let o=this.locallyActiveSubscriptions.get(i);if(null==o){const t=()=>{this.locallyActiveSubscriptions.delete(i),this.subscriptionsMayHaveChanged()};o=new Jt(e,n,this.logger,r,t),this.locallyActiveSubscriptions.set(i,o),this.subscriptionsMayHaveChanged()}return new Gt(o)},unsubscribeAll:async()=>{await t.rustSubscriptionsCommand({unsubscribe:{name:e,params:n}}),this.subscriptionsMayHaveChanged()}}}get activeStreams(){return[...this.locallyActiveSubscriptions.values()].map(t=>({name:t.name,params:t.parameters}))}get subscriptionIdentity(){return[...this.locallyActiveSubscriptions.keys()].join("\n")}subscriptionsMayHaveChanged(){this.syncStreamImplementation?.updateSubscriptions(this.activeStreams)}}class Jt{name;parameters;logger;waitForFirstSync;clearSubscription;refcount=0;constructor(t,e,n,s,r){this.name=t,this.parameters=e,this.logger=n,this.waitForFirstSync=s,this.clearSubscription=r}decrementRefCount(){this.refcount--,0==this.refcount&&this.clearSubscription()}}class Gt{subscription;active=!0;constructor(t){this.subscription=t,t.refcount++,Kt?.register(this,t,this)}get name(){return this.subscription.name}get parameters(){return this.subscription.parameters}waitForFirstSync(t){return this.subscription.waitForFirstSync(t)}unsubscribe(){this.active&&(this.active=!1,Kt?.unregister(this),this.subscription.decrementRefCount())}}const Kt="FinalizationRegistry"in globalThis?new FinalizationRegistry(t=>{t.logger.log({level:_.warn,message:`A subscription to ${t.name} with params ${JSON.stringify(t.parameters)} leaked! Please ensure calling unsubscribe() when you don't need a subscription anymore. For global subscriptions, consider storing them in global fields to avoid this warning.`})}):null;class Qt{table;head;_length;constructor(t){this.table=[...t],this.head=0,this._length=this.table.length}get isEmpty(){return 0==this.length}get length(){return this._length}removeFirst(){if(this.isEmpty)throw new Error("Queue is empty");const t=this.table[this.head];return this._length--,this.table[this.head]=void 0,this.head=(this.head+1)%this.table.length,t}addLast(t){if(this.length==this.table.length)throw new Error("Queue is full");this.table[(this.head+this._length)%this.table.length]=t,this._length++}}class Yt{available;size;firstWaiter;lastWaiter;constructor(t){this.available=new Qt(t),this.size=this.available.length}addWaiter(t,e){const n={isActive:!0,acquiredItems:[],remainingItems:t,onAcquire:e,prev:this.lastWaiter};return this.lastWaiter?(this.lastWaiter.next=n,this.lastWaiter=n):this.lastWaiter=this.firstWaiter=n,n}deactivateWaiter(t){const{prev:e,next:n}=t;t.isActive=!1,e&&(e.next=n),n&&(n.prev=e),t==this.firstWaiter&&(this.firstWaiter=n),t==this.lastWaiter&&(this.lastWaiter=e)}requestPermits(t,e){if(t<=0||t>this.size)throw new Error(`Invalid amount of items requested (${t}), must be between 1 and ${this.size}`);return new Promise((n,s)=>{function r(){s(e?.reason??new Error("Semaphore acquire aborted"))}if(e?.aborted)return r();let i;const o=()=>{const t=i.acquiredItems;i.acquiredItems=[];for(const e of t){const t=this.firstWaiter;t?(t.acquiredItems.push(e),t.remainingItems--,0==t.remainingItems&&t.onAcquire()):this.available.addLast(e)}},a=()=>{e?.removeEventListener("abort",a),i.isActive&&(this.deactivateWaiter(i),r())},c=()=>{this.deactivateWaiter(i),e?.removeEventListener("abort",a);const t=i.acquiredItems;n({items:t,release:o})};for(i=this.addWaiter(t,c);!this.available.isEmpty&&i.remainingItems>0;)i.acquiredItems.push(this.available.removeFirst()),i.remainingItems--;if(0==i.remainingItems)return c();e?.addEventListener("abort",a)})}async requestOne(t){const{items:e,release:n}=await this.requestPermits(1,t);return{release:n,item:e[0]}}requestAll(t){return this.requestPermits(this.size,t)}}class Xt{inner=new Yt([null]);async acquire(t){const{release:e}=await this.inner.requestOne(t);return e}async runExclusive(t,e){const n=await this.acquire(e);try{return await t()}finally{n()}}}class Zt{clientId;id;op;opData;previousValues;table;transactionId;metadata;static fromRow(t){const e=JSON.parse(t.data);return new Zt(parseInt(t.id),e.op,e.type,e.id,t.tx_id,e.data,e.old,e.metadata)}constructor(t,e,n,s,r,i,o,a){this.clientId=t,this.id=s,this.op=e,this.opData=i,this.table=n,this.transactionId=r,this.previousValues=o,this.metadata=a}toJSON(){return{op_id:this.clientId,op:this.op,type:this.table,id:this.id,tx_id:this.transactionId,data:this.opData,old:this.previousValues,metadata:this.metadata}}equals(t){return JSON.stringify(this.toComparisonArray())==JSON.stringify(t.toComparisonArray())}toComparisonArray(){return[this.transactionId,this.clientId,this.op,this.table,this.id,this.opData,this.previousValues,this.metadata]}}const te=Symbol.asyncIterator??Symbol.for("Symbol.asyncIterator"),ee={done:!0,value:void 0};function ne(t){return{done:!1,value:t}}function se(t){let e,n=!1,s=null,r=!1,i=[];const o=()=>{const t=e;return e=void 0,t};return{next:()=>new Promise((a,c)=>{if(n)return a(ee);if(s)return s({resolve:a,reject:c}),void(s=null);if(i.length){const t=i.shift();return void("fulfilled"===t.status?a(ne(t.value)):c(t.reason))}e={resolve:a,reject:c},r||(()=>{const e=t=>{r=!1;const e=o();e?t(e):s=t};r=!0,t.next().then(t=>{n=1==t.done,e(e=>e.resolve(t))},t=>{e(e=>e.reject(t))})})()}),inject:t=>{const e=o();null!=e?e.resolve(ne(t)):i.push({status:"fulfilled",value:t})},injectError(t){const e=o();null!=e?e.reject(t):i.push({status:"rejected",reason:t})}}}function re(){const t=new ie;return{notify(){t.countOutstandingEvents>0||t.notify()},waitForNotification:e=>t.waitForEvent(e)}}class ie{options;waitingConsumer;outstandingEvents;constructor(t={}){this.options=t,this.outstandingEvents=[]}get countOutstandingEvents(){return this.outstandingEvents.length}notifyInner(t){const e=this.waitingConsumer;this.waitingConsumer=void 0;const n=e=>{t(e),this.options.eventDelivered?.()};e?n(e):this.outstandingEvents.push(n)}notify(t){this.notifyInner(e=>e.resolve(t))}notifyError(t){this.notifyInner(e=>e.reject(t))}waitForEvent(t){return new Promise((e,n)=>{if(null!=this.waitingConsumer)throw new Error("Illegal call to waitForEvent, already has a waiter.");const s=()=>{t?.removeEventListener("abort",r)},r=()=>{s(),this.waitingConsumer=void 0,e(void 0)},i={resolve:t=>{s(),e(t)},reject:t=>{s(),n(t)}};if(t.aborted)e(void 0);else if(this.countOutstandingEvents>0){const[t]=this.outstandingEvents.splice(0,1);t(i)}else this.waitingConsumer=i,t.addEventListener("abort",r)})}static queueBasedAsyncIterable(t,e){return{[te]:()=>{const n=new ie,s=new AbortController;function r(){s.abort(),e?.removeEventListener("abort",r)}return e&&(e.aborted?s.abort():e.addEventListener("abort",r)),t(n,s.signal),{async next(){const t=await n.waitForEvent(s.signal);return null==t?ee:ne(t)},return:async()=>(r(),ee)}}}}}class oe extends I{db;logger;updateListener;_clientId;constructor(t,e){super(),this.db=t,this.logger=e,this.updateListener=t.registerListener({tablesUpdated:({tables:t})=>{t.includes(Ft.CRUD)&&this.iterateListeners(t=>t.crudUpdate?.())}})}async dispose(){this.updateListener?.()}async _getClientId(){return(await this.db.get("SELECT powersync_client_id() as client_id")).client_id}getClientId(){return null==this._clientId&&(this._clientId=this._getClientId()),this._clientId}async updateLocalTarget(t){const e=await this.db.readTransaction(async t=>{if(await Nt(t)!=Bt)return;const e=await t.getOptional("SELECT seq FROM main.sqlite_sequence WHERE name = 'ps_crud'");return e?.seq});if(null==e)return!1;const n=await t();return this.writeTransaction(async t=>{const s=await t.execute("SELECT 1 FROM ps_crud LIMIT 1");if(s.rows?.length)return this.logger.log({level:_.debug,message:`New data uploaded since write checkpoint ${n} - need new write checkpoint`}),!1;const{seq:r}=await t.get("SELECT seq FROM main.sqlite_sequence WHERE name = 'ps_crud'");return r!=e?(this.logger.log({level:_.debug,message:`New data uploaded since write checpoint ${n} - need new write checkpoint (sequence updated)`}),!1):(this.logger.log({level:_.debug,message:`Updating target write checkpoint to ${n}`}),await Nt(t,n),!0)})}readCheckpointRequestId(t,e=null){return this.db.writeTransaction(async n=>await Dt(n,`${t}_checkpoint_request_id`,e))}async nextCrudItem(){const t=await this.db.getOptional("SELECT * FROM ps_crud ORDER BY id ASC LIMIT 1");if(t)return Zt.fromRow(t)}async hasCrud(){return!!await this.db.getOptional("SELECT 1 FROM ps_crud LIMIT 1")}async getCrudBatch(t=100){if(!await this.hasCrud())return null;const e=await this.db.getAll("SELECT * FROM ps_crud ORDER BY id ASC LIMIT ?",[t]),n=[];for(const t of e)n.push(Zt.fromRow(t));if(0===n.length)return null;const s=n[n.length-1];return{crud:n,haveMore:!0,complete:async t=>this.handleCrudCheckpoint(s.clientId,t)}}handleCrudCheckpoint(t,e){return this.writeTransaction(async n=>{if(await n.execute("DELETE FROM ps_crud WHERE id <= ?",[t]),e){const t=await n.execute("SELECT 1 FROM ps_crud LIMIT 1");t.rows?.length&&await Nt(n,e)}else await Nt(n,Bt)})}async writeTransaction(t,e){return this.db.writeTransaction(t,e)}async control(t,e){return await this.writeTransaction(async n=>await Dt(n,t,e))}async hasMigratedSubkeys(){const{r:t}=await this.db.get("SELECT EXISTS(SELECT * FROM ps_kv WHERE key = ?) as r",[oe._subkeyMigrationKey]);return 0!=t}async migrateToFixedSubkeys(){await this.writeTransaction(async t=>{await t.execute("UPDATE ps_oplog SET key = powersync_remove_duplicate_key_encoding(key);"),await t.execute("INSERT OR REPLACE INTO ps_kv (key, value) VALUES (?, ?);",[oe._subkeyMigrationKey,"1"])})}static _subkeyMigrationKey="powersync_js_migrated_subkeys"}const ae={state:"pending"};class ce{currentState=ae;stateChanged=new I;waitingForCheckpointsReady=re();updateState(t){this.currentState=t,this.stateChanged.iterateListeners(t=>t.stateChanged?.())}downloadIterationEnded(){this.updateState(ae),this.waitingForCheckpointsReady=re()}disconnected(){this.updateState({state:"disconnected"})}waitForCheckpointWaiter(t){return this.waitingForCheckpointsReady.waitForNotification(t)}markCheckpointsReady(t){return t.then(t=>this.updateState({state:"ready"}),t=>{throw this.updateState({state:"error",error:t}),t})}async waitForCheckpointRequestsReady(t,e=!0){return new Promise((n,s)=>{if(t.aborted)return void n(!1);const r=()=>{const t=this.currentState;switch(t.state){case"disconnected":return s(new Error("Cannot request checkpoints, sync client is disconnected.")),!0;case"ready":return n(!0),!0;case"error":return s(t.error),!0;case"pending":return e&&this.waitingForCheckpointsReady.notify(),!1}};if(r())return;let i,o;function a(){i(),t.removeEventListener("abort",o)}o=()=>{n(!1),a()},i=this.stateChanged.registerListener({stateChanged(){r()&&a()}}),t.addEventListener("abort",o)})}}function le(t,e){const n=t?.internal_last_applied_checkpoint_request_id;return null!=n&&BigInt(n)>=e}class ue extends Error{reason;constructor(t){super(t),this.reason=t,Object.setPrototypeOf(this,ue.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,ue)}}const he=/\/+$/,de={LogLevels:_,EventQueue:ie,AbortOperation:ue};class pe{connector;logger;credentials=null;constructor(t,e){this.connector=t,this.logger=e}async getCredentials(t){return this.credentials?this.credentials:this.prefetchCredentials(t)}async prefetchCredentials(t){return this.credentials=await this.fetchCredentials(t),this.credentials}async fetchCredentials(t){const e=await this.connector.fetchCredentials(t);if(e?.endpoint.match(he))throw new Error(`A trailing forward slash "/" was found in the fetchCredentials endpoint: "${e.endpoint}". Remove the trailing forward slash "/" to fix this error.`);return e}invalidateCredentials(){this.credentials=null,this.connector.invalidateCredentials?.()}getUserAgent(){return"powersync-js/1.3.1"}async buildRequest(t,e){const n=await this.getCredentials(e);if(null!=n&&(null==n.endpoint||""==n.endpoint))throw new Error("PowerSync endpoint not configured");if(null==n?.token||""==n?.token){const t=new Error("Not signed in");throw t.status=401,t}const s=this.getUserAgent();return{url:n.endpoint+t,headers:{"content-type":"application/json",Authorization:`Token ${n.token}`,"x-user-agent":s},userAgent:s,path:t}}async fetchAndDecodeJson({path:t,method:e="GET",headers:n,body:s,signal:r}){const i=await this.buildRequest(t,r),o=await this.fetch({resource:i.url,request:{method:e,headers:{...n,...i.headers},body:s,signal:r},expectStreamingResponse:!1});if(401===o.status&&this.invalidateCredentials(),!o.ok)throw new Error(`Received ${o.status} - ${o.statusText} when getting from ${t}: ${await o.text()}}`);return o.json()}createTextDecoder(){return new TextDecoder}createSocket(t){return new WebSocket(t)}async socketStreamRaw(t){const e=await this.loadWebSocketSupport(de),n=await this.buildRequest(t.path,t.abortSignal);n.url=n.url.replace(/^https?:\/\//,function(t){return"https://"===t?"wss://":"ws://"});const{fetchStrategy:s=T.Buffered,abortSignal:r,data:i}=t;return await e.webSocketSyncStream({remote:this,buffered:s==T.Buffered,abortSignal:r,requestPayload:i,request:n})}async fetchStreamRaw(t){const{data:e,path:n,abortSignal:s}=t,r=await this.buildRequest(n,s);if(s.aborted)throw new ue("Abort request received before making fetchStreamRaw request");const i=new AbortController;let o,a=null;s.addEventListener("abort",()=>{const t=s.reason??new ue("Cancelling network request before it resolves. Abort signal has been received.");null==a?i.abort(t):a.cancel(t).catch(()=>{})});let c=!1;try{const t="application/x-ndjson",s="application/vnd.powersync.bson-stream";if(o=await this.fetch({resource:r.url,request:{method:"POST",headers:{...r.headers,accept:`${s};q=0.9,${t};q=0.8`},body:JSON.stringify(e),signal:i.signal,cache:"no-store"},expectStreamingResponse:!0}),!o.ok||!o.body){const t=await o.text(),e=new Error(`HTTP ${o.statusText}: ${t}`);throw e.status=o.status,this.logger.log({level:_.error,message:`Could not POST streaming to ${n} - ${o.status} - ${o.statusText}: ${t}`,error:e}),401===o.status&&this.invalidateCredentials(),e}c=o.headers.get("content-type")==s}catch(t){if("AbortError"==t.name)throw new ue(`Pending fetch request to ${r.url} has been aborted.`);throw t}a=o.body.getReader();return{isBson:c,stream:{next:async()=>{if(i.signal.aborted)return ee;try{return await a.read()}catch(t){if(i.signal.aborted)return ee;throw t}}}}}async fetchStream(t){const{isBson:e,stream:n}=await this.fetchStreamRaw(t);return e?function(t){const e=[];let n=!1;const s=new DataView(new ArrayBuffer(4));let r=null,i=4;return{async next(){for(;;){if(e.length)return ne(e.shift());if(n)return ee;const o=await t.next();if(o.done){if(n=!0,r||4!=i)throw new Error("illegal end of stream in BSON object");return ee}const a=o.value;for(let t=0;t{for(;;){if(r)return ee;{const t=s.shift();if(t)return{done:!1,value:t}}const{done:i,value:o}=await t.next();if(i){const t=n.trim();return 0!=t.length?(r=!0,{done:!1,value:t}):ee}const a=e.decode(o,{stream:!0});n+=a;const c=n.split("\n");for(let t=0;t0&&s.push(e)}n=c[c.length-1]}}}}(n,this.createTextDecoder())}}function ge(t){return"EstablishSyncStream"in t||"CloseSyncStream"in t}var me;!function(t){t.CRUD="crud",t.SYNC="sync"}(me||(me={}));class fe extends I{options;abortController;crudUpdateListener;streamingSyncPromise;logger;activeStreams;connectionMayHaveChanged=!1;crudUploadNotifier=re();checkpoints=new ce;notifyCompletedUploads;handleActiveStreamsChange;syncStatus;constructor(t){super(),this.options=t,this.activeStreams=t.subscriptions,this.logger=t.logger,this.syncStatus=new jt(null,{}),this.abortController=null}triggerCrudUpload(){this.crudUploadNotifier.notify()}async waitForReady(){}waitUntilStatusMatches(t){return new Promise(e=>{if(t(this.syncStatus))return void e();const n=this.registerListener({statusChanged:()=>{t(this.syncStatus)&&(e(),n?.())}})})}get lastSyncedAt(){const t=this.syncStatus.lastSyncedAt;return t&&new Date(t)}get isConnected(){return this.syncStatus.connected}async dispose(){super.dispose(),this.crudUpdateListener?.(),this.crudUpdateListener=void 0}async requestNextCheckpointFromService(t){if(!await this.checkpoints.waitForCheckpointRequestsReady(t))throw t.reason;const e=await this.options.adapter.readCheckpointRequestId("next"),n=await this.options.adapter.getClientId();return await this.requestCheckpointFromService(t,{client_id:n,checkpoint_request_id:e})}async requestCheckpointFromService(t,e){{const n=await this.options.postCheckpointRequest(e.client_id,e.checkpoint_request_id,t);if(null!=n)return n}return(await this.options.remote.fetchAndDecodeJson({method:"POST",path:"/sync/checkpoint-request",body:JSON.stringify(e),signal:t})).data.checkpoint_request_id}async getLegacyWriteCheckpoint(){let t=`/write-checkpoint2.json?client_id=${await this.options.adapter.getClientId()}`;const e=(await this.options.remote.fetchAndDecodeJson({path:t})).data.write_checkpoint;return this.logger.log({level:_.debug,message:`Created write checkpoint: ${e}`}),e}async crudUploadLoop(t,e){for(;!t.aborted;)await Promise.all([this._uploadAllCrud(t,e),this.delayRetry(t,e.crudUploadThrottleMs)]),await this.crudUploadNotifier.waitForNotification(t)}async _uploadAllCrud(t,e){return this.obtainLock({type:me.CRUD,signal:t,callback:async()=>{let n;for(;!t.aborted;)try{const s=await this.options.adapter.nextCrudItem();if(!s){await this.options.adapter.updateLocalTarget(()=>"legacy"===e.checkpointMode?this.getLegacyWriteCheckpoint():this.requestNextCheckpointFromService(t))?this.notifyCompletedUploads?.():null!=n&&this.logger.log({level:_.debug,message:"Upload complete, no write checkpoint needed."});break}if(this.updateJsSyncState({uploading:!0}),s.clientId==n?.clientId)throw this.logger.log({level:_.warn,message:"Potentially previously uploaded CRUD entries are still present in the upload queue.\nMake sure to handle uploads and complete CRUD transactions or batches by calling and awaiting their [.complete()] method.\nThe next upload iteration will be delayed."}),new Error("Delaying due to previously encountered CRUD item.");n=s,await this.options.uploadCrud(t),this.updateJsSyncState({uploadError:void 0})}catch(s){if(n=void 0,this.updateJsSyncState({uploading:!1,uploadError:s}),await this.delayRetry(t,e.retryDelayMs),!this.isConnected)break;this.logger.log({level:_.debug,message:"Caught exception when uploading. Upload will retry after a delay.",error:s})}finally{this.updateJsSyncState({uploading:!1})}}})}async connect(t){this.abortController&&await this.disconnect();const e=new AbortController;this.abortController=e;const n=e.signal;return this.streamingSyncPromise=Promise.all([this.crudUploadLoop(n,t).catch(t=>{n.reason!==t&&this.logger.log({level:_.error,message:"Error in crud upload loop",error:t})}),this.streamingSync(n,t),this.repostUnacknowledgedCheckpointRequests(n,t)]).finally(()=>{this.checkpoints.disconnected()}),new Promise(t=>{let e=!1,s=!1;const r=()=>{s||(s=!0,i(),n.removeEventListener("abort",r),t())},i=this.registerListener({statusChanged:t=>{if(t.connecting&&(e=!0),null!=t.downloadError)this.logger.log({level:_.warn,message:"Initial connect attempt did not successfully connect to server"});else if(!e||t.connecting)return;r()}});n.addEventListener("abort",r,{once:!0})})}async requestCheckpoint(){const t=(new AbortController).signal;return BigInt(await this.requestNextCheckpointFromService(t))}async disconnect(){if(this.abortController){this.abortController.signal.aborted||this.abortController.abort(new ue("Disconnect has been requested"));try{await this.streamingSyncPromise}catch(t){this.logger.log({level:_.warn,message:"Error in sync while disconnecting",error:t})}this.streamingSyncPromise=void 0,this.abortController=null,this.markAsDisconnected()}}markAsDisconnected(){const t=this.syncStatus.core;null!=t&&this.updateSyncStatus({...t,connected:!1,connecting:!1,downloading:null})}async streamingSync(t,e){this.crudUpdateListener=this.options.adapter.registerListener({crudUpdate:()=>this.triggerCrudUpload()});let n=new AbortController;for(t.addEventListener("abort",()=>{n.abort(t?.reason??new ue("Received command to disconnect from upstream")),this.crudUpdateListener?.(),this.crudUpdateListener=void 0,this.markAsDisconnected()});;){let s=!0,r=null;try{if(t?.aborted)break;r=await this.streamingSyncIteration(n.signal,e)}catch(e){const n=t.aborted;n?(this.logger.log({level:_.warn,message:"Sync aborted",error:e}),s=!1):this.connectionMayHaveChanged&&e.message?.indexOf("No iteration is active")>=0?(this.connectionMayHaveChanged=!1,this.logger.log({level:_.info,message:"Sync error after changed connection, retrying immediately"}),s=!1):this.logger.log({level:_.error,message:"Sync error",error:e}),n||this.updateJsSyncState({downloadError:e})}finally{this.checkpoints.downloadIterationEnded(),this.notifyCompletedUploads=void 0,t.aborted||(n.abort(new ue("Closing sync stream network requests before retry.")),n=new AbortController),1!=r?.immediateRestart&&(this.markAsDisconnected(),s&&await this.delayRetry(n.signal,e.retryDelayMs,!0))}}this.markAsDisconnected()}markConnectionMayHaveChanged(){this.connectionMayHaveChanged=!0,this.handleActiveStreamsChange?.()}async requireKeyFormat(t){const e=await this.options.adapter.hasMigratedSubkeys();return t&&!e?(await this.options.adapter.migrateToFixedSubkeys(),!0):e}streamingSyncIteration(t,e){return this.obtainLock({type:me.SYNC,signal:t,callback:async()=>{const n=Object.entries(e.appMetadata).filter(([t,e])=>"string"!=typeof e);if(n.length>0)throw new Error(`Invalid appMetadata provided. Only string values are allowed. Invalid values: ${n.map(([t,e])=>`${t}: ${e}`).join(", ")}`);return await this.requireKeyFormat(!0),await this.rustSyncIteration(t,e)}})}receiveSyncLines(t){const{options:e,connection:n}=t,s=this.options.remote,r=async()=>n.connectionMethod==q.HTTP?await s.fetchStream(e):await this.options.remote.socketStreamRaw({...e,fetchStrategy:n.fetchStrategy});let i,o=!1;return{async next(){if(o)return ee;if(null==i)return i=await r(),ne({command:Ut.CONNECTION_STATE,payload:"established"});{const t=await i.next();return t.done?(o=!0,ne({command:Ut.CONNECTION_STATE,payload:"end"})):ne({command:"string"==typeof t.value?Ut.PROCESS_TEXT_LINE:Ut.PROCESS_BSON_LINE,payload:t.value})}}}}async repostUnacknowledgedCheckpointRequests(t,e){let n;const s=e.checkpointMode;if("legacy"!=s)for(n="requests"==s?1e4:Math.max(s.requests.retryDelay,1e4);!t.aborted;)try{if(!await this.checkpoints.waitForCheckpointRequestsReady(t,!1))return;const e=await this.options.adapter.readCheckpointRequestId("current");if(await this.delayRetry(t,n),e!=await this.options.adapter.readCheckpointRequestId("current"))continue;if(le(this.syncStatus?.core,BigInt(e)))continue;if(!await this.checkpoints.waitForCheckpointRequestsReady(t,!1))return;this.logger.log({level:_.debug,message:`Retry checkpoint request ${e}`}),await this.requestCheckpointFromService(t,{client_id:await this.options.adapter.getClientId(),checkpoint_request_id:e})}catch(e){if(t.aborted)return;this.logger.log({level:_.warn,error:e,message:"Error retrying checkpoint request."}),await this.delayRetry(t,n)}}async seedCheckpointRequestState(t,e){const n=await this.requestCheckpointFromService(t,e);await this.options.adapter.readCheckpointRequestId("seed",n)}async rustSyncIteration(t,e){const n=this,s=this.options.adapter,r=this.options.remote;let i,o=!1;if(t.aborted)throw new ue("Connection request has been aborted");const a=this.options.serializedSchema;async function c(t,e){const r=await s.control(t,e??null),i=null==e||"string"==typeof e?e:"";return n.logger.log({level:_.trace,message:`powersync_control(${t}, ${i}) -> ${r}`}),t!=Ut.STOP&&(n.connectionMayHaveChanged=!1),JSON.parse(r)}async function l(t){if("LogLine"in t){const{severity:e,line:s}=t.LogLine;switch(e){case"DEBUG":n.logger.log({level:_.debug,message:s});break;case"INFO":n.logger.log({level:_.info,message:s});break;case"WARNING":n.logger.log({level:_.warn,message:s})}}else"UpdateSyncStatus"in t?n.updateSyncStatus(t.UpdateSyncStatus.status):"FetchCredentials"in t?t.FetchCredentials.did_expire?r.invalidateCredentials():(r.invalidateCredentials(),r.fetchCredentials().then(t=>{i?.()},t=>{n.logger.log({level:_.warn,message:"Could not prefetch credentials",error:t})})):"FlushFileSystem"in t||"DidCompleteSync"in t&&n.updateJsSyncState({downloadError:void 0})}try{const s={immediateRestart:!1};let r=null;for(const i of await function(){const t={parameters:e.params,app_metadata:e.appMetadata,active_streams:n.activeStreams,include_defaults:e.includeDefaultStreams,checkpoint_mode:"legacy"===e.checkpointMode?"legacy":"requests"};return a&&(t.schema=a),c(Ut.START,JSON.stringify(t))}())if("EstablishSyncStream"in i){const s=i.EstablishSyncStream,o={path:"/sync/stream",abortSignal:t,data:s.request};if(r=se(n.receiveSyncLines({options:o,connection:e})),s.checkpoint_request){this.checkpoints.markCheckpointsReady(this.seedCheckpointRequestState(t,s.checkpoint_request)).catch(e=>{t.aborted||r?.injectError(e)})}}else{if("CloseSyncStream"in i)return s;await l(i)}if(null==r)return s;this.notifyCompletedUploads=()=>{r.inject({command:Ut.NOTIFY_CRUD_UPLOAD_COMPLETED})},this.handleActiveStreamsChange=()=>{r.inject({command:Ut.UPDATE_SUBSCRIPTIONS,payload:JSON.stringify(this.activeStreams)})},i=()=>{r.inject({command:Ut.NOTIFY_TOKEN_REFRESHED})};let u=!1;t:for(;;){const{done:t,value:e}=await r.next();if(t)break;u||e.command!=Ut.PROCESS_TEXT_LINE&&e.command!=Ut.PROCESS_BSON_LINE||(u=!0,this.triggerCrudUpload?.());const n=await c(e.command,e.payload);for(const t of n){if("EstablishSyncStream"in t)throw new Error("Received EstablishSyncStream while already connected.");if("CloseSyncStream"in t){o=t.CloseSyncStream.hide_disconnect;break t}await l(t)}}}finally{this.notifyCompletedUploads=this.handleActiveStreamsChange=void 0,i=void 0,await async function(){const t=await c(Ut.STOP);for(const e of t)ge(e)||await l(e)}()}return{immediateRestart:o}}updateSyncStatus(t,e){const n=new jt(t,{...this.syncStatus.jsState,...e});this.syncStatus.isEqual(n)||(this.syncStatus=n,this.iterateListeners(t=>t.statusChanged?.(n)))}updateJsSyncState(t){this.updateSyncStatus(this.syncStatus.core,t)}async delayRetry(t,e,n=!1){return new Promise(s=>{if(t.aborted)return void s();let r,i=null;const o=()=>{s(),r&&(clearTimeout(r),r=void 0),i&&(i.abort(),i=null),t.removeEventListener("abort",o)};t.addEventListener("abort",o,{once:!0});const a=e*(.9+.2*Math.random());r=setTimeout(o,a),n&&(i=new AbortController,this.checkpoints.waitForCheckpointWaiter(i.signal).finally(o))})}updateSubscriptions(t){this.activeStreams=t,this.handleActiveStreamsChange?.()}}class ye extends Error{static NAME="ConnectionClosedError";static MATCHES(t){return t instanceof ye||t instanceof Error&&t.name==ye.NAME}constructor(t){super(t),this.name=ye.NAME}}class we{inner;leaseMutex;constructor(t,e){this.inner=t,this.leaseMutex=e?null:new Xt}get options(){return this.inner.options}acquireMutex(t){return this.leaseMutex?this.leaseMutex.acquire(t):new Promise((e,n)=>{const s={signal:t};navigator.locks.request(`db-lock-${this.options.filename}`,s,t=>new Promise(t=>e(()=>{t()}))).catch(n)})}unsafeUseInner(){return this.inner}async acquireConnection(t){const e=await this.acquireMutex(t),n=new be(e,this.inner);try{this.inner.requireSqlite(),this.inner.isAutoCommit()||await this.inner.executeRaw("ROLLBACK")}catch(t){throw e(),t}return n}async close(){const t=await this.acquireMutex();try{await this.inner.close()}finally{t()}}}class be{returnMutex;connection;useMutex=new Xt;closed=!1;constructor(t,e){this.returnMutex=t,this.connection=e}async returnLease(){await this.useMutex.runExclusive(async()=>{this.closed||(this.closed=!0,this.returnMutex())})}async use(t){return await this.useMutex.runExclusive(async()=>{if(this.closed)throw new Error("lease token has already been closed");return await t(this.connection)})}}const Se="open-wasqlite-db";const ve="SharedWorkerGlobalScope"in globalThis;class _e extends pe{connector;constructor(t,e){super(t,e),this.connector=t}fetch({resource:t,request:e}){return fetch(t,e)}async loadWebSocketSupport(t){if(!Ce){const e=await import("./websockets-Q8W_lerF.js");Ce=new e.WebSocketSupport(t)}return Ce}getUserAgent(){let t=[super.getUserAgent(),"powersync-web"];try{t.push(...function(t){t??=navigator;const e=function(t){const e=t.userAgentData?.brands;if(null!=e){const t=[{name:"Google Chrome",value:"Chrome"},{name:"Opera",value:"Opera"},{name:"Edge",value:"Edge"},{name:"Chromium",value:"Chromium"}];for(let{name:n,value:s}of t){const t=e.find(t=>t.brand==n);if(null!=t)return`${s}/${t.version}`}}const n=t.userAgent,s=[{re:/(?:firefox|fxios)\/(\d+)/i,value:"Firefox"},{re:/(?:edg|edge|edga|edgios)\/(\d+)/i,value:"Edge"},{re:/opr\/(\d+)/i,value:"Opera"},{re:/(?:chrome|chromium|crios)\/(\d+)/i,value:"Chrome"},{re:/version\/(\d+).*safari/i,value:"Safari"}];for(let{re:t,value:e}of s){const s=t.exec(n);if(null!=s)return`${e}/${s[1]}`}return null}(t),n=function(t){if(null!=t.userAgentData?.platform)return t.userAgentData.platform.toLowerCase();const e=t.userAgent,n=[{re:/windows/i,value:"windows"},{re:/android/i,value:"android"},{re:/linux/i,value:"linux"},{re:/iphone|ipad|ipod/i,value:"ios"},{re:/macintosh|mac os x/i,value:"macos"}];for(let{re:t,value:s}of n)if(t.test(e))return s;return null}(t);return[e,n].filter(t=>null!=t)}())}catch(t){this.logger.log({level:_.warn,message:"Failed to get user agent info",error:t})}return t.join(" ")}}let Ce;class Ee extends fe{constructor(t){super(t)}get webOptions(){return this.options}async obtainLock(t){const e=`streaming-sync-${t.type}-${this.webOptions.identifier}`;return t.type==me.SYNC&&this.logger.log({level:_.debug,message:`requesting lock for ${e}`}),N().request(e,{signal:t.signal},t.callback)}}class ke{clients;inner;currentLevel=_.info;sendBroadcasts=!0;constructor(t,e){this.clients=e,this.inner=C({prefix:t})}log(t){if(this.inner.log(t),this.sendBroadcasts&&t.level>=this.currentLevel){const e=this.sanitizeRecord(t);this.iterateClients(t=>t.clientProvider.log(e))}}setLevel(t){this.inner.minLevel=t,this.currentLevel=t}async iterateClients(t){for(const e of this.clients)try{await t(e)}catch(t){console.error("Caught exception when iterating client",t)}}sanitizeRecord(t){if(!t.error)return t;let e;try{e=structuredClone(t.error)}catch(t){console.error(t),e="Could not serialize log params. Check shared worker logs for more details."}return{...t,error:e}}}class Ae extends F{options;config;#u;#h=new AbortController;#d;constructor(t,e){super(),this.options=t,this.config=e,this.#u={connection:t.connection,notifyRemoteClosed:t.remoteCanCloseUnexpectedly?new AbortController:void 0,traceQueries:!0===e.debugMode};const{port1:n,port2:s}=new MessageChannel;t.connection.setUpdateListener(y(n,[n])),this.#d=s,s.onmessage=t=>{const e={tables:t.data};this.iterateListeners(t=>{t.tablesUpdated&&t.tablesUpdated(e)})}}get name(){return this.config.dbFilename}markRemoteClosed(){this.#u.notifyRemoteClosed.abort()}async close(){this.#h.abort(),this.#d.close(),await qe(this.#u,t=>t.close(),!0),this.options.onClose?.(),this.options.source?.[n]()}readLock(t,e){return this.#p(!1,t,e)}writeLock(t,e){return this.#p(!0,t,e)}async#p(t,e,n){const s=await qe(this.#u,e=>e.requestAccess(t,n?.timeoutMs));try{return await e(new Le(this.#u,s))}finally{await qe(this.#u,t=>t.completeAccess(s))}}async refreshSchema(){}async shareConnection(){const t=this.#h,n=this.options.source;if(null==n)throw new Error("shareConnection() is only available for connections based by workers.");await new Promise((e,n)=>navigator.locks.request(`shared-connection-${this.name}-${Date.now()}-${Math.round(1e4*Math.random())}`,{signal:t.signal},async()=>{e(),t.signal.aborted||await new Promise(e=>{t.signal.addEventListener("abort",()=>{e()})})}).catch(t=>{"AbortError"==t.name?e():n(t)}));return{port:await n[e](),identifier:this.name}}getConfiguration(){return this.config}}class Le extends M{#u;#g;constructor(t,e){super(),this.#u=t,this.#g=e}async maybeTrace(t,e){if(!this.#u.traceQueries)return qe(this.#u,t);{const n=performance.now(),s=e();try{const e=await qe(this.#u,t);return performance.measure(`[SQL] ${s}`,{start:n}),e}catch(t){throw performance.measure(`[SQL] [ERROR: ${t.message}] ${s}`,{start:n}),t}}}async executeRaw(t,e){return await this.#m(t,e)}async#m(t,e){return this.maybeTrace(n=>n.execute(this.#g,t,e),()=>t)}async executeBatch(t,e=[]){const n=await this.maybeTrace(n=>n.executeBatch(this.#g,t,e),()=>`${t} (batch of ${e.length})`),s={insertId:void 0,rowsAffected:0};for(const t of n)s.insertId=t.insertId,s.rowsAffected=(s.rowsAffected??0)+t.rowsAffected;return R(s)}}async function qe(t,e,n=!1){const s=t.notifyRemoteClosed;return s?new Promise((r,i)=>{function o(){i(new ye("Remote peer closed with request in flight"))}function a(t){s.signal.removeEventListener("abort",o),t()}s.signal.aborted&&(i(new ye("Called operation on closed remote")),!n)||(s.signal.addEventListener("abort",o),e(t.connection).then(t=>a(()=>r(t))).catch(t=>a(()=>i(t))))}):e(t.connection)}var Te;!function(t){t.CLOSE_CLIENT="close-client",t.CLOSE_ACK="close-ack"}(Te||(Te={}));const xe={};class Pe extends I{ports;isInitialized;statusListener;syncParams;lastConnectOptions;portMutex;subscriptions=[];connectionManager;syncStatus;logger;database=this.generateReconnectableDatabase();sharedCloseSignal=function(t){return new Promise((e,n)=>{const s={signal:t};N().request(`tab-close-signal-${crypto.randomUUID()}`,s,t=>(e(t.name),new Promise(t=>{}))).catch(n)})}();constructor(){super(),this.ports=[],this.syncParams=null,this.lastConnectOptions=void 0,this.portMutex=new Xt,this.isInitialized=new Promise(t=>{const e=this.registerListener({initialized:()=>{t(),e?.()}})}),this.logger=new ke("shared-sync",this.ports),this.connectionManager=new Vt({createSyncImplementation:async()=>{await this.waitForReady();const t=this.generateStreamingImplementation(),e=t.registerListener({statusChanged:t=>{this.syncStatus=t;const e=t.toJSON();this.ports.forEach(t=>t.clientProvider.statusChanged(e))}});return{sync:t,onDispose:()=>{e(),this.syncStatus&&=new jt(this.syncStatus.core,{})}}},logger:this.logger,defaultConnectionMethod:q.HTTP})}get isConnected(){return this.connectionManager.syncStreamImplementation?.isConnected??!1}async getLastWrappedPort(){return await this.portMutex.runExclusive(()=>{for(let t=this.ports.length-1;t>=0;t--)if(!this.ports[t].isClosing)return this.ports[t]})}async getRandomWrappedPort(){return await this.portMutex.runExclusive(()=>{const t=this.ports.filter(t=>!t.isClosing);return t[Math.floor(Math.random()*t.length)]})}async waitUntilStatusMatches(t){return this.withSyncImplementation(async e=>e.waitUntilStatusMatches(t))}async waitForReady(){return this.isInitialized}collectActiveSubscriptions(){this.logger.log({level:_.debug,message:"Collecting active stream subscriptions across tabs"});const t=new Map;for(const e of this.ports)for(const n of e.currentSubscriptions){const e=JSON.stringify(n);t.set(e,n)}this.subscriptions=[...t.values()],this.logger.log({level:_.debug,message:`Collected stream subscriptions, ${JSON.stringify(this.subscriptions)}`}),this.connectionManager.syncStreamImplementation?.updateSubscriptions(this.subscriptions)}updateSubscriptions(t,e){t.currentSubscriptions=e,this.collectActiveSubscriptions()}setLogLevel(t){this.logger.setLevel(t)}async setParams(t){await this.portMutex.runExclusive(async()=>{this.collectActiveSubscriptions()}),this.syncParams||(this.syncParams=t,this.logger.sendBroadcasts=t.enableBroadcastLogs,await this.database.readLock(async()=>{}),self.onerror=t=>{this.logger.log({level:_.error,message:"Uncaught exception in PowerSync shared sync worker",error:t})},this.iterateListeners(t=>t.initialized?.()))}async dispose(){return await this.waitForReady(),this.statusListener?.(),this.connectionManager.close()}async connect(t,e){return this.lastConnectOptions=t,this.connectionManager.connect(xe,t??{},e)}async disconnect(){return this.connectionManager.disconnect()}async addPort(t){return await this.portMutex.runExclusive(()=>{const e={port:t,clientProvider:l(t),currentSubscriptions:[],closeListeners:[],isClosing:!1};this.ports.push(e);const n=this.syncStatus;return n&&e.clientProvider.statusChanged(n.toJSON()),e})}async removePort(t){return t.isClosing=!0,await this.portMutex.runExclusive(async()=>{const e=this.ports.findIndex(e=>e==t);if(e<0)return this.logger.log({level:_.warn,message:`Could not remove port ${t} since it is not present in active ports.`}),()=>{};const s=this.ports[e];this.ports.splice(e,1);for(const t of s.closeListeners)await t();return this.collectActiveSubscriptions(),()=>s.clientProvider[n]()})}triggerCrudUpload(){this.withSyncImplementation(async t=>{t.triggerCrudUpload()})}requestCheckpoint(){return this.withSyncImplementation(t=>t.requestCheckpoint())}async withSyncImplementation(t){if(await this.waitForReady(),this.connectionManager.syncStreamImplementation)return t(this.connectionManager.syncStreamImplementation);return t(await new Promise(t=>{const e=this.connectionManager.registerListener({syncStreamCreated:n=>{t(n),e?.()}})}))}generateStreamingImplementation(){const t=this.syncParams;return new Ee({adapter:new oe(this.database,this.logger),remote:new _e({invalidateCredentials:async()=>{const t=await this.getLastWrappedPort();if(!t)throw new Error("No client port found to invalidate credentials");try{this.logger.log({level:_.info,message:"calling the last port client provider to invalidate credentials"}),t.clientProvider.invalidateCredentials()}catch(t){this.logger.log({level:_.error,message:"error invalidating credentials",error:t})}},fetchCredentials:t=>this.#f(t=>(this.logger.log({level:_.info,message:"calling the last port client provider for credentials"}),t.clientProvider.fetchCredentials()),"fetchCredentials",t)},this.logger),uploadCrud:t=>this.#f(t=>t.clientProvider.uploadCrud(),"uploadCrud",t),postCheckpointRequest:(t,e,n)=>this.#f(n=>n.clientProvider.postCheckpointRequest(t,e),"postCheckpointRequest",n),...t.streamOptions,subscriptions:this.subscriptions,logger:this.logger})}async#f(t,e,n){const s=async()=>{const n=await this.getLastWrappedPort();if(!n)throw new Error(`No client port found for ${e}`);return await new Promise((s,r)=>{const i=()=>{r(new Error(`Tab closed while handling ${e}`))};n.closeListeners.push(i),t(n).then(s,r).finally(()=>{const t=n.closeListeners.indexOf(i);t>=0&&n.closeListeners.splice(t,1)})})};return n?Ie({signal:n,action:s}):s()}async openInternalDB(t){const e=await this.getRandomWrappedPort();if(!e)throw new Error("Could not open DB connection since no client is connected.");const n=setTimeout(()=>{s.abort()},1e4),s=new AbortController,r=()=>{s.abort()},i=()=>{const t=e.closeListeners.indexOf(r);t>=0&&e.closeListeners.splice(t,1)};e.closeListeners.push(r);const o=l(await Ie({action:()=>e.clientProvider.getDBWorkerPort(),signal:s.signal,cleanupOnAbort:t=>{t.close()}}).catch(t=>{throw i(),t})),a=this.syncParams.dbParams.dbFilename,c=await this.sharedCloseSignal,u=await Ie({action:async()=>{const t=await o.connectToExisting({identifier:a,lockName:c});return new Ae({connection:t,source:o,remoteCanCloseUnexpectedly:!0},this.syncParams.dbParams)},signal:s.signal,cleanupOnAbort:t=>{t.close()}}).finally(()=>{i()});return clearTimeout(n),e.closeListeners.push(async()=>{this.logger.log({level:_.info,message:"Aborting open connection because associated tab closed."}),t(u),u.markRemoteClosed(),u.close().catch(t=>this.logger.log({level:_.warn,message:"error closing database connection",error:t}))}),u}generateReconnectableDatabase(){const t=this.syncParams,e=this;return new class extends F{connectionState=null;get name(){return t?.dbParams.dbFilename}async connect(){if(null==this.connectionState){const t=this.handleClientClosed.bind(this);this.connectionState=(async()=>{try{const n=await e.openInternalDB(t);return n.registerListener({tablesUpdated:t=>{this.iterateListeners(e=>e.tablesUpdated?.(t))}}),this.connectionState=n,n}catch(t){throw this.connectionState=null,t}})()}return await this.connectionState}async close(){null!=this.connectionState&&await(await this.connectionState).close()}handleClientClosed(t){if(t===this.connectionState){this.connectionState=null;const t=e.connectionManager.syncStreamImplementation;t?.triggerCrudUpload(),t?.markConnectionMayHaveChanged()}}async readLock(t,e){return(await this.connect()).readLock(t,e)}async writeLock(t,e){return(await this.connect()).writeLock(t,e)}async refreshSchema(){}}}}function Ie(t){const{action:e,signal:n,cleanupOnAbort:s}=t,r=()=>n.reason instanceof Error?n.reason:new ue("Operation aborted by abort controller");return new Promise((t,i)=>{function o(){n.removeEventListener("abort",o),i(r())}function a(t){n.removeEventListener("abort",o),t()}n.aborted?i(r()):(n.addEventListener("abort",o,{once:!0}),e().then(e=>{if(n.aborted)return a(()=>s?.(e));a(()=>t(e))}).catch(t=>a(()=>i(t))))})}class Oe{sync;port;resolvedPort=null;resolvedPortPromise=null;constructor(t,e){this.sync=t,this.port=e,a(this,this.port),this.port.addEventListener("message",async t=>{const e=t.data;e?.event==Te.CLOSE_CLIENT&&await this.removePort()})}async removePort(){if(this.resolvedPort){const t=this.resolvedPort;this.resolvedPort=null;const e=await this.sync.removePort(t);this.resolvedPort=null,this.port.postMessage({event:Te.CLOSE_ACK,data:{}}),e?.()}}async addLockBasedCloseSignal(t){this.resolvedPort=await this.sync.addPort(this.port),N().request(t,async()=>{await this.removePort()})}setLogLevel(t){this.sync.setLogLevel(t)}triggerCrudUpload(){return this.sync.triggerCrudUpload()}setParams(t,e){return this.resolvedPort.currentSubscriptions=e,this.sync.setParams(t)}connect(t,e){return this.sync.connect(t,e)}updateSubscriptions(t){this.resolvedPort&&this.sync.updateSubscriptions(this.resolvedPort,t)}requestCheckpoint(){return this.sync.requestCheckpoint()}disconnect(){return this.sync.disconnect()}}const Re=new class{logger;#y=new Map;#w=new Xt;constructor(t){this.logger=t}async handleConnection({logLevel:t,database:e,lockName:n}){const s={log:e=>{e.level>=t&&this.logger.log(e)}};return w(await this.openConnectionLocally(s,e,n))}async connectToExisting(t,e){return N().request(Se,async()=>{const n=this.#y.get(t);if(null==n)throw new Error(`connectToExisting(${t}) failed because the worker doesn't own a database with that name.`);return w(await n.connect(e))})}async openConnectionLocally(t,e,n){let s;for(let n=0;n<2;n++)try{s=await this.#b(t,e)}catch(t){this.logger.log({level:_.warn,message:`Attempt ${n+1} of 3 to open database failed, retrying in 1 second...`,error:t}),await new Promise(t=>setTimeout(t,1e3))}return s??=await this.#b(t,e),s.connect(n)}async#b(t,e){const{filename:n,readonly:s,vfs:r}=e,i=!(ve||s||r==xt.InMemoryVfs),o=this.#y;async function a(){let s=o.get(n);if(null==s){const r=new Mt(e),a=new we(r,i),c=await a.acquireMutex();try{await r.init()}catch(t){throw c(),await r.close(),t}c();s=new D({inner:a,logger:t,onClose:()=>o.delete(n)}),o.set(n,s)}return s}return i?N().request(Se,a):this.#w.runExclusive(a)}closeAll(){const t=[...this.#y.values()];return Promise.all(t.map(t=>{t.forceClose()}))}}(C({prefix:"db-worker",minLevel:_.trace})),Me={connect:t=>Re.handleConnection(t),connectToExisting:({identifier:t,lockName:e})=>Re.connectToExisting(t,e)};if(ve){const t=new Pe;self.onconnect=e=>{e.ports[0].onmessage=e=>{const{service:n,port:s}=e.data;"database"===n?a(Me,s):"sync"===n&&new Oe(t,s)}}}else a(Me);export{St as A,bt as B,B as C,j as D,yt as E,ft as F,lt as G,ut as H,ht as I,wt as J,ot as K,$ as S,X as a,nt as b,J as c,z as d,dt as e,W as f,gt as g,mt as h,pt as i,rt as j,H as k,K as l,V as m,it as n,G as o,tt as p,Z as q,at as r,ct as s,st as t,et as u,Y as v,Q as w,Ct as x,_t as y,vt as z}; //# sourceMappingURL=worker.js.map