@live-state/sync 0.0.7-canary-7 → 0.0.7-pr-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { z as Client, y as ClientEvents, C as ClientOptions, a as ClientRouterConstraint, n as ClientStorageLoadedEvent, m as ConnectionStateChangeEvent, o as DataLoadReplyEvent, D as DataLoadRequestedEvent, M as MessageReceivedEvent, q as MutationReceivedEvent, r as MutationRejectedEvent, p as MutationSentEvent, e as OptimisticHandlerContext, w as OptimisticMutationAppliedEvent, x as OptimisticMutationUndoneEvent, O as OptimisticMutationsConfig, c as OptimisticMutationsRegistry, g as OptimisticOperation, f as OptimisticStorageProxy, Q as QueryExecutedEvent, t as QuerySubscriptionTriggeredEvent, v as StoreStateUpdatedEvent, S as SubscriptionCreatedEvent, s as SubscriptionRemovedEvent, A as createClient, d as defineOptimisticMutations, u as useLiveQuery, l as useLoadData } from './index-LV6LHPwh.js';
1
+ export { B as BootstrapStatusChangeEvent, F as Client, A as ClientBootstrapStatus, E as ClientEvents, C as ClientOptions, a as ClientRouterConstraint, l as ClientState, p as ClientStorageLoadedEvent, o as ConnectionStateChangeEvent, q as DataLoadReplyEvent, D as DataLoadRequestedEvent, M as MessageReceivedEvent, s as MutationReceivedEvent, t as MutationRejectedEvent, r as MutationSentEvent, e as OptimisticHandlerContext, y as OptimisticMutationAppliedEvent, z as OptimisticMutationUndoneEvent, O as OptimisticMutationsConfig, c as OptimisticMutationsRegistry, g as OptimisticOperation, f as OptimisticStorageProxy, Q as QueryExecutedEvent, w as QuerySubscriptionTriggeredEvent, x as StoreStateUpdatedEvent, S as SubscriptionCreatedEvent, v as SubscriptionRemovedEvent, G as createClient, d as defineOptimisticMutations, m as useClientState, u as useLiveQuery, n as useLoadData } from './index-C0Qm5yHg.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import {d,a,b,f as f$1,e,c}from'./chunk-LSAVBBUS.js';import {a as a$1}from'./chunk-RSSRYEM3.js';export{b as defineOptimisticMutations}from'./chunk-RSSRYEM3.js';import {useSyncExternalStore,useEffect}from'react';import {xxHash32}from'js-xxhash';import {z}from'zod';import {stringify}from'qs';import ve from'fast-deep-equal';import {openDB}from'idb';var f=p=>xxHash32(JSON.stringify(p)).toString(32);var S=(p,e,t=false)=>Object.entries(e).every(([i,s])=>{if(i==="$and")return s.every(n=>S(p,n,t));if(i==="$or")return s.some(n=>S(p,n,t));let o=(s==null?void 0:s.$eq)!==void 0?s==null?void 0:s.$eq:s;if(typeof s=="object"&&s!==null&&(s==null?void 0:s.$eq)===void 0){if(s.$in!==void 0){let r=p[i];return r===void 0?false:t?!s.$in.includes(r):s.$in.includes(r)}if(s.$not!==void 0&&!t)return S(p,{[i]:s.$not},true);if(s.$gt!==void 0){let r=p[i];return typeof r!="number"?false:t?r<=s.$gt:r>s.$gt}if(s.$gte!==void 0){let r=p[i];return typeof r!="number"?false:t?r<s.$gte:r>=s.$gte}if(s.$lt!==void 0){let r=p[i];return typeof r!="number"?false:t?r>=s.$lt:r<s.$lt}if(s.$lte!==void 0){let r=p[i];return typeof r!="number"?false:t?r>s.$lte:r<=s.$lte}let n=p[i];return !n||typeof n!="object"&&!Array.isArray(n)?false:Array.isArray(n)?t?!n.some(r=>S(r,s,false)):n.some(r=>S(r,s,false)):S(n,s,t)}return t?p[i]!==o:p[i]===o}),C=p=>{if(typeof p!="object"||p===null)return false;let e=p;return "where"in e||"limit"in e||"orderBy"in e||"include"in e},E={CRITICAL:0,ERROR:1,WARN:2,INFO:3,DEBUG:4},U=class{level;prefix;constructor(e={}){this.level=e.level??E.INFO,this.prefix=e.prefix?`[${e.prefix}] `:"";}critical(...e){this.level>=E.CRITICAL&&console.error(`${this.prefix}[CRITICAL]`,...e);}error(...e){this.level>=E.ERROR&&console.error(`${this.prefix}[ERROR]`,...e);}warn(...e){this.level>=E.WARN&&console.warn(`${this.prefix}[WARN]`,...e);}info(...e){this.level>=E.INFO&&console.log(`${this.prefix}[INFO]`,...e);}debug(...e){this.level>=E.DEBUG&&console.log(`${this.prefix}[DEBUG]`,...e);}setLevel(e){this.level=e;}getLevel(){return this.level}},F=p=>new U(p);var Q=class{subscriptions=new Map;getOrStoreSubscription(e){let t=e.buildQueryRequest(),i=f(t);if(this.subscriptions.has(i))return this.subscriptions.get(i).subscribe;let s={subscribe:o=>{let n=this.subscriptions.get(i);return n.callbacks.add(o),n.unsubscribe||(n.unsubscribe=()=>{},n.unsubscribe=e.subscribe(()=>{n.callbacks.forEach(r=>{r();});})),()=>{var r;(r=this.subscriptions.get(i))==null||r.callbacks.delete(o),setTimeout(()=>{var c;let a=this.subscriptions.get(i);a&&a.callbacks.size===0&&((c=a.unsubscribe)==null||c.call(a),this.subscriptions.delete(i));},10);}},callbacks:new Set,unsubscribe:void 0};return this.subscriptions.set(i,s),this.subscriptions.get(i).subscribe}},ue=new Q,Te=p=>useSyncExternalStore(ue.getOrStoreSubscription(p),p.get),Ce=(p,e)=>{useEffect(()=>{let t=p.load(e.buildQueryRequest());return ()=>{t();}},[e,p.load]);};var J=z.object({resource:z.string(),where:z.record(z.string(),z.any()).optional(),include:z.record(z.string(),z.any()).optional(),lastSyncedAt:z.string().optional(),limit:z.coerce.number().optional(),sort:z.array(z.object({key:z.string(),direction:z.enum(["asc","desc"])})).optional()}),_=z.record(z.string(),z.object({value:z.any().nullable(),_meta:z.object({timestamp:z.string().optional().nullable()}).optional()})),le=_.superRefine((p,e)=>{p.id&&e.addIssue({code:z.ZodIssueCode.custom,message:"Payload cannot have an id"});}),X=z.object({id:z.string().optional(),type:z.literal("MUTATE"),resource:z.string(),resourceId:z.string().optional()}),Z=z.object({timestamp:z.string().optional(),originMutationId:z.string().optional()}).optional(),N=X.extend({procedure:z.string(),payload:z.any().optional(),meta:Z}),W=X.extend({procedure:z.enum(["INSERT","UPDATE"]),payload:le,meta:Z});z.union([W,N]);var ee=z.object({resource:z.string(),procedure:z.string(),input:z.any().optional()});var R=z.string(),q=z.union([ee,J]),de=z.object({id:R,type:z.literal("SUBSCRIBE")}).and(q),pe=z.object({id:R,type:z.literal("UNSUBSCRIBE")}).and(q),he=z.object({id:R,type:z.literal("QUERY")}).and(q),ye=z.object({id:R,type:z.literal("CUSTOM_QUERY"),resource:z.string(),procedure:z.string(),input:z.any().optional()}),te=W.extend({id:R}),me=N.extend({id:R}),ge=z.union([me,te]);z.union([de,he,ye,ge,pe]);var fe=z.object({id:R,type:z.literal("REJECT"),resource:z.string(),message:z.string().optional()}),be=z.object({id:R,type:z.literal("REPLY"),data:z.any()}),ie=z.union([fe,be,te]),se=z.object({resource:z.string(),data:z.array(_)});var x=class{ws=null;url;autoConnect;autoReconnect;reconnectTimeout;reconnectLimit;reconnectAttempts=0;eventListeners=new Map;reconnectTimer=null;intentionallyDisconnected=false;credentials;constructor(e){this.url=e.url,this.autoConnect=e.autoConnect??false,this.autoReconnect=e.autoReconnect??false,this.reconnectTimeout=e.reconnectTimeout??5e3,this.reconnectLimit=e.reconnectLimit,this.credentials=e.credentials,this.autoConnect&&this.connect();}connected(){var e;return ((e=this.ws)==null?void 0:e.readyState)===WebSocket.OPEN}async connect(){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;this.intentionallyDisconnected=false;let e=await c(this.credentials);this.ws=new WebSocket(this.url+(e?`?${stringify(e)}`:"")),this.ws.addEventListener("open",this.handleOpen.bind(this)),this.ws.addEventListener("close",this.handleClose.bind(this)),this.ws.addEventListener("error",this.handleError.bind(this)),this.ws.addEventListener("message",this.handleMessage.bind(this));}disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.intentionallyDisconnected=true,this.ws&&(this.ws.close(),this.ws=null);}addEventListener(e,t){var i;this.eventListeners.has(e)||this.eventListeners.set(e,new Set),(i=this.eventListeners.get(e))==null||i.add(t);}removeEventListener(e,t){var i;this.eventListeners.has(e)&&((i=this.eventListeners.get(e))==null||i.delete(t));}send(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN)this.ws.send(e);else throw new Error("WebSocket is not open")}handleOpen(e){this.reconnectAttempts=0,this.dispatchEvent("open",e),this.dispatchEvent("connectionChange",{open:true});}handleClose(e){this.dispatchEvent("close",e),this.dispatchEvent("connectionChange",{open:false}),this.autoReconnect&&!this.intentionallyDisconnected&&this.scheduleReconnect();}handleError(e){var t,i;this.dispatchEvent("error",e),this.dispatchEvent("connectionChange",{open:false}),(i=(t=e.error)==null?void 0:t.message)!=null&&i.includes("non-101")&&(this.ws&&(this.ws.close(),this.ws=null),this.autoReconnect&&!this.intentionallyDisconnected&&this.scheduleReconnect());}handleMessage(e){this.dispatchEvent("message",e);}scheduleReconnect(){this.reconnectLimit&&this.reconnectAttempts>=this.reconnectLimit||(this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.connect();},this.reconnectTimeout));}dispatchEvent(e,t){var i;(i=this.eventListeners.get(e))==null||i.forEach(s=>{s(t);});}};var L=class{constructor(e){this.logger=e;this.nodes=new Map;}nodes;createNode(e,t,i){if(this.nodes.has(e))throw new Error(`Node with id ${e} already exists`);let s={id:e,type:t,referencedBy:new Map(i.map(o=>[o,new Set])),references:new Map,subscriptions:new Set};return this.nodes.set(e,s),s}getNode(e){return this.nodes.get(e)}hasNode(e){return this.nodes.has(e)}createLink(e,t){let i=this.nodes.get(e),s=this.nodes.get(t);if(!i)throw new Error(`Source node with id ${e} does not exist`);if(!s)throw new Error(`Target node with id ${t} does not exist`);i.references.set(s.type,t);let o=s.referencedBy.get(i.type);o&&o instanceof Set?o.add(e):s.referencedBy.set(i.type,e),this.notifySubscribers(t);}removeLink(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);let s=i.references.get(t);if(!s)return;i.references.delete(t);let o=this.nodes.get(s);if(!o)return;let n=o.referencedBy.get(i.type);n&&(n instanceof Set?n.delete(e):o.referencedBy.delete(i.type),this.notifySubscribers(s)),this.notifySubscribers(e);}subscribe(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);return i.subscriptions.add(t),()=>{i.subscriptions.delete(t);}}removeNode(e){let t=this.nodes.get(e);t&&(Array.from(t.referencedBy.entries()).forEach(([i,s])=>{(s instanceof Set?Array.from(s.values()):[s]).forEach(n=>{let r=this.nodes.get(n);!r||!r.references.get(i)||(r.references.delete(i),this.notifySubscribers(n));});}),this.nodes.delete(e));}updateNode(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);t(i),this.notifySubscribers(e);}notifySubscribers(e){let t=this.nodes.get(e);t&&Array.from(t.subscriptions).forEach(i=>{var s;try{i(e);}catch(o){(s=this.logger)==null||s.error(`Error in node subscription for node ${e}:`,o);}});}getAllNodes(){return Array.from(this.nodes.values())}};var B="__meta",k="databases",j=class{db;async init(e,t){var c,d;if(typeof window>"u")return;let s=((c=(await window.indexedDB.databases()).find(u=>u.name===t))==null?void 0:c.version)??1,o=await f(e),n=Object.fromEntries(await Promise.all(Object.entries(e).map(async([u,l])=>[u,await f(l)]))),r=await openDB("live-state-databases",1,{upgrade(u){u.objectStoreNames.contains(k)||u.createObjectStore(k);}}),a=(d=await this.getAll(r,k))==null?void 0:d[t];(a==null?void 0:a.schemaHash)!==o&&s++,this.db=await openDB(t,s,{async upgrade(u){[...Object.keys(e),B].forEach(l=>{(a==null?void 0:a.objectHashes[l])!==n[l]&&u.objectStoreNames.contains(l)&&u.deleteObjectStore(l),u.objectStoreNames.contains(l)||u.createObjectStore(l);}),await r.put(k,{schemaHash:o,objectHashes:n},t);},blocking(){window.location.reload();},blocked(){window.location.reload();}});}async get(e){return await this.getAll(this.db,e)??{}}getOne(e,t){return this.db?this.db.get(e,t):new Promise(i=>i(void 0))}set(e,t,i){var s;return (s=this.db)==null?void 0:s.put(e,i,t)}delete(e,t){var i;return (i=this.db)==null?void 0:i.delete(e,t)}getMeta(e){return this.db?this.db.get(B,e):new Promise(t=>t(void 0))}setMeta(e,t){var i;return (i=this.db)==null?void 0:i.put(B,t,e)}async getAll(e,t){if(!e)return;if(e.getAllRecords)return e.getAllRecords(t);let[i,s]=await Promise.all([e.getAll(t),e.getAllKeys(t)]);return Object.fromEntries(i.map((o,n)=>[s[n],o]))}};var D=class{constructor(e,t,i,s,o,n){this.schema=e;this.logger=i,this.optimisticObjGraph=new L(i),this.kvStorage=new j,this.onQuerySubscriptionTriggered=n,t!==false&&this.kvStorage.init(this.schema,t.name).then(()=>{Promise.all([this.kvStorage.getMeta("mutationStack"),this.kvStorage.getMeta("customMutationStack"),this.kvStorage.getMeta("customMutationIndex")]).then(([r,a,c])=>{r&&Object.keys(r).length>0&&(this.optimisticMutationStack=r),a&&a.length>0&&(this.customMutationStack=a),c&&Object.keys(c).length>0&&(this.customMutationIndex=c),s==null||s(this.optimisticMutationStack,this.customMutationStack,this.customMutationIndex);}).then(()=>{Object.entries(this.schema).forEach(([r])=>{this.kvStorage.get(r).then(a=>{if(!a||Object.keys(a).length===0){o==null||o(r,0);return}let c=Object.entries(a).map(([d,u])=>({...u,id:{value:d}}));o==null||o(r,c.length),this.loadConsolidatedState(r,c);});});}).catch(r=>{i.debug("Storage initialization failed (may not be available in this environment):",r);});});}rawObjPool={};optimisticMutationStack={};customMutationStack=[];optimisticObjGraph;optimisticRawObjPool={};logger;onQuerySubscriptionTriggered;customMutationIndex={};collectionSubscriptions=new Map;querySnapshots={};kvStorage;get(e$1,t,i=false){var a;let s=t??f(e$1);if(this.querySnapshots[s]&&!i){let c=this.querySnapshots[s];if(c)return c}let o,n=(a=e$1.where)==null?void 0:a.id;n===void 0?o=Object.keys(this.optimisticRawObjPool[e$1.resource]??{}):typeof n=="string"?o=[n]:typeof n=="object"&&n!==null?"$in"in n&&Array.isArray(n.$in)?o=n.$in:"$eq"in n&&typeof n.$eq=="string"?o=[n.$eq]:o=Object.keys(this.optimisticRawObjPool[e$1.resource]??{}):o=Object.keys(this.optimisticRawObjPool[e$1.resource]??{});let r=o.flatMap(c=>{let d=f$1(this.materializeOneWithInclude(c,e$1.include));return d?[d]:[]});if(e$1.sort&&e$1.sort.length>0){let c=(d,u)=>{for(let l of e$1.sort){let m=d[l.key],g=u[l.key];if(m<g)return l.direction==="asc"?-1:1;if(m>g)return l.direction==="asc"?1:-1}return 0};r.sort(c);}if(e$1.where||e$1.limit){let c=e$1.where?d=>S(d,e$1.where):()=>true;r=e(r,c,e$1.limit);}return !i&&this.collectionSubscriptions.has(s)&&(this.querySnapshots[s]=r),r}subscribe(e,t){var o;let i=f(e);return this.collectionSubscriptions.get(i)||this.collectionSubscriptions.set(i,{callbacks:new Set,query:e,flatInclude:e.include?this.flattenIncludes(e.include,e.resource):void 0}),(o=this.collectionSubscriptions.get(i))==null||o.callbacks.add(t),()=>{var n,r;(n=this.collectionSubscriptions.get(i))==null||n.callbacks.delete(t),((r=this.collectionSubscriptions.get(i))==null?void 0:r.callbacks.size)===0&&(this.collectionSubscriptions.delete(i),delete this.querySnapshots[i]);}}addMutation(e,t,i=false){var n,r,a,c,d,u,l;let s=this.schema[e];if(this.logger.debug("Adding mutation",t),!s)throw new Error("Schema not found");let o=(n=this.optimisticRawObjPool[e])==null?void 0:n[t.resourceId];if(i)this.optimisticMutationStack[e]??=[],this.optimisticMutationStack[e].push(t);else {this.optimisticMutationStack[e]=((a=(r=this.optimisticMutationStack)==null?void 0:r[e])==null?void 0:a.filter(I=>I.id!==t.id))??[];let m=(c=t.meta)==null?void 0:c.originMutationId;if(this.logger.debug("Broadcast mutation received",{mutationId:t.id,resource:e,resourceId:t.resourceId,procedure:t.procedure,originMutationId:m??"(none)",customMutationIndexKeys:Object.keys(this.customMutationIndex),optimisticStackSize:((d=this.optimisticMutationStack[e])==null?void 0:d.length)??0}),m&&this.customMutationIndex[m]){let w=this.customMutationIndex[m].filter(M=>M.resource===e),T=false;for(let M of w){let O=(u=this.optimisticMutationStack[e])==null?void 0:u.find(A=>A.id===M.mutationId);if(O&&O.resourceId===t.resourceId&&O.procedure===t.procedure){this.logger.debug("Removing optimistic mutation (resourceId match)",{optimisticMutationId:M.mutationId,resourceId:t.resourceId}),this.undoMutation(e,M.mutationId),T=true;break}}if(!T)for(let M of w){let O=(l=this.optimisticMutationStack[e])==null?void 0:l.find(A=>A.id===M.mutationId&&A.procedure===t.procedure);if(O){this.logger.debug("Removing optimistic mutation (resource+procedure fallback)",{optimisticMutationId:M.mutationId,optimisticResourceId:O.resourceId,broadcastResourceId:t.resourceId}),this.undoMutation(e,M.mutationId),T=true;break}}}this.rawObjPool[e]??={};let g={value:{...this.schema[e].mergeMutation("set",t.payload,this.rawObjPool[e][t.resourceId])[0].value,id:{value:t.resourceId}}};this.rawObjPool[e][t.resourceId]=g;let b=g.value;delete b.id,this.kvStorage.set(e,t.resourceId,b);}this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.updateRawObjPool(e,t.resourceId,t.payload,o);}undoMutation(e,t){var n,r;if(!this.optimisticMutationStack[e])return;let i=(n=this.optimisticMutationStack[e])==null?void 0:n.findIndex(a=>a.id===t);if(i===-1)return;let s=this.optimisticMutationStack[e][i];this.logger.debug("Removing mutation",s);let o=(r=this.optimisticRawObjPool[e])==null?void 0:r[s.resourceId];this.optimisticMutationStack[e].splice(i,1),this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.updateRawObjPool(e,s.resourceId,Object.fromEntries(Object.entries(s.payload).map(([a])=>[a,{value:null,_meta:{}}])),o);}addCustomMutationMessage(e){this.customMutationStack.push(e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack);}registerCustomMutation(e,t){this.customMutationIndex[e]=t,this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex);}confirmCustomMutation(e){var i;let t=this.customMutationIndex[e];if(this.logger.debug("confirmCustomMutation called",{messageId:e,hasIndex:!!t,mutations:t??[]}),!!t){for(let{resource:s,mutationId:o}of t){let n=!!((i=this.optimisticMutationStack[s])!=null&&i.find(r=>r.id===o));this.logger.debug("confirmCustomMutation: undoing mutation",{resource:s,mutationId:o,stillInStack:n}),this.undoMutation(s,o);}delete this.customMutationIndex[e],this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex),this.customMutationStack=this.customMutationStack.filter(s=>s.id!==e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack);}}undoCustomMutation(e){var s;let t=this.customMutationIndex[e];if(!t)return [];let i=[];for(let{resource:o,mutationId:n}of t){let r=(s=this.optimisticMutationStack[o])==null?void 0:s.find(a=>a.id===n);this.undoMutation(o,n),r&&i.push({resource:o,mutationId:n,resourceId:r.resourceId});}return delete this.customMutationIndex[e],this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex),this.customMutationStack=this.customMutationStack.filter(o=>o.id!==e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack),i}getCustomMutationMutationIds(){let e=new Set;for(let t of Object.values(this.customMutationIndex))for(let{mutationId:i}of t)e.add(i);return e}loadConsolidatedState(e,t){t.forEach(i=>{var r;let s=(r=i.id)==null?void 0:r.value;if(!s)return;let{cleanedPayload:o,nestedMutations:n}=this.extractNestedRelations(e,i);n.forEach(a=>{this.addMutation(a.resource,a);}),this.addMutation(e,{id:s,type:"MUTATE",resource:e,resourceId:s,procedure:"INSERT",payload:o});});}extractNestedRelations(e,t){let i=this.schema[e],s={...t},o=[];return i!=null&&i.relations?(Object.entries(t).forEach(([n,r])=>{var u;let a=i.relations[n];if(!a)return;let c=a.entity.name,d=r==null?void 0:r.value;if(a.type==="one"){if(d&&typeof d=="object"&&!Array.isArray(d)&&((u=d.id)!=null&&u.value)){let l=d.id.value,m={...d},{cleanedPayload:g,nestedMutations:b}=this.extractNestedRelations(c,m);o.push(...b),o.push({id:l,type:"MUTATE",resource:c,resourceId:l,procedure:"INSERT",payload:g}),delete s[n];}}else a.type==="many"&&Array.isArray(d)&&(d.forEach(l=>{var m,g;if(l&&typeof l=="object"&&!Array.isArray(l)&&((g=(m=l.value)==null?void 0:m.id)!=null&&g.value)){let b=l.value.id.value,I={...l.value},{cleanedPayload:w,nestedMutations:T}=this.extractNestedRelations(c,I);o.push(...T),o.push({id:b,type:"MUTATE",resource:c,resourceId:b,procedure:"INSERT",payload:w});}}),delete s[n]);}),{cleanedPayload:s,nestedMutations:o}):{cleanedPayload:s,nestedMutations:o}}updateRawObjPool(e,t,i,s){var r;if(!this.schema[e])return;let o=(r=this.rawObjPool[e])==null?void 0:r[t],n=(this.optimisticMutationStack[e]??[]).reduce((a,c)=>c.resourceId!==t?a:this.schema[e].mergeMutation("set",c.payload,a)[0],o);if(this.optimisticRawObjPool[e]??={},n?this.optimisticRawObjPool[e][t]={value:{...n.value,id:{value:t}}}:delete this.optimisticRawObjPool[e][t],!(!this.optimisticObjGraph.hasNode(t)&&!n)){if(this.optimisticObjGraph.hasNode(t)||this.optimisticObjGraph.createNode(t,e,Object.values(this.schema[e].relations).flatMap(a=>a.type==="many"?[a.entity.name]:[])),Object.keys(this.schema[e].relations).length>0){let a=Object.fromEntries(Object.entries(this.schema[e].relations).flatMap(([c,d])=>d.type==="one"?[[d.relationalColumn,c]]:[]));Object.entries(i).forEach(([c,d])=>{let u=this.schema[e].relations[a[c]];if(!a[c])return;let l=s==null?void 0:s.value[c],[,m]=u.mergeMutation("set",d,l);if(m){if(!this.optimisticObjGraph.hasNode(m.value)){let g=u.entity.name;this.optimisticObjGraph.createNode(m.value,g,Object.values(this.schema[g].relations).flatMap(b=>b.type==="many"?[b.entity.name]:[]));}l!=null&&l.value&&this.optimisticObjGraph.removeLink(t,u.entity.name),this.optimisticObjGraph.createLink(t,m.value);}});}this.notifyCollectionSubscribers(e),this.optimisticObjGraph.notifySubscribers(t);}}materializeOneWithInclude(e,t={}){var a;if(!e)return;let i=this.optimisticObjGraph.getNode(e);if(!i)return;let s=i.type,o=(a=this.optimisticRawObjPool[s])==null?void 0:a[e];if(!o)return;let[n,r]=Object.entries(t).reduce((c,[d,u])=>{let l=this.schema[s].relations[d];return l&&(l.type==="one"?c[0].push([d,l.entity.name,u??true]):l.type==="many"&&c[1].push([d,l.entity.name,u??true])),c},[[],[]]);return {value:{...o.value,...Object.fromEntries(n.map(([c,d,u])=>[c,this.materializeOneWithInclude(i.references.get(d),C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{})])),...Object.fromEntries(r.map(([c,d,u])=>{let l=i.referencedBy.get(d),m=l instanceof Set;return [c,m?{value:Array.from(l.values()).map(g=>this.materializeOneWithInclude(g,C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{}))}:this.materializeOneWithInclude(l,C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{})]}))}}}notifyCollectionSubscribers(e){this.collectionSubscriptions.forEach(t=>{var i,s;if(t.query.resource===e||(i=t.flatInclude)!=null&&i.includes(e)){let o=f(t.query),n=this.querySnapshots[o],r=this.get(t.query,void 0,true);if(ve(r,n))return;this.querySnapshots[o]=r,(s=this.onQuerySubscriptionTriggered)==null||s.call(this,t.query),t.callbacks.forEach(a=>{a(r);});}});}flattenIncludes(e,t){let i=[];return Object.entries(e).forEach(([s,o])=>{var a;let n=(a=this.schema[t])==null?void 0:a.relations[s];if(!n)return;let r=n.entity.name;if(i.push(r),typeof o=="object"&&o!==null){let c=C(o)?o.include??{}:o;i.push(...this.flattenIncludes(c,r));}}),Array.from(new Set(i))}};var P=class{constructor(e,t){this.client=e;this.query=t;}buildQueryRequest(){return this.query}then(e,t){return this.client.genericQuery(this.query.resource,this.query.procedure,this.query.input).then(e,t)}},$=class{url;ws;store;logger;optimisticMutations;remoteSubscriptions=new Map;eventListeners=new Set;replyHandlers={};constructor(e){var t,i,s,o;this.url=e.url,this.logger=F({level:e.logLevel??E.INFO}),this.optimisticMutations=e.optimisticMutations,this.store=new D(e.schema,e.storage,this.logger,(n,r,a)=>{var d,u;let c=new Set;if(a)for(let l of Object.values(a))for(let{mutationId:m}of l)c.add(m);(u=(d=Object.values(n))==null?void 0:d.flat())==null||u.forEach(l=>{c.has(l.id)||this.sendWsMessage(l);}),this.replayCustomMutationStack();},(n,r)=>{this.emitEvent({type:"CLIENT_STORAGE_LOADED",resource:n,itemCount:r});},n=>{this.emitEvent({type:"QUERY_SUBSCRIPTION_TRIGGERED",query:n});}),this.ws=new x({url:e.url,autoConnect:((t=e.connection)==null?void 0:t.autoConnect)??true,autoReconnect:((i=e.connection)==null?void 0:i.autoReconnect)??true,reconnectTimeout:((s=e.connection)==null?void 0:s.reconnectTimeout)??5e3,reconnectLimit:(o=e.connection)==null?void 0:o.maxReconnectAttempts,credentials:e.credentials}),this.ws.addEventListener("message",n=>{this.handleServerMessage(n.data);}),this.ws.addEventListener("connectionChange",n=>{if(this.emitEvent({type:"CONNECTION_STATE_CHANGE",open:n.open}),n.open){Array.from(this.remoteSubscriptions.values()).forEach(({query:a})=>{this.sendWsMessage({id:b(),type:"SUBSCRIBE",...a});});let r=this.store.getCustomMutationMutationIds();Object.values(this.store.optimisticMutationStack).forEach(a=>{a&&a.forEach(c=>{r.has(c.id)||(this.emitEvent({type:"MUTATION_SENT",mutationId:c.id,resource:c.resource,resourceId:c.resourceId,procedure:c.procedure??"UNKNOWN",optimistic:true}),this.sendWsMessage(c));});}),this.replayCustomMutationStack();}});}get(e){let t=this.store.get(e);return this.emitEvent({type:"QUERY_EXECUTED",query:e,resultCount:Array.isArray(t)?t.length:t?1:0}),t}handleServerMessage(e){var t,i,s,o;try{this.logger.debug("Message received from the server:",e);let n=ie.parse(JSON.parse(e));if(this.logger.debug("Parsed message:",n),this.emitEvent({type:"MESSAGE_RECEIVED",message:n}),n.type==="MUTATE"){let{resource:r,id:a,resourceId:c,procedure:d}=n;this.emitEvent({type:"MUTATION_RECEIVED",mutationId:a,resource:r,resourceId:c,procedure:d??"UNKNOWN"});try{this.store.addMutation(r,n);}catch(u){this.logger.error("Error merging mutation from the server:",u);}}else if(n.type==="REJECT"){if(this.replyHandlers[n.id]){clearTimeout(this.replyHandlers[n.id].timeoutHandle),this.emitUndoEvents(this.store.undoCustomMutation(n.id));let c=n.message??"Mutation rejected";(i=(t=this.replyHandlers[n.id]).reject)==null||i.call(t,new Error(c)),delete this.replyHandlers[n.id];}let r=((s=this.store.optimisticMutationStack[n.resource])==null?void 0:s.length)??0,a=(o=this.store.optimisticMutationStack[n.resource])==null?void 0:o.find(c=>c.id===n.id);this.store.undoMutation(n.resource,n.id),this.emitEvent({type:"MUTATION_REJECTED",mutationId:n.id,resource:n.resource}),a&&this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:n.id,resource:n.resource,resourceId:a.resourceId,pendingMutations:r-1});}else if(n.type==="REPLY"){let{id:r,data:a}=n;if(this.replyHandlers[r]){clearTimeout(this.replyHandlers[r].timeoutHandle),this.replyHandlers[r].handler(a);return}let c=se.parse(a);this.emitEvent({type:"DATA_LOAD_REPLY",resource:c.resource,itemCount:c.data.length}),this.store.loadConsolidatedState(c.resource,c.data),this.emitEvent({type:"STORE_STATE_UPDATED",resource:c.resource,itemCount:c.data.length});}}catch(n){this.logger.error("Error parsing message from the server:",n);}}load(e){let t=b(),i=f(e);this.emitEvent({type:"DATA_LOAD_REQUESTED",query:e,subscriptionId:t}),this.sendWsMessage({id:t,type:"SUBSCRIBE",...e});let s=!this.remoteSubscriptions.has(i);return this.remoteSubscriptions.has(i)?this.remoteSubscriptions.get(i).subCounter+=1:this.remoteSubscriptions.set(i,{query:e,subCounter:1}),s&&this.emitEvent({type:"SUBSCRIPTION_CREATED",query:e,subscriptionKey:i,subscriberCount:1}),()=>{if(this.remoteSubscriptions.has(i)){let o=this.remoteSubscriptions.get(i);o.subCounter-=1,this.remoteSubscriptions.get(i).subCounter<=0&&(this.remoteSubscriptions.delete(i),this.sendWsMessage({id:b(),type:"UNSUBSCRIBE",...e}),this.emitEvent({type:"SUBSCRIPTION_REMOVED",query:e,subscriptionKey:i}));}}}subscribe(e,t){return this.store.subscribe(e,t)}mutate(e,t,i,s){var r,a;let o={id:b(),type:"MUTATE",resource:e,payload:this.store.schema[e].encodeMutation("set",s,new Date().toISOString()),resourceId:t,procedure:i},n=(((r=this.store.optimisticMutationStack[e])==null?void 0:r.length)??0)+1;(a=this.store)==null||a.addMutation(e,o,true),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:o.id,resource:e,resourceId:t,procedure:i,pendingMutations:n}),this.emitEvent({type:"MUTATION_SENT",mutationId:o.id,resource:e,resourceId:t,procedure:i,optimistic:true}),this.sendWsMessage(o);}genericMutate(e,t,i){var r,a;let s=(r=this.ws)==null?void 0:r.connected(),o=(a=this.optimisticMutations)==null?void 0:a.getHandler(e,t);if(!s&&!o)throw new Error("WebSocket not connected");let n={id:b(),type:"MUTATE",resource:e,procedure:t,payload:i,meta:{timestamp:new Date().toISOString()}};if(o)try{let{proxy:c,getOperations:d}=a$1(this.store,this.store.schema);o({input:i,storage:c});let u=d(),l=this.applyOptimisticOperations(u);this.store.registerCustomMutation(n.id,l),this.emitEvent({type:"MUTATION_SENT",mutationId:n.id,resource:e,resourceId:"",procedure:t,optimistic:!0});}catch(c){throw this.logger.error("Error executing optimistic handler:",c),this.emitUndoEvents(this.store.undoCustomMutation(n.id)),c}else this.emitEvent({type:"MUTATION_SENT",mutationId:n.id,resource:e,resourceId:"",procedure:t,optimistic:false});return s?(this.sendWsMessage(n),new Promise((c,d)=>{this.replyHandlers[n.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[n.id],this.emitUndoEvents(this.store.undoCustomMutation(n.id)),d(new Error("Reply timeout"));},5e3),handler:u=>{delete this.replyHandlers[n.id],this.store.confirmCustomMutation(n.id),c(u);},reject:d};})):(this.store.addCustomMutationMessage(n),Promise.resolve(void 0))}applyOptimisticOperations(e){var i;let t=[];try{for(let s of e){let o=b(),n=new Date().toISOString(),r={id:o,type:"MUTATE",resource:s.resource,resourceId:s.id,procedure:s.type==="insert"?"INSERT":"UPDATE",payload:this.store.schema[s.resource].encodeMutation("set",s.data,n)},a=(((i=this.store.optimisticMutationStack[s.resource])==null?void 0:i.length)??0)+1;this.store.addMutation(s.resource,r,!0),t.push({resource:s.resource,mutationId:o}),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:o,resource:s.resource,resourceId:s.id,procedure:s.type==="insert"?"INSERT":"UPDATE",pendingMutations:a});}return t}catch(s){for(let{resource:o,mutationId:n}of t)this.store.undoMutation(o,n);throw s}}emitUndoEvents(e){var t;for(let{resource:i,mutationId:s,resourceId:o}of e){let n=((t=this.store.optimisticMutationStack[i])==null?void 0:t.length)??0;this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:s,resource:i,resourceId:o,pendingMutations:n});}}genericQuery(e,t,i){if(!this.ws||!this.ws.connected())throw new Error("WebSocket not connected");let s={id:b(),type:"CUSTOM_QUERY",resource:e,procedure:t,input:i};return this.sendWsMessage(s),new Promise((o,n)=>{this.replyHandlers[s.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[s.id],n(new Error("Reply timeout"));},5e3),handler:r=>{delete this.replyHandlers[s.id],o(r);},reject:n};})}addEventListener(e){return this.eventListeners.add(e),()=>{this.eventListeners.delete(e);}}replayCustomMutationStack(){var e;if((e=this.ws)!=null&&e.connected())for(let t of this.store.customMutationStack)this.sendWsMessage(t),!this.replyHandlers[t.id]&&(this.replyHandlers[t.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[t.id],this.emitUndoEvents(this.store.undoCustomMutation(t.id));},5e3),handler:()=>{delete this.replyHandlers[t.id],this.store.confirmCustomMutation(t.id);}});}sendWsMessage(e){var t;(t=this.ws)!=null&&t.connected()&&this.ws.send(JSON.stringify(e));}emitEvent(e){this.eventListeners.forEach(t=>{t(e);});}},st=p=>{let e=new $(p),t=(i,s)=>new Proxy(s,{get(o,n,r){if(n in o)return Reflect.get(o,n,r);if(typeof n=="string")return a=>new P(e,{resource:i,procedure:n,input:a})}});return {client:{ws:e.ws,load:i=>e.load(i),addEventListener:i=>e.addEventListener(i)},store:{query:new Proxy({},{get(i,s){if(typeof s=="string")return Object.hasOwn(p.schema,s)?t(s,a._init(p.schema[s],e)):new Proxy({},{get(o,n){if(typeof n=="string")return r=>new P(e,{resource:s,procedure:n,input:r})}})},has(i,s){return typeof s=="string"}}),mutate:d(()=>{},{apply:(i,s,o)=>{if(s.length<2)return;if(s.length>2)throw new Error("Trying to access an invalid path");let[n,r]=s;if(r==="insert"){let{id:a,...c}=o[0];return e.mutate(n,a,"INSERT",c)}if(r==="update"){let[a,c]=o;return e.mutate(n,a,"UPDATE",c)}return e.genericMutate(n,r,o[0])}})}}};export{st as createClient,Te as useLiveQuery,Ce as useLoadData};
1
+ import {d,a,b,f as f$1,e,c}from'./chunk-LSAVBBUS.js';import {a as a$1}from'./chunk-RSSRYEM3.js';export{b as defineOptimisticMutations}from'./chunk-RSSRYEM3.js';import {useSyncExternalStore,useMemo,useEffect}from'react';import {xxHash32}from'js-xxhash';import {z}from'zod';import {stringify}from'qs';import Te from'fast-deep-equal';import {openDB}from'idb';var f=l=>xxHash32(JSON.stringify(l)).toString(32);var v=(l,e,t=false)=>Object.entries(e).every(([i,s])=>{if(i==="$and")return s.every(n=>v(l,n,t));if(i==="$or")return s.some(n=>v(l,n,t));let r=(s==null?void 0:s.$eq)!==void 0?s==null?void 0:s.$eq:s;if(typeof s=="object"&&s!==null&&(s==null?void 0:s.$eq)===void 0){if(s.$in!==void 0){let o=l[i];return o===void 0?false:t?!s.$in.includes(o):s.$in.includes(o)}if(s.$not!==void 0&&!t)return v(l,{[i]:s.$not},true);if(s.$gt!==void 0){let o=l[i];return typeof o!="number"?false:t?o<=s.$gt:o>s.$gt}if(s.$gte!==void 0){let o=l[i];return typeof o!="number"?false:t?o<s.$gte:o>=s.$gte}if(s.$lt!==void 0){let o=l[i];return typeof o!="number"?false:t?o>=s.$lt:o<s.$lt}if(s.$lte!==void 0){let o=l[i];return typeof o!="number"?false:t?o>s.$lte:o<=s.$lte}let n=l[i];return !n||typeof n!="object"&&!Array.isArray(n)?false:Array.isArray(n)?t?!n.some(o=>v(o,s,false)):n.some(o=>v(o,s,false)):v(n,s,t)}return t?l[i]!==r:l[i]===r}),C=l=>{if(typeof l!="object"||l===null)return false;let e=l;return "where"in e||"limit"in e||"orderBy"in e||"include"in e},E={CRITICAL:0,ERROR:1,WARN:2,INFO:3,DEBUG:4},U=class{level;prefix;constructor(e={}){this.level=e.level??E.INFO,this.prefix=e.prefix?`[${e.prefix}] `:"";}critical(...e){this.level>=E.CRITICAL&&console.error(`${this.prefix}[CRITICAL]`,...e);}error(...e){this.level>=E.ERROR&&console.error(`${this.prefix}[ERROR]`,...e);}warn(...e){this.level>=E.WARN&&console.warn(`${this.prefix}[WARN]`,...e);}info(...e){this.level>=E.INFO&&console.log(`${this.prefix}[INFO]`,...e);}debug(...e){this.level>=E.DEBUG&&console.log(`${this.prefix}[DEBUG]`,...e);}setLevel(e){this.level=e;}getLevel(){return this.level}},F=l=>new U(l);var _=class{subscriptions=new Map;getOrStoreSubscription(e){let t=e.buildQueryRequest(),i=f(t);if(this.subscriptions.has(i))return this.subscriptions.get(i).subscribe;let s={subscribe:r=>{let n=this.subscriptions.get(i);return n.callbacks.add(r),n.unsubscribe||(n.unsubscribe=()=>{},n.unsubscribe=e.subscribe(()=>{n.callbacks.forEach(o=>{o();});})),()=>{var o;(o=this.subscriptions.get(i))==null||o.callbacks.delete(r),setTimeout(()=>{var c;let a=this.subscriptions.get(i);a&&a.callbacks.size===0&&((c=a.unsubscribe)==null||c.call(a),this.subscriptions.delete(i));},10);}},callbacks:new Set,unsubscribe:void 0};return this.subscriptions.set(i,s),this.subscriptions.get(i).subscribe}},pe=new _,we=l=>useSyncExternalStore(pe.getOrStoreSubscription(l),l.get),Ae=l=>{let{subscribe:e,getSnapshot:t}=useMemo(()=>{let i={bootstrapStatus:l.bootstrapStatus,connected:l.ws.connected()},s=()=>{let r={bootstrapStatus:l.bootstrapStatus,connected:l.ws.connected()};(r.bootstrapStatus!==i.bootstrapStatus||r.connected!==i.connected)&&(i=r);};return {subscribe:r=>l.addEventListener(n=>{(n.type==="BOOTSTRAP_STATUS_CHANGE"||n.type==="CONNECTION_STATE_CHANGE")&&(s(),r());}),getSnapshot:()=>i}},[l]);return useSyncExternalStore(e,t,t)},xe=(l,e)=>{useEffect(()=>{let t=l.load(e.buildQueryRequest());return ()=>{t();}},[e,l.load]);};var X=z.object({resource:z.string(),where:z.record(z.string(),z.any()).optional(),include:z.record(z.string(),z.any()).optional(),lastSyncedAt:z.string().optional(),limit:z.coerce.number().optional(),sort:z.array(z.object({key:z.string(),direction:z.enum(["asc","desc"])})).optional()}),Q=z.record(z.string(),z.object({value:z.any().nullable(),_meta:z.object({timestamp:z.string().optional().nullable()}).optional()})),he=Q.superRefine((l,e)=>{l.id&&e.addIssue({code:z.ZodIssueCode.custom,message:"Payload cannot have an id"});}),Z=z.object({id:z.string().optional(),type:z.literal("MUTATE"),resource:z.string(),resourceId:z.string().optional()}),ee=z.object({timestamp:z.string().optional(),originMutationId:z.string().optional()}).optional(),N=Z.extend({procedure:z.string(),payload:z.any().optional(),meta:ee}),B=Z.extend({procedure:z.enum(["INSERT","UPDATE"]),payload:he,meta:ee});z.union([B,N]);var te=z.object({resource:z.string(),procedure:z.string(),input:z.any().optional()});var T=z.string(),W=z.union([te,X]),ye=z.object({id:T,type:z.literal("SUBSCRIBE")}).and(W),me=z.object({id:T,type:z.literal("UNSUBSCRIBE")}).and(W),ge=z.object({id:T,type:z.literal("QUERY")}).and(W),fe=z.object({id:T,type:z.literal("CUSTOM_QUERY"),resource:z.string(),procedure:z.string(),input:z.any().optional()}),ie=B.extend({id:T}),be=N.extend({id:T}),Se=z.union([be,ie]);z.union([ye,ge,fe,Se,me]);var Me=z.object({id:T,type:z.literal("REJECT"),resource:z.string(),message:z.string().optional()}),ve=z.object({id:T,type:z.literal("REPLY"),data:z.any()}),se=z.union([Me,ve,ie]),ne=z.object({resource:z.string(),data:z.array(Q)});var x=class{ws=null;url;autoConnect;autoReconnect;reconnectTimeout;reconnectLimit;reconnectAttempts=0;eventListeners=new Map;reconnectTimer=null;intentionallyDisconnected=false;credentials;constructor(e){this.url=e.url,this.autoConnect=e.autoConnect??false,this.autoReconnect=e.autoReconnect??false,this.reconnectTimeout=e.reconnectTimeout??5e3,this.reconnectLimit=e.reconnectLimit,this.credentials=e.credentials,this.autoConnect&&this.connect();}connected(){var e;return ((e=this.ws)==null?void 0:e.readyState)===WebSocket.OPEN}async connect(){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;this.intentionallyDisconnected=false;let e=await c(this.credentials);this.ws=new WebSocket(this.url+(e?`?${stringify(e)}`:"")),this.ws.addEventListener("open",this.handleOpen.bind(this)),this.ws.addEventListener("close",this.handleClose.bind(this)),this.ws.addEventListener("error",this.handleError.bind(this)),this.ws.addEventListener("message",this.handleMessage.bind(this));}disconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.intentionallyDisconnected=true,this.ws&&(this.ws.close(),this.ws=null);}addEventListener(e,t){var i;this.eventListeners.has(e)||this.eventListeners.set(e,new Set),(i=this.eventListeners.get(e))==null||i.add(t);}removeEventListener(e,t){var i;this.eventListeners.has(e)&&((i=this.eventListeners.get(e))==null||i.delete(t));}send(e){if(this.ws&&this.ws.readyState===WebSocket.OPEN)this.ws.send(e);else throw new Error("WebSocket is not open")}handleOpen(e){this.reconnectAttempts=0,this.dispatchEvent("open",e),this.dispatchEvent("connectionChange",{open:true});}handleClose(e){this.dispatchEvent("close",e),this.dispatchEvent("connectionChange",{open:false}),this.autoReconnect&&!this.intentionallyDisconnected&&this.scheduleReconnect();}handleError(e){var t,i;this.dispatchEvent("error",e),this.dispatchEvent("connectionChange",{open:false}),(i=(t=e.error)==null?void 0:t.message)!=null&&i.includes("non-101")&&(this.ws&&(this.ws.close(),this.ws=null),this.autoReconnect&&!this.intentionallyDisconnected&&this.scheduleReconnect());}handleMessage(e){this.dispatchEvent("message",e);}scheduleReconnect(){this.reconnectLimit&&this.reconnectAttempts>=this.reconnectLimit||(this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.connect();},this.reconnectTimeout));}dispatchEvent(e,t){var i;(i=this.eventListeners.get(e))==null||i.forEach(s=>{s(t);});}};var k=class{constructor(e){this.logger=e;this.nodes=new Map;}nodes;createNode(e,t,i){if(this.nodes.has(e))throw new Error(`Node with id ${e} already exists`);let s={id:e,type:t,referencedBy:new Map(i.map(r=>[r,new Set])),references:new Map,subscriptions:new Set};return this.nodes.set(e,s),s}getNode(e){return this.nodes.get(e)}hasNode(e){return this.nodes.has(e)}createLink(e,t){let i=this.nodes.get(e),s=this.nodes.get(t);if(!i)throw new Error(`Source node with id ${e} does not exist`);if(!s)throw new Error(`Target node with id ${t} does not exist`);i.references.set(s.type,t);let r=s.referencedBy.get(i.type);r&&r instanceof Set?r.add(e):s.referencedBy.set(i.type,e),this.notifySubscribers(t);}removeLink(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);let s=i.references.get(t);if(!s)return;i.references.delete(t);let r=this.nodes.get(s);if(!r)return;let n=r.referencedBy.get(i.type);n&&(n instanceof Set?n.delete(e):r.referencedBy.delete(i.type),this.notifySubscribers(s)),this.notifySubscribers(e);}subscribe(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);return i.subscriptions.add(t),()=>{i.subscriptions.delete(t);}}removeNode(e){let t=this.nodes.get(e);t&&(Array.from(t.referencedBy.entries()).forEach(([i,s])=>{(s instanceof Set?Array.from(s.values()):[s]).forEach(n=>{let o=this.nodes.get(n);!o||!o.references.get(i)||(o.references.delete(i),this.notifySubscribers(n));});}),this.nodes.delete(e));}updateNode(e,t){let i=this.nodes.get(e);if(!i)throw new Error(`Node with id ${e} does not exist`);t(i),this.notifySubscribers(e);}notifySubscribers(e){let t=this.nodes.get(e);t&&Array.from(t.subscriptions).forEach(i=>{var s;try{i(e);}catch(r){(s=this.logger)==null||s.error(`Error in node subscription for node ${e}:`,r);}});}getAllNodes(){return Array.from(this.nodes.values())}};var q="__meta",j="databases",L=class{db;async init(e,t){var c,p;if(typeof window>"u")return;let s=((c=(await window.indexedDB.databases()).find(u=>u.name===t))==null?void 0:c.version)??1,r=await f(e),n=Object.fromEntries(await Promise.all(Object.entries(e).map(async([u,d])=>[u,await f(d)]))),o=await openDB("live-state-databases",1,{upgrade(u){u.objectStoreNames.contains(j)||u.createObjectStore(j);}}),a=(p=await this.getAll(o,j))==null?void 0:p[t];(a==null?void 0:a.schemaHash)!==r&&s++,this.db=await openDB(t,s,{async upgrade(u){[...Object.keys(e),q].forEach(d=>{(a==null?void 0:a.objectHashes[d])!==n[d]&&u.objectStoreNames.contains(d)&&u.deleteObjectStore(d),u.objectStoreNames.contains(d)||u.createObjectStore(d);}),await o.put(j,{schemaHash:r,objectHashes:n},t);},blocking(){window.location.reload();},blocked(){window.location.reload();}});}async get(e){return await this.getAll(this.db,e)??{}}getOne(e,t){return this.db?this.db.get(e,t):new Promise(i=>i(void 0))}set(e,t,i){var s;return (s=this.db)==null?void 0:s.put(e,i,t)}delete(e,t){var i;return (i=this.db)==null?void 0:i.delete(e,t)}getMeta(e){return this.db?this.db.get(q,e):new Promise(t=>t(void 0))}setMeta(e,t){var i;return (i=this.db)==null?void 0:i.put(q,t,e)}async getAll(e,t){if(!e)return;if(e.getAllRecords)return e.getAllRecords(t);let[i,s]=await Promise.all([e.getAll(t),e.getAllKeys(t)]);return Object.fromEntries(i.map((r,n)=>[s[n],r]))}};var P=class{constructor(e,t,i,s,r,n){this.schema=e;this.logger=i,this.optimisticObjGraph=new k(i),this.kvStorage=new L,this.onQuerySubscriptionTriggered=n,t!==false&&this.kvStorage.init(this.schema,t.name).then(()=>{Promise.all([this.kvStorage.getMeta("mutationStack"),this.kvStorage.getMeta("customMutationStack"),this.kvStorage.getMeta("customMutationIndex")]).then(([o,a,c])=>{o&&Object.keys(o).length>0&&(this.optimisticMutationStack=o),a&&a.length>0&&(this.customMutationStack=a),c&&Object.keys(c).length>0&&(this.customMutationIndex=c),s==null||s(this.optimisticMutationStack,this.customMutationStack,this.customMutationIndex);}).then(()=>{Object.entries(this.schema).forEach(([o])=>{this.kvStorage.get(o).then(a=>{if(!a||Object.keys(a).length===0){r==null||r(o,0);return}let c=Object.entries(a).map(([p,u])=>({...u,id:{value:p}}));r==null||r(o,c.length),this.loadConsolidatedState(o,c);});});}).catch(o=>{i.debug("Storage initialization failed (may not be available in this environment):",o);});});}rawObjPool={};optimisticMutationStack={};customMutationStack=[];optimisticObjGraph;optimisticRawObjPool={};logger;onQuerySubscriptionTriggered;customMutationIndex={};collectionSubscriptions=new Map;querySnapshots={};kvStorage;get(e$1,t,i=false){var a;let s=t??f(e$1);if(this.querySnapshots[s]&&!i){let c=this.querySnapshots[s];if(c)return c}let r,n=(a=e$1.where)==null?void 0:a.id;n===void 0?r=Object.keys(this.optimisticRawObjPool[e$1.resource]??{}):typeof n=="string"?r=[n]:typeof n=="object"&&n!==null?"$in"in n&&Array.isArray(n.$in)?r=n.$in:"$eq"in n&&typeof n.$eq=="string"?r=[n.$eq]:r=Object.keys(this.optimisticRawObjPool[e$1.resource]??{}):r=Object.keys(this.optimisticRawObjPool[e$1.resource]??{});let o=r.flatMap(c=>{let p=f$1(this.materializeOneWithInclude(c,e$1.include));return p?[p]:[]});if(e$1.sort&&e$1.sort.length>0){let c=(p,u)=>{for(let d of e$1.sort){let m=p[d.key],g=u[d.key];if(m<g)return d.direction==="asc"?-1:1;if(m>g)return d.direction==="asc"?1:-1}return 0};o.sort(c);}if(e$1.where||e$1.limit){let c=e$1.where?p=>v(p,e$1.where):()=>true;o=e(o,c,e$1.limit);}return !i&&this.collectionSubscriptions.has(s)&&(this.querySnapshots[s]=o),o}subscribe(e,t){var r;let i=f(e);return this.collectionSubscriptions.get(i)||this.collectionSubscriptions.set(i,{callbacks:new Set,query:e,flatInclude:e.include?this.flattenIncludes(e.include,e.resource):void 0}),(r=this.collectionSubscriptions.get(i))==null||r.callbacks.add(t),()=>{var n,o;(n=this.collectionSubscriptions.get(i))==null||n.callbacks.delete(t),((o=this.collectionSubscriptions.get(i))==null?void 0:o.callbacks.size)===0&&(this.collectionSubscriptions.delete(i),delete this.querySnapshots[i]);}}addMutation(e,t,i=false){var n,o,a,c,p,u,d;let s=this.schema[e];if(this.logger.debug("Adding mutation",t),!s)throw new Error("Schema not found");let r=(n=this.optimisticRawObjPool[e])==null?void 0:n[t.resourceId];if(i)this.optimisticMutationStack[e]??=[],this.optimisticMutationStack[e].push(t);else {this.optimisticMutationStack[e]=((a=(o=this.optimisticMutationStack)==null?void 0:o[e])==null?void 0:a.filter(I=>I.id!==t.id))??[];let m=(c=t.meta)==null?void 0:c.originMutationId;if(this.logger.debug("Broadcast mutation received",{mutationId:t.id,resource:e,resourceId:t.resourceId,procedure:t.procedure,originMutationId:m??"(none)",customMutationIndexKeys:Object.keys(this.customMutationIndex),optimisticStackSize:((p=this.optimisticMutationStack[e])==null?void 0:p.length)??0}),m&&this.customMutationIndex[m]){let w=this.customMutationIndex[m].filter(S=>S.resource===e),R=false;for(let S of w){let O=(u=this.optimisticMutationStack[e])==null?void 0:u.find(A=>A.id===S.mutationId);if(O&&O.resourceId===t.resourceId&&O.procedure===t.procedure){this.logger.debug("Removing optimistic mutation (resourceId match)",{optimisticMutationId:S.mutationId,resourceId:t.resourceId}),this.undoMutation(e,S.mutationId),R=true;break}}if(!R)for(let S of w){let O=(d=this.optimisticMutationStack[e])==null?void 0:d.find(A=>A.id===S.mutationId&&A.procedure===t.procedure);if(O){this.logger.debug("Removing optimistic mutation (resource+procedure fallback)",{optimisticMutationId:S.mutationId,optimisticResourceId:O.resourceId,broadcastResourceId:t.resourceId}),this.undoMutation(e,S.mutationId),R=true;break}}}this.rawObjPool[e]??={};let g={value:{...this.schema[e].mergeMutation("set",t.payload,this.rawObjPool[e][t.resourceId])[0].value,id:{value:t.resourceId}}};this.rawObjPool[e][t.resourceId]=g;let b=g.value;delete b.id,this.kvStorage.set(e,t.resourceId,b);}this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.updateRawObjPool(e,t.resourceId,t.payload,r);}undoMutation(e,t){var n,o;if(!this.optimisticMutationStack[e])return;let i=(n=this.optimisticMutationStack[e])==null?void 0:n.findIndex(a=>a.id===t);if(i===-1)return;let s=this.optimisticMutationStack[e][i];this.logger.debug("Removing mutation",s);let r=(o=this.optimisticRawObjPool[e])==null?void 0:o[s.resourceId];this.optimisticMutationStack[e].splice(i,1),this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.updateRawObjPool(e,s.resourceId,Object.fromEntries(Object.entries(s.payload).map(([a])=>[a,{value:null,_meta:{}}])),r);}addCustomMutationMessage(e){this.customMutationStack.push(e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack);}registerCustomMutation(e,t){this.customMutationIndex[e]=t,this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex);}confirmCustomMutation(e){var i;let t=this.customMutationIndex[e];if(this.logger.debug("confirmCustomMutation called",{messageId:e,hasIndex:!!t,mutations:t??[]}),!!t){for(let{resource:s,mutationId:r}of t){let n=!!((i=this.optimisticMutationStack[s])!=null&&i.find(o=>o.id===r));this.logger.debug("confirmCustomMutation: undoing mutation",{resource:s,mutationId:r,stillInStack:n}),this.undoMutation(s,r);}delete this.customMutationIndex[e],this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex),this.customMutationStack=this.customMutationStack.filter(s=>s.id!==e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack);}}undoCustomMutation(e){var s;let t=this.customMutationIndex[e];if(!t)return [];let i=[];for(let{resource:r,mutationId:n}of t){let o=(s=this.optimisticMutationStack[r])==null?void 0:s.find(a=>a.id===n);this.undoMutation(r,n),o&&i.push({resource:r,mutationId:n,resourceId:o.resourceId});}return delete this.customMutationIndex[e],this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex),this.customMutationStack=this.customMutationStack.filter(r=>r.id!==e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack),i}getCustomMutationMutationIds(){let e=new Set;for(let t of Object.values(this.customMutationIndex))for(let{mutationId:i}of t)e.add(i);return e}loadConsolidatedState(e,t){t.forEach(i=>{var o;let s=(o=i.id)==null?void 0:o.value;if(!s)return;let{cleanedPayload:r,nestedMutations:n}=this.extractNestedRelations(e,i);n.forEach(a=>{this.addMutation(a.resource,a);}),this.addMutation(e,{id:s,type:"MUTATE",resource:e,resourceId:s,procedure:"INSERT",payload:r});});}extractNestedRelations(e,t){let i=this.schema[e],s={...t},r=[];return i!=null&&i.relations?(Object.entries(t).forEach(([n,o])=>{var u;let a=i.relations[n];if(!a)return;let c=a.entity.name,p=o==null?void 0:o.value;if(a.type==="one"){if(p&&typeof p=="object"&&!Array.isArray(p)&&((u=p.id)!=null&&u.value)){let d=p.id.value,m={...p},{cleanedPayload:g,nestedMutations:b}=this.extractNestedRelations(c,m);r.push(...b),r.push({id:d,type:"MUTATE",resource:c,resourceId:d,procedure:"INSERT",payload:g}),delete s[n];}}else a.type==="many"&&Array.isArray(p)&&(p.forEach(d=>{var m,g;if(d&&typeof d=="object"&&!Array.isArray(d)&&((g=(m=d.value)==null?void 0:m.id)!=null&&g.value)){let b=d.value.id.value,I={...d.value},{cleanedPayload:w,nestedMutations:R}=this.extractNestedRelations(c,I);r.push(...R),r.push({id:b,type:"MUTATE",resource:c,resourceId:b,procedure:"INSERT",payload:w});}}),delete s[n]);}),{cleanedPayload:s,nestedMutations:r}):{cleanedPayload:s,nestedMutations:r}}updateRawObjPool(e,t,i,s){var o;if(!this.schema[e])return;let r=(o=this.rawObjPool[e])==null?void 0:o[t],n=(this.optimisticMutationStack[e]??[]).reduce((a,c)=>c.resourceId!==t?a:this.schema[e].mergeMutation("set",c.payload,a)[0],r);if(this.optimisticRawObjPool[e]??={},n?this.optimisticRawObjPool[e][t]={value:{...n.value,id:{value:t}}}:delete this.optimisticRawObjPool[e][t],!(!this.optimisticObjGraph.hasNode(t)&&!n)){if(this.optimisticObjGraph.hasNode(t)||this.optimisticObjGraph.createNode(t,e,Object.values(this.schema[e].relations).flatMap(a=>a.type==="many"?[a.entity.name]:[])),Object.keys(this.schema[e].relations).length>0){let a=Object.fromEntries(Object.entries(this.schema[e].relations).flatMap(([c,p])=>p.type==="one"?[[p.relationalColumn,c]]:[]));Object.entries(i).forEach(([c,p])=>{let u=this.schema[e].relations[a[c]];if(!a[c])return;let d=s==null?void 0:s.value[c],[,m]=u.mergeMutation("set",p,d);if(m){if(!this.optimisticObjGraph.hasNode(m.value)){let g=u.entity.name;this.optimisticObjGraph.createNode(m.value,g,Object.values(this.schema[g].relations).flatMap(b=>b.type==="many"?[b.entity.name]:[]));}d!=null&&d.value&&this.optimisticObjGraph.removeLink(t,u.entity.name),this.optimisticObjGraph.createLink(t,m.value);}});}this.notifyCollectionSubscribers(e),this.optimisticObjGraph.notifySubscribers(t);}}materializeOneWithInclude(e,t={}){var a;if(!e)return;let i=this.optimisticObjGraph.getNode(e);if(!i)return;let s=i.type,r=(a=this.optimisticRawObjPool[s])==null?void 0:a[e];if(!r)return;let[n,o]=Object.entries(t).reduce((c,[p,u])=>{let d=this.schema[s].relations[p];return d&&(d.type==="one"?c[0].push([p,d.entity.name,u??true]):d.type==="many"&&c[1].push([p,d.entity.name,u??true])),c},[[],[]]);return {value:{...r.value,...Object.fromEntries(n.map(([c,p,u])=>[c,this.materializeOneWithInclude(i.references.get(p),C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{})])),...Object.fromEntries(o.map(([c,p,u])=>{let d=i.referencedBy.get(p),m=d instanceof Set;return [c,m?{value:Array.from(d.values()).map(g=>this.materializeOneWithInclude(g,C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{}))}:this.materializeOneWithInclude(d,C(u)?u.include??{}:typeof u=="object"&&u!==null?u:{})]}))}}}notifyCollectionSubscribers(e){this.collectionSubscriptions.forEach(t=>{var i,s;if(t.query.resource===e||(i=t.flatInclude)!=null&&i.includes(e)){let r=f(t.query),n=this.querySnapshots[r],o=this.get(t.query,void 0,true);if(Te(o,n))return;this.querySnapshots[r]=o,(s=this.onQuerySubscriptionTriggered)==null||s.call(this,t.query),t.callbacks.forEach(a=>{a(o);});}});}flattenIncludes(e,t){let i=[];return Object.entries(e).forEach(([s,r])=>{var a;let n=(a=this.schema[t])==null?void 0:a.relations[s];if(!n)return;let o=n.entity.name;if(i.push(o),typeof r=="object"&&r!==null){let c=C(r)?r.include??{}:r;i.push(...this.flattenIncludes(c,o));}}),Array.from(new Set(i))}};var oe=l=>{if(l instanceof Error&&l.message.includes("Unknown procedure"))return true;if(l instanceof Error&&typeof l.cause=="object"&&l.cause!==null&&"message"in l.cause){let e=l.cause.message;return typeof e=="string"&&e.includes("Unknown procedure")}return false},ae={pending:0,local:1,remote:2},D=class{constructor(e,t){this.client=e;this.query=t;}buildQueryRequest(){return this.query}then(e,t){return this.client.genericQuery(this.query.resource,this.query.procedure,this.query.input).then(e,t)}},$=class{url;ws;store;logger;optimisticMutations;remoteSubscriptions=new Map;eventListeners=new Set;replyHandlers={};_bootstrapStatus="pending";storageLoadedCount=0;expectedStorageLoads;constructor(e){var t,i,s,r;this.url=e.url,this.logger=F({level:e.logLevel??E.INFO}),this.optimisticMutations=e.optimisticMutations,this.expectedStorageLoads=e.storage===false?0:Object.keys(e.schema).length,this.store=new P(e.schema,e.storage,this.logger,(n,o,a)=>{var p,u;let c=new Set;if(a)for(let d of Object.values(a))for(let{mutationId:m}of d)c.add(m);(u=(p=Object.values(n))==null?void 0:p.flat())==null||u.forEach(d=>{c.has(d.id)||this.sendWsMessage(d);}),this.replayCustomMutationStack();},(n,o)=>{this.emitEvent({type:"CLIENT_STORAGE_LOADED",resource:n,itemCount:o}),this.storageLoadedCount+=1,this.expectedStorageLoads>0&&this.storageLoadedCount>=this.expectedStorageLoads&&this.setBootstrapStatus("local");},n=>{this.emitEvent({type:"QUERY_SUBSCRIPTION_TRIGGERED",query:n});}),this.ws=new x({url:e.url,autoConnect:((t=e.connection)==null?void 0:t.autoConnect)??true,autoReconnect:((i=e.connection)==null?void 0:i.autoReconnect)??true,reconnectTimeout:((s=e.connection)==null?void 0:s.reconnectTimeout)??5e3,reconnectLimit:(r=e.connection)==null?void 0:r.maxReconnectAttempts,credentials:e.credentials}),this.ws.addEventListener("message",n=>{this.handleServerMessage(n.data);}),this.ws.addEventListener("connectionChange",n=>{if(this.emitEvent({type:"CONNECTION_STATE_CHANGE",open:n.open}),n.open){Array.from(this.remoteSubscriptions.values()).forEach(({query:a})=>{this.sendWsMessage({id:b(),type:"SUBSCRIBE",...a});});let o=this.store.getCustomMutationMutationIds();Object.values(this.store.optimisticMutationStack).forEach(a=>{a&&a.forEach(c=>{o.has(c.id)||(this.emitEvent({type:"MUTATION_SENT",mutationId:c.id,resource:c.resource,resourceId:c.resourceId,procedure:c.procedure??"UNKNOWN",optimistic:true}),this.sendWsMessage(c));});}),this.replayCustomMutationStack();}});}get(e){let t=this.store.get(e);return this.emitEvent({type:"QUERY_EXECUTED",query:e,resultCount:Array.isArray(t)?t.length:t?1:0}),t}handleServerMessage(e){var t,i,s,r;try{this.logger.debug("Message received from the server:",e);let n=se.parse(JSON.parse(e));if(this.logger.debug("Parsed message:",n),this.emitEvent({type:"MESSAGE_RECEIVED",message:n}),n.type==="MUTATE"){let{resource:o,id:a,resourceId:c,procedure:p}=n;this.emitEvent({type:"MUTATION_RECEIVED",mutationId:a,resource:o,resourceId:c,procedure:p??"UNKNOWN"});try{this.store.addMutation(o,n);}catch(u){this.logger.error("Error merging mutation from the server:",u);}}else if(n.type==="REJECT"){if(this.replyHandlers[n.id]){clearTimeout(this.replyHandlers[n.id].timeoutHandle),this.emitUndoEvents(this.store.undoCustomMutation(n.id));let c=n.message??"Mutation rejected";(i=(t=this.replyHandlers[n.id]).reject)==null||i.call(t,new Error(c)),delete this.replyHandlers[n.id];}let o=((s=this.store.optimisticMutationStack[n.resource])==null?void 0:s.length)??0,a=(r=this.store.optimisticMutationStack[n.resource])==null?void 0:r.find(c=>c.id===n.id);this.store.undoMutation(n.resource,n.id),this.emitEvent({type:"MUTATION_REJECTED",mutationId:n.id,resource:n.resource}),a&&this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:n.id,resource:n.resource,resourceId:a.resourceId,pendingMutations:o-1});}else if(n.type==="REPLY"){let{id:o,data:a}=n;if(this.replyHandlers[o]){clearTimeout(this.replyHandlers[o].timeoutHandle),this.replyHandlers[o].handler(a);return}let c=ne.parse(a);this.emitEvent({type:"DATA_LOAD_REPLY",resource:c.resource,itemCount:c.data.length}),this.store.loadConsolidatedState(c.resource,c.data),this.emitEvent({type:"STORE_STATE_UPDATED",resource:c.resource,itemCount:c.data.length}),this.setBootstrapStatus("remote");}}catch(n){this.logger.error("Error parsing message from the server:",n);}}load(e){let t=b(),i=f(e);this.emitEvent({type:"DATA_LOAD_REQUESTED",query:e,subscriptionId:t}),this.sendWsMessage({id:t,type:"SUBSCRIBE",...e});let s=!this.remoteSubscriptions.has(i);return this.remoteSubscriptions.has(i)?this.remoteSubscriptions.get(i).subCounter+=1:this.remoteSubscriptions.set(i,{query:e,subCounter:1}),s&&this.emitEvent({type:"SUBSCRIPTION_CREATED",query:e,subscriptionKey:i,subscriberCount:1}),()=>{if(this.remoteSubscriptions.has(i)){let r=this.remoteSubscriptions.get(i);r.subCounter-=1,this.remoteSubscriptions.get(i).subCounter<=0&&(this.remoteSubscriptions.delete(i),this.sendWsMessage({id:b(),type:"UNSUBSCRIBE",...e}),this.emitEvent({type:"SUBSCRIPTION_REMOVED",query:e,subscriptionKey:i}));}}}subscribe(e,t){return this.store.subscribe(e,t)}mutate(e,t,i,s){var o,a;let r={id:b(),type:"MUTATE",resource:e,payload:this.store.schema[e].encodeMutation("set",s,new Date().toISOString()),resourceId:t,procedure:i},n=(((o=this.store.optimisticMutationStack[e])==null?void 0:o.length)??0)+1;(a=this.store)==null||a.addMutation(e,r,true),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:r.id,resource:e,resourceId:t,procedure:i,pendingMutations:n}),this.emitEvent({type:"MUTATION_SENT",mutationId:r.id,resource:e,resourceId:t,procedure:i,optimistic:true}),this.sendWsMessage(r);}genericMutate(e,t,i){var o,a;let s=(o=this.ws)==null?void 0:o.connected(),r=(a=this.optimisticMutations)==null?void 0:a.getHandler(e,t);if(!s&&!r)throw new Error("WebSocket not connected");let n={id:b(),type:"MUTATE",resource:e,procedure:t,payload:i,meta:{timestamp:new Date().toISOString()}};if(r)try{let{proxy:c,getOperations:p}=a$1(this.store,this.store.schema);r({input:i,storage:c});let u=p(),d=this.applyOptimisticOperations(u);this.store.registerCustomMutation(n.id,d),this.emitEvent({type:"MUTATION_SENT",mutationId:n.id,resource:e,resourceId:"",procedure:t,optimistic:!0});}catch(c){throw this.logger.error("Error executing optimistic handler:",c),this.emitUndoEvents(this.store.undoCustomMutation(n.id)),c}else this.emitEvent({type:"MUTATION_SENT",mutationId:n.id,resource:e,resourceId:"",procedure:t,optimistic:false});return s?(this.sendWsMessage(n),new Promise((c,p)=>{this.replyHandlers[n.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[n.id],this.emitUndoEvents(this.store.undoCustomMutation(n.id)),p(new Error("Reply timeout"));},5e3),handler:u=>{delete this.replyHandlers[n.id],this.store.confirmCustomMutation(n.id),c(u);},reject:p};})):(this.store.addCustomMutationMessage(n),Promise.resolve(void 0))}applyOptimisticOperations(e){var i;let t=[];try{for(let s of e){let r=b(),n=new Date().toISOString(),o={id:r,type:"MUTATE",resource:s.resource,resourceId:s.id,procedure:s.type==="insert"?"INSERT":"UPDATE",payload:this.store.schema[s.resource].encodeMutation("set",s.data,n)},a=(((i=this.store.optimisticMutationStack[s.resource])==null?void 0:i.length)??0)+1;this.store.addMutation(s.resource,o,!0),t.push({resource:s.resource,mutationId:r}),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:r,resource:s.resource,resourceId:s.id,procedure:s.type==="insert"?"INSERT":"UPDATE",pendingMutations:a});}return t}catch(s){for(let{resource:r,mutationId:n}of t)this.store.undoMutation(r,n);throw s}}emitUndoEvents(e){var t;for(let{resource:i,mutationId:s,resourceId:r}of e){let n=((t=this.store.optimisticMutationStack[i])==null?void 0:t.length)??0;this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:s,resource:i,resourceId:r,pendingMutations:n});}}genericQuery(e,t,i){if(!this.ws||!this.ws.connected())throw new Error("WebSocket not connected");let s={id:b(),type:"CUSTOM_QUERY",resource:e,procedure:t,input:i};return this.sendWsMessage(s),new Promise((r,n)=>{this.replyHandlers[s.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[s.id],n(new Error("Reply timeout"));},5e3),handler:o=>{delete this.replyHandlers[s.id],r(o);},reject:n};})}get bootstrapStatus(){return this._bootstrapStatus}setBootstrapStatus(e){ae[e]<=ae[this._bootstrapStatus]||(this._bootstrapStatus=e,this.emitEvent({type:"BOOTSTRAP_STATUS_CHANGE",bootstrapStatus:e}));}addEventListener(e){return this.eventListeners.add(e),()=>{this.eventListeners.delete(e);}}replayCustomMutationStack(){var e;if((e=this.ws)!=null&&e.connected())for(let t of this.store.customMutationStack)this.sendWsMessage(t),!this.replyHandlers[t.id]&&(this.replyHandlers[t.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[t.id],this.emitUndoEvents(this.store.undoCustomMutation(t.id));},5e3),handler:()=>{delete this.replyHandlers[t.id],this.store.confirmCustomMutation(t.id);}});}sendWsMessage(e){var t;(t=this.ws)!=null&&t.connected()&&this.ws.send(JSON.stringify(e));}emitEvent(e){this.eventListeners.forEach(t=>{t(e);});}},at=l=>{let e=new $(l),t=(i,s)=>new Proxy(s,{get(r,n,o){if(n in r)return Reflect.get(r,n,o);if(typeof n=="string")return a=>new D(e,{resource:i,procedure:n,input:a})}});return {client:{ws:e.ws,get bootstrapStatus(){return e.bootstrapStatus},load:i=>e.load(i),addEventListener:i=>e.addEventListener(i)},store:{query:new Proxy({},{get(i,s){if(typeof s=="string")return Object.hasOwn(l.schema,s)?t(s,a._init(l.schema[s],e)):new Proxy({},{get(r,n){if(typeof n=="string")return o=>new D(e,{resource:s,procedure:n,input:o})}})},has(i,s){return typeof s=="string"}}),mutate:d(()=>{},{apply:(i,s,r)=>{if(s.length<2)return;if(s.length>2)throw new Error("Trying to access an invalid path");let[n,o]=s;if(o==="insert")return e.genericMutate(n,o,r[0]).catch(a=>{if(!oe(a))throw a;let{id:c,...p}=r[0]??{};return e.mutate(n,c,"INSERT",p)});if(o==="update"){let a=r.length>1&&typeof r[0]=="string"&&typeof r[1]=="object"&&r[1]!==null?{id:r[0],...r[1]}:r[0];return e.genericMutate(n,o,a).catch(c=>{var d;if(!oe(c))throw c;let[p,u]=r.length>1?r:[(d=r[0])==null?void 0:d.id,r[0]];return e.mutate(n,p,"UPDATE",u)})}return e.genericMutate(n,o,r[0])}})}}};export{at as createClient,Ae as useClientState,we as useLiveQuery,xe as useLoadData};
@@ -1,4 +1,4 @@
1
- import { C as ClientOptions, a as ClientRouterConstraint, b as Client } from './index-LV6LHPwh.js';
1
+ import { C as ClientOptions, a as ClientRouterConstraint, b as Client } from './index-C0Qm5yHg.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';
4
4
 
@@ -1 +1 @@
1
- import {d,c,a,f as f$1}from'./chunk-LSAVBBUS.js';import {stringify}from'qs';var f=async(e,c,u)=>{let s=a=>{if(!a)return {};if(a instanceof Headers){let y={};return a.forEach((l,d)=>{y[d]=l;}),y}return Array.isArray(a)?Object.fromEntries(a):a},r=s(u==null?void 0:u.headers),o=s(c==null?void 0:c.headers),i={...u,...c,headers:{...r,...o}},n=await fetch(e,i),t;try{t=await n.json();}catch{t=await n.text().catch(()=>{});}if(!n.ok)throw new Error(`Failed to fetch: ${n.status} ${n.statusText}`,{cause:t});return t},g=e=>{if(e===null)return "null";if(Array.isArray(e))return e.map(g);if(typeof e=="object"&&e!==null&&e.constructor===Object){let c={};for(let[u,s]of Object.entries(e))c[u]=g(s);return c}return e},S=e=>{let c$1={get:async s=>{let r=g(s),o=stringify(r),i=await c(e.credentials)??{},n=await f(`${e.url}/${s.resource}${o?`?${o}`:""}`,{headers:{...i,"Content-Type":"application/json"}},e.fetchOptions);return !n||typeof n!="object"?[]:Array.isArray(n)?n.map(t=>{var l,d;let a=f$1(t),y=((d=(l=t==null?void 0:t.value)==null?void 0:l.id)==null?void 0:d.value)??(t==null?void 0:t.id);return {...a,id:y}}):Object.entries(n).map(([t,a])=>({...f$1(a),id:t}))},subscribe:()=>{throw new Error("Fetch client does not support subscriptions")}},u=(s,r)=>new Proxy(r,{get(o,i,n){if(i in o)return Reflect.get(o,i,n);if(typeof i=="string")return async t=>{let a=await c(e.credentials)??{};return await f(`${e.url}/${s}/query/${i}`,{method:"POST",headers:{...a,"Content-Type":"application/json"},body:JSON.stringify({input:t})},e.fetchOptions)}}});return {query:new Proxy({},{get(s,r){if(typeof r=="string")return Object.hasOwn(e.schema,r)?u(r,a._init(e.schema[r],c$1,true)):new Proxy({},{get(o,i){if(typeof i=="string")return async n=>{let t=await c(e.credentials)??{};return await f(`${e.url}/${r}/query/${i}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({input:n})},e.fetchOptions)}}})},has(s,r){return typeof r=="string"}}),mutate:d(()=>{},{apply:async(s,r,o)=>{if(r.length<2)return;if(r.length>2)throw new Error("Trying to access an invalid path");let[i,n]=r,t=await c(e.credentials)??{};if(n==="insert"){let{id:a,...y}=o[0];await f(`${e.url}/${i}/insert`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({resourceId:a,payload:e.schema[i].encodeMutation("set",y,new Date().toISOString())})},e.fetchOptions);return}if(n==="update"){let[a,y]=o,{id:l,...d}=y;await f(`${e.url}/${i}/update`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({resourceId:a,payload:e.schema[i].encodeMutation("set",d,new Date().toISOString())})},e.fetchOptions);return}return await f(`${e.url}/${i}/${n}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({payload:o[0],meta:{timestamp:new Date().toISOString()}})},e.fetchOptions)}})}};export{S as createClient};
1
+ import {d,c,a,f}from'./chunk-LSAVBBUS.js';import {stringify}from'qs';var l=async(e,c,u)=>{let s=o=>{if(!o)return {};if(o instanceof Headers){let y={};return o.forEach((f,d)=>{y[d]=f;}),y}return Array.isArray(o)?Object.fromEntries(o):o},i=s(u==null?void 0:u.headers),n=s(c==null?void 0:c.headers),a={...u,...c,headers:{...i,...n}},r=await fetch(e,a),t;try{t=await r.json();}catch{t=await r.text().catch(()=>{});}if(!r.ok)throw new Error(`Failed to fetch: ${r.status} ${r.statusText}`,{cause:t});return t},b=e=>{if(e instanceof Error&&e.message.includes("Unknown procedure"))return true;if(e instanceof Error&&typeof e.cause=="object"&&e.cause!==null&&("message"in e.cause||"code"in e.cause)){let c=e.cause,u=c.message,s=c.code==="UNKNOWN_PROCEDURE"||c.code==="unknown_procedure",i=typeof u=="string"&&u.includes("Unknown procedure");return s||i}return false},p=e=>{if(e===null)return "null";if(Array.isArray(e))return e.map(p);if(typeof e=="object"&&e!==null&&e.constructor===Object){let c={};for(let[u,s]of Object.entries(e))c[u]=p(s);return c}return e},E=e=>{let c$1={get:async s=>{let i=p(s),n=stringify(i),a=await c(e.credentials)??{},r=await l(`${e.url}/${s.resource}${n?`?${n}`:""}`,{headers:{...a,"Content-Type":"application/json"}},e.fetchOptions);return !r||typeof r!="object"?[]:Array.isArray(r)?r.map(t=>{var f$1,d;let o=f(t),y=((d=(f$1=t==null?void 0:t.value)==null?void 0:f$1.id)==null?void 0:d.value)??(t==null?void 0:t.id);return {...o,id:y}}):Object.entries(r).map(([t,o])=>({...f(o),id:t}))},subscribe:()=>{throw new Error("Fetch client does not support subscriptions")}},u=(s,i)=>new Proxy(i,{get(n,a,r){if(a in n)return Reflect.get(n,a,r);if(typeof a=="string")return async t=>{let o=await c(e.credentials)??{};return await l(`${e.url}/${s}/query/${a}`,{method:"POST",headers:{...o,"Content-Type":"application/json"},body:JSON.stringify({input:t})},e.fetchOptions)}}});return {query:new Proxy({},{get(s,i){if(typeof i=="string")return Object.hasOwn(e.schema,i)?u(i,a._init(e.schema[i],c$1,true)):new Proxy({},{get(n,a){if(typeof a=="string")return async r=>{let t=await c(e.credentials)??{};return await l(`${e.url}/${i}/query/${a}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({input:r})},e.fetchOptions)}}})},has(s,i){return typeof i=="string"}}),mutate:d(()=>{},{apply:async(s,i,n)=>{var o;if(i.length<2)return;if(i.length>2)throw new Error("Trying to access an invalid path");let[a,r]=i,t=await c(e.credentials)??{};if(r==="insert"){try{return await l(`${e.url}/${a}/${r}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({payload:n[0],meta:{timestamp:new Date().toISOString()}})},e.fetchOptions)}catch(d){if(!b(d))throw d}let{id:y,...f}=n[0]??{};return await l(`${e.url}/${a}/insert`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({resourceId:y,payload:e.schema[a].encodeMutation("set",f,new Date().toISOString())})},e.fetchOptions)}if(r==="update"){let y=n.length>1&&typeof n[0]=="string"&&typeof n[1]=="object"&&n[1]!==null?{id:n[0],...n[1]}:n[0];try{return await l(`${e.url}/${a}/${r}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({payload:y,meta:{timestamp:new Date().toISOString()}})},e.fetchOptions)}catch(w){if(!b(w))throw w}let[f,d]=n.length>1?n:[(o=n[0])==null?void 0:o.id,n[0]],{id:C,...$}=d??{};return await l(`${e.url}/${a}/update`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({resourceId:f,payload:e.schema[a].encodeMutation("set",$,new Date().toISOString())})},e.fetchOptions)}return await l(`${e.url}/${a}/${r}`,{method:"POST",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify({payload:n[0],meta:{timestamp:new Date().toISOString()}})},e.fetchOptions)}})}};export{E as createClient};
@@ -580,10 +580,12 @@ type CollectionQueryType<TRoute extends ClientRouterConstraint["routes"][string]
580
580
  } : {
581
581
  [K2 in keyof TRoute["customQueries"]]: CustomQueryFunction<InferSchema$1<TRoute["customQueries"][K2]["inputValidator"]>, ReturnType<TRoute["customQueries"][K2]["handler"]>, TShouldAwait>;
582
582
  };
583
- type CollectionMutateType<TRoute extends ClientRouterConstraint["routes"][string], TShouldAwait extends boolean> = TRoute["resourceSchema"] extends LiveObjectAny ? {
583
+ type CollectionMutateType<TRoute extends ClientRouterConstraint["routes"][string], TShouldAwait extends boolean> = TRoute["resourceSchema"] extends LiveObjectAny ? Omit<{
584
+ /** @deprecated Use custom mutations instead. Default insert will be removed in a future version. */
584
585
  insert: (input: Simplify<InferInsert<TRoute["resourceSchema"]>>) => ConditionalPromise<void, TShouldAwait>;
586
+ /** @deprecated Use custom mutations instead. Default update will be removed in a future version. */
585
587
  update: (id: string, value: Simplify<InferUpdate<TRoute["resourceSchema"]>>) => ConditionalPromise<void, TShouldAwait>;
586
- } & {
588
+ }, Extract<keyof TRoute["customMutations"], "insert" | "update">> & {
587
589
  [K2 in keyof TRoute["customMutations"]]: CustomMutationFunction<InferSchema$1<TRoute["customMutations"][K2]["inputValidator"]>, ReturnType<TRoute["customMutations"][K2]["handler"]>>;
588
590
  } : {
589
591
  [K2 in keyof TRoute["customMutations"]]: CustomMutationFunction<InferSchema$1<TRoute["customMutations"][K2]["inputValidator"]>, ReturnType<TRoute["customMutations"][K2]["handler"]>>;
@@ -856,14 +858,6 @@ declare const createOptimisticStorageProxy: <TSchema extends Schema<any>>(store:
856
858
  */
857
859
  declare const defineOptimisticMutations: <TRouter extends ClientRouterConstraint, TSchema extends Schema<any>>(config: OptimisticMutationsConfig<TRouter, TSchema>) => OptimisticMutationsRegistry<TSchema>;
858
860
 
859
- declare const useLiveQuery: <T extends {
860
- get: () => U;
861
- subscribe: (cb: (v: U) => void) => () => void;
862
- }, U>(observable: T) => ReturnType<T["get"]>;
863
- declare const useLoadData: (client: Client<ClientRouterConstraint>["client"], query: {
864
- buildQueryRequest: () => RawQueryRequest | CustomQueryRequest;
865
- }) => void;
866
-
867
861
  type WebSocketClientEventMap = WebSocketEventMap & {
868
862
  connectionChange: {
869
863
  open: boolean;
@@ -995,10 +989,16 @@ type OptimisticMutationUndoneEvent = {
995
989
  resourceId: string;
996
990
  pendingMutations: number;
997
991
  };
998
- type ClientEvents = ConnectionStateChangeEvent | MessageReceivedEvent | ClientStorageLoadedEvent | DataLoadRequestedEvent | DataLoadReplyEvent | MutationSentEvent | MutationReceivedEvent | MutationRejectedEvent | SubscriptionCreatedEvent | SubscriptionRemovedEvent | QueryExecutedEvent | QuerySubscriptionTriggeredEvent | StoreStateUpdatedEvent | OptimisticMutationAppliedEvent | OptimisticMutationUndoneEvent;
992
+ type ClientBootstrapStatus = "pending" | "local" | "remote";
993
+ type BootstrapStatusChangeEvent = {
994
+ type: "BOOTSTRAP_STATUS_CHANGE";
995
+ bootstrapStatus: ClientBootstrapStatus;
996
+ };
997
+ type ClientEvents = ConnectionStateChangeEvent | MessageReceivedEvent | ClientStorageLoadedEvent | DataLoadRequestedEvent | DataLoadReplyEvent | MutationSentEvent | MutationReceivedEvent | MutationRejectedEvent | SubscriptionCreatedEvent | SubscriptionRemovedEvent | QueryExecutedEvent | QuerySubscriptionTriggeredEvent | StoreStateUpdatedEvent | OptimisticMutationAppliedEvent | OptimisticMutationUndoneEvent | BootstrapStatusChangeEvent;
999
998
  type Client<TRouter extends ClientRouterConstraint> = {
1000
999
  client: {
1001
1000
  ws: WebSocketClient;
1001
+ readonly bootstrapStatus: ClientBootstrapStatus;
1002
1002
  addEventListener: (listener: (event: ClientEvents) => void) => () => void;
1003
1003
  load: (query: RawQueryRequest | CustomQueryRequest) => () => void;
1004
1004
  };
@@ -1006,6 +1006,19 @@ type Client<TRouter extends ClientRouterConstraint> = {
1006
1006
  };
1007
1007
  declare const createClient: <TRouter extends ClientRouterConstraint>(opts: WebSocketClientOptions) => Client<TRouter>;
1008
1008
 
1009
+ declare const useLiveQuery: <T extends {
1010
+ get: () => U;
1011
+ subscribe: (cb: (v: U) => void) => () => void;
1012
+ }, U>(observable: T) => ReturnType<T["get"]>;
1013
+ type ClientState = {
1014
+ bootstrapStatus: ClientBootstrapStatus;
1015
+ connected: boolean;
1016
+ };
1017
+ declare const useClientState: (client: Client<ClientRouterConstraint>["client"]) => ClientState;
1018
+ declare const useLoadData: (client: Client<ClientRouterConstraint>["client"], query: {
1019
+ buildQueryRequest: () => RawQueryRequest | CustomQueryRequest;
1020
+ }) => void;
1021
+
1009
1022
  type ClientOptions<TSchema extends Schema<any> = Schema<any>> = {
1010
1023
  url: string;
1011
1024
  schema: TSchema;
@@ -1017,4 +1030,4 @@ type ClientOptions<TSchema extends Schema<any> = Schema<any>> = {
1017
1030
  optimisticMutations?: OptimisticMutationsRegistry<any>;
1018
1031
  };
1019
1032
 
1020
- export { createClient as A, type ClientOptions as C, type DataLoadRequestedEvent as D, type MessageReceivedEvent as M, type OptimisticMutationsConfig as O, type QueryExecutedEvent as Q, type SubscriptionCreatedEvent as S, type ClientRouterConstraint as a, type Client$1 as b, type OptimisticMutationsRegistry as c, defineOptimisticMutations as d, type OptimisticHandlerContext as e, type OptimisticStorageProxy as f, type OptimisticOperation as g, type OptimisticInsertOperation as h, type OptimisticUpdateOperation as i, type OptimisticMutationHandler as j, createOptimisticStorageProxy as k, useLoadData as l, type ConnectionStateChangeEvent as m, type ClientStorageLoadedEvent as n, type DataLoadReplyEvent as o, type MutationSentEvent as p, type MutationReceivedEvent as q, type MutationRejectedEvent as r, type SubscriptionRemovedEvent as s, type QuerySubscriptionTriggeredEvent as t, useLiveQuery as u, type StoreStateUpdatedEvent as v, type OptimisticMutationAppliedEvent as w, type OptimisticMutationUndoneEvent as x, type ClientEvents as y, type Client as z };
1033
+ export { type ClientBootstrapStatus as A, type BootstrapStatusChangeEvent as B, type ClientOptions as C, type DataLoadRequestedEvent as D, type ClientEvents as E, type Client as F, createClient as G, type MessageReceivedEvent as M, type OptimisticMutationsConfig as O, type QueryExecutedEvent as Q, type SubscriptionCreatedEvent as S, type ClientRouterConstraint as a, type Client$1 as b, type OptimisticMutationsRegistry as c, defineOptimisticMutations as d, type OptimisticHandlerContext as e, type OptimisticStorageProxy as f, type OptimisticOperation as g, type OptimisticInsertOperation as h, type OptimisticUpdateOperation as i, type OptimisticMutationHandler as j, createOptimisticStorageProxy as k, type ClientState as l, useClientState as m, useLoadData as n, type ConnectionStateChangeEvent as o, type ClientStorageLoadedEvent as p, type DataLoadReplyEvent as q, type MutationSentEvent as r, type MutationReceivedEvent as s, type MutationRejectedEvent as t, useLiveQuery as u, type SubscriptionRemovedEvent as v, type QuerySubscriptionTriggeredEvent as w, type StoreStateUpdatedEvent as x, type OptimisticMutationAppliedEvent as y, type OptimisticMutationUndoneEvent as z };
@@ -1,3 +1,3 @@
1
- export { e as OptimisticHandlerContext, h as OptimisticInsertOperation, j as OptimisticMutationHandler, O as OptimisticMutationsConfig, c as OptimisticMutationsRegistry, g as OptimisticOperation, f as OptimisticStorageProxy, i as OptimisticUpdateOperation, k as createOptimisticStorageProxy, d as defineOptimisticMutations } from './index-LV6LHPwh.js';
1
+ export { e as OptimisticHandlerContext, h as OptimisticInsertOperation, j as OptimisticMutationHandler, O as OptimisticMutationsConfig, c as OptimisticMutationsRegistry, g as OptimisticOperation, f as OptimisticStorageProxy, i as OptimisticUpdateOperation, k as createOptimisticStorageProxy, d as defineOptimisticMutations } from './index-C0Qm5yHg.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';