@live-state/sync 0.0.7 → 1.0.0-canary-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.
@@ -0,0 +1 @@
1
+ var d="0123456789ABCDEFGHJKMNPQRSTVWXYZ";var a;(function(e){e.Base32IncorrectEncoding="B32_ENC_INVALID",e.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",e.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",e.EncodeTimeNegative="ENC_TIME_NEG",e.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",e.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",e.PRNGDetectFailure="PRNG_DETECT",e.ULIDInvalid="ULID_INVALID",e.Unexpected="UNEXPECTED",e.UUIDInvalid="UUID_INVALID";})(a||(a={}));var c=class extends Error{constructor(t,n){super(`${n} (${t})`),this.name="ULIDError",this.code=t;}};function m(e){let t=Math.floor(e()*32);return t===32&&(t=31),d.charAt(t)}function E(e){let t=p(),n=t&&(t.crypto||t.msCrypto)||null;if(typeof(n==null?void 0:n.getRandomValues)=="function")return ()=>{let r=new Uint8Array(1);return n.getRandomValues(r),r[0]/255};if(typeof(n==null?void 0:n.randomBytes)=="function")return ()=>n.randomBytes(1).readUInt8()/255;throw new c(a.PRNGDetectFailure,"Failed to find a reliable PRNG")}function p(){return g()?self:typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:null}function N(e,t){let n="";for(;e>0;e--)n=m(t)+n;return n}function I(e,t=10){if(isNaN(e))throw new c(a.EncodeTimeValueMalformed,`Time must be a number: ${e}`);if(e>0xffffffffffff)throw new c(a.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${0xffffffffffff}: ${e}`);if(e<0)throw new c(a.EncodeTimeNegative,`Time must be positive: ${e}`);if(Number.isInteger(e)===false)throw new c(a.EncodeTimeValueMalformed,`Time must be an integer: ${e}`);let n,r="";for(let o=t;o>0;o--)n=e%32,r=d.charAt(n)+r,e=(e-n)/32;return r}function g(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function T(e,t){let n=E(),r=Date.now();return I(r,10)+N(16,n)}var b=()=>T().toLowerCase();var D=(e,t)=>typeof e=="function"?e(t):e;var _=(e,t,n=[])=>new Proxy(e,{get:(r,o)=>{var f,l;if(o==="__isProxy__")return true;let i=(f=t.get)==null?void 0:f.call(t,r,[...n,o]);if(i!==void 0)return i;let s=r,u=o;return (l=s[u])!=null&&l.__isProxy__||(s[u]=_(typeof s[u]=="object"?s[u]:()=>{},t,[...n,o])),s[u]},apply:(r,o,i)=>{var s;return (s=t.apply)==null?void 0:s.call(t,r,n,i)}}),M=(e,t,n)=>{let r=[],o=0;for(let i=0;i<e.length&&(n===void 0||o<n);i++)t(e[i],i)&&(r.push(e[i]),o++);return r};export{b as a,D as b,_ as c,M as d};
package/dist/client.d.ts CHANGED
@@ -1,3 +1,3 @@
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';
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-DOU7wys1.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import {d,a,b as b$1,f,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 b=l=>xxHash32(JSON.stringify(l)).toString(32);var E=(l,e,t=false)=>Object.entries(e).every(([i,s])=>{if(i==="$and")return s.every(n=>E(l,n,t));if(i==="$or")return s.some(n=>E(l,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=l[i];return r===void 0?false:t?!s.$in.includes(r):s.$in.includes(r)}if(s.$not!==void 0&&!t)return E(l,{[i]:s.$not},true);if(s.$gt!==void 0){let r=l[i];return typeof r!="number"?false:t?r<=s.$gt:r>s.$gt}if(s.$gte!==void 0){let r=l[i];return typeof r!="number"?false:t?r<s.$gte:r>=s.$gte}if(s.$lt!==void 0){let r=l[i];return typeof r!="number"?false:t?r>=s.$lt:r<s.$lt}if(s.$lte!==void 0){let r=l[i];return typeof r!="number"?false:t?r>s.$lte:r<=s.$lte}let n=l[i];return !n||typeof n!="object"&&!Array.isArray(n)?false:Array.isArray(n)?t?!n.some(r=>E(r,s,false)):n.some(r=>E(r,s,false)):E(n,s,t)}return t?l[i]!==o:l[i]===o}),I=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},T={CRITICAL:0,ERROR:1,WARN:2,INFO:3,DEBUG:4},U=class{level;prefix;constructor(e={}){this.level=e.level??T.INFO,this.prefix=e.prefix?`[${e.prefix}] `:"";}critical(...e){this.level>=T.CRITICAL&&console.error(`${this.prefix}[CRITICAL]`,...e);}error(...e){this.level>=T.ERROR&&console.error(`${this.prefix}[ERROR]`,...e);}warn(...e){this.level>=T.WARN&&console.warn(`${this.prefix}[WARN]`,...e);}info(...e){this.level>=T.INFO&&console.log(`${this.prefix}[INFO]`,...e);}debug(...e){this.level>=T.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=b(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}},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 o={bootstrapStatus:l.bootstrapStatus,connected:l.ws.connected()};(o.bootstrapStatus!==i.bootstrapStatus||o.connected!==i.connected)&&(i=o);};return {subscribe:o=>l.addEventListener(n=>{(n.type==="BOOTSTRAP_STATUS_CHANGE"||n.type==="CONNECTION_STATE_CHANGE")&&(s(),o());}),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 O=z.string(),W=z.union([te,X]),ye=z.object({id:O,type:z.literal("SUBSCRIBE")}).and(W),me=z.object({id:O,type:z.literal("UNSUBSCRIBE")}).and(W),ge=z.object({id:O,type:z.literal("QUERY")}).and(W),fe=z.object({id:O,type:z.literal("CUSTOM_QUERY"),resource:z.string(),procedure:z.string(),input:z.any().optional()}),ie=B.extend({id:O}),be=N.extend({id:O}),Me=z.union([be,ie]);z.union([ye,ge,fe,Me,me]);var Se=z.object({id:O,type:z.literal("REJECT"),resource:z.string(),message:z.string().optional()}),ve=z.object({id:O,type:z.literal("REPLY"),data:z.any()}),se=z.union([Se,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(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 q="__meta",L="databases",j=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,o=await b(e),n=Object.fromEntries(await Promise.all(Object.entries(e).map(async([u,d])=>[u,await b(d)]))),r=await openDB("live-state-databases",1,{upgrade(u){u.objectStoreNames.contains(L)||u.createObjectStore(L);}}),a=(p=await this.getAll(r,L))==null?void 0:p[t];(a==null?void 0:a.schemaHash)!==o&&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 r.put(L,{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(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((o,n)=>[s[n],o]))}};var P=class{constructor(e,t,i,s,o,n){this.schema=e;this.logger=i,this.optimisticObjGraph=new k(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(([p,u])=>({...u,id:{value:p}}));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??b(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 p=f(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 y=p[d.key],g=u[d.key];if(y<g)return d.direction==="asc"?-1:1;if(y>g)return d.direction==="asc"?1:-1}return 0};r.sort(c);}if(e$1.where||e$1.limit){let c=e$1.where?p=>E(p,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=b(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,p,u,d;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(M=>M.id!==t.id))??[];let y=(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:y??"(none)",customMutationIndexKeys:Object.keys(this.customMutationIndex),optimisticStackSize:((p=this.optimisticMutationStack[e])==null?void 0:p.length)??0}),y&&this.customMutationIndex[y]){let w=this.customMutationIndex[y].filter(S=>S.resource===e),C=false;for(let S of w){let R=(u=this.optimisticMutationStack[e])==null?void 0:u.find(A=>A.id===S.mutationId);if(R&&R.resourceId===t.resourceId&&R.procedure===t.procedure){this.logger.debug("Removing optimistic mutation (resourceId match)",{optimisticMutationId:S.mutationId,resourceId:t.resourceId}),this.undoMutation(e,S.mutationId),C=true;break}}if(!C)for(let S of w){let R=(d=this.optimisticMutationStack[e])==null?void 0:d.find(A=>A.id===S.mutationId&&A.procedure===t.procedure);if(R){this.logger.debug("Removing optimistic mutation (resource+procedure fallback)",{optimisticMutationId:S.mutationId,optimisticResourceId:R.resourceId,broadcastResourceId:t.resourceId}),this.undoMutation(e,S.mutationId),C=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 f=g.value;delete f.id,this.kvStorage.set(e,t.resourceId,f);}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,p=r==null?void 0:r.value;if(a.type==="one"){if(p&&typeof p=="object"&&!Array.isArray(p)&&((u=p.id)!=null&&u.value)){let d=p.id.value,y={...p},{cleanedPayload:g,nestedMutations:f}=this.extractNestedRelations(c,y);o.push(...f),o.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 y,g;if(d&&typeof d=="object"&&!Array.isArray(d)&&((g=(y=d.value)==null?void 0:y.id)!=null&&g.value)){let f=d.value.id.value,M={...d.value},{cleanedPayload:w,nestedMutations:C}=this.extractNestedRelations(c,M);o.push(...C),o.push({id:f,type:"MUTATE",resource:c,resourceId:f,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,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],[,y]=u.mergeMutation("set",p,d);if(y){if(!this.optimisticObjGraph.hasNode(y.value)){let g=u.entity.name;this.optimisticObjGraph.createNode(y.value,g,Object.values(this.schema[g].relations).flatMap(f=>f.type==="many"?[f.entity.name]:[]));}d!=null&&d.value&&this.optimisticObjGraph.removeLink(t,u.entity.name),this.optimisticObjGraph.createLink(t,y.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,[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:{...o.value,...Object.fromEntries(n.map(([c,p,u])=>[c,this.materializeOneWithInclude(i.references.get(p),I(u)?u.include??{}:typeof u=="object"&&u!==null?u:{})])),...Object.fromEntries(r.map(([c,p,u])=>{let d=i.referencedBy.get(p),y=d instanceof Set;return [c,y?{value:Array.from(d.values()).map(g=>this.materializeOneWithInclude(g,I(u)?u.include??{}:typeof u=="object"&&u!==null?u:{}))}:this.materializeOneWithInclude(d,I(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=b(t.query),n=this.querySnapshots[o],r=this.get(t.query,void 0,true);if(Te(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=I(o)?o.include??{}:o;i.push(...this.flattenIncludes(c,r));}}),Array.from(new Set(i))}};var re=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,o;this.url=e.url,this.logger=F({level:e.logLevel??T.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,r,a)=>{var p,u;let c=new Set;if(a)for(let d of Object.values(a))for(let{mutationId:y}of d)c.add(y);(u=(p=Object.values(n))==null?void 0:p.flat())==null||u.forEach(d=>{c.has(d.id)||this.sendWsMessage(d);}),this.replayCustomMutationStack();},(n,r)=>{this.emitEvent({type:"CLIENT_STORAGE_LOADED",resource:n,itemCount:r}),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:(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$1(),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=se.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:p}=n;this.emitEvent({type:"MUTATION_RECEIVED",mutationId:a,resource:r,resourceId:c,procedure:p??"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=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$1(),i=b(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$1(),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$1(),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 c,p,u,d;let s=(c=this.ws)==null?void 0:c.connected(),o=(p=this.optimisticMutations)==null?void 0:p.getHandler(e,t),r=(t==="insert"||t==="update")&&!o&&this.store.schema[e]?(()=>{let y=i??{},{id:g,...f}=y;if(typeof g=="string")try{let M=this.store.schema[e].encodeMutation("set",f,new Date().toISOString());return {id:g,input:f,encoded:M}}catch{return}})():void 0;if(!s&&!o&&!r)throw new Error("WebSocket not connected");let a={id:b$1(),type:"MUTATE",resource:e,procedure:t,payload:i,meta:{timestamp:new Date().toISOString()}};if(r){let y={id:a.id,type:"MUTATE",resource:e,resourceId:r.id,procedure:t==="insert"?"INSERT":"UPDATE",payload:r.encoded};(u=this.store)==null||u.addMutation(e,y,true),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:a.id,resource:e,resourceId:r.id,procedure:y.procedure,pendingMutations:((d=this.store.optimisticMutationStack[e])==null?void 0:d.length)??0}),this.emitEvent({type:"MUTATION_SENT",mutationId:a.id,resource:e,resourceId:r.id,procedure:t,optimistic:true});}else if(o)try{let{proxy:y,getOperations:g}=a$1(this.store,this.store.schema);o({input:i,storage:y});let f=g(),M=this.applyOptimisticOperations(f);this.store.registerCustomMutation(a.id,M),this.emitEvent({type:"MUTATION_SENT",mutationId:a.id,resource:e,resourceId:"",procedure:t,optimistic:!0});}catch(y){throw this.logger.error("Error executing optimistic handler:",y),this.emitUndoEvents(this.store.undoCustomMutation(a.id)),y}else this.emitEvent({type:"MUTATION_SENT",mutationId:a.id,resource:e,resourceId:"",procedure:t,optimistic:false});return s?(this.sendWsMessage(a),new Promise((y,g)=>{this.replyHandlers[a.id]={timeoutHandle:setTimeout(()=>{var f;if(delete this.replyHandlers[a.id],r){let M=((f=this.store.optimisticMutationStack[e])==null?void 0:f.length)??0;this.store.undoMutation(e,a.id),this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:a.id,resource:e,resourceId:r.id,pendingMutations:Math.max(M-1,0)});}else this.emitUndoEvents(this.store.undoCustomMutation(a.id));g(new Error("Reply timeout"));},5e3),handler:f=>{delete this.replyHandlers[a.id],r||this.store.confirmCustomMutation(a.id),y(f);},reject:g};})):(this.store.addCustomMutationMessage(a),Promise.resolve(void 0))}applyOptimisticOperations(e){var i;let t=[];try{for(let s of e){let o=b$1(),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$1(),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};})}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(o,n,r){if(n in o)return Reflect.get(o,n,r);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(o,n){if(typeof n=="string")return r=>new D(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")return e.genericMutate(n,r,o[0]).catch(a=>{if(!re(a))throw a;let{id:c,...p}=o[0]??{};return e.mutate(n,c,"INSERT",p)});if(r==="update"){let a=o.length>1&&typeof o[0]=="string"&&typeof o[1]=="object"&&o[1]!==null?{id:o[0],...o[1]}:o[0];return e.genericMutate(n,r,a).catch(c=>{var d;if(!re(c))throw c;let[p,u]=o.length>1?o:[(d=o[0])==null?void 0:d.id,o[0]];return e.mutate(n,p,"UPDATE",u)})}return e.genericMutate(n,r,o[0])}})}}};export{at as createClient,Ae as useClientState,we as useLiveQuery,xe as useLoadData};
1
+ import {c,a,d,b}from'./chunk-YPTDCIAN.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 as z$1}from'zod';import {stringify}from'qs';import Ge from'fast-deep-equal';import {openDB}from'idb';var T=o=>xxHash32(JSON.stringify(o)).toString(32);var R=(o,e,t=false)=>Object.entries(e).every(([i,n])=>{if(i==="$and")return n.every(s=>R(o,s,t));if(i==="$or")return n.some(s=>R(o,s,t));let r=(n==null?void 0:n.$eq)!==void 0?n==null?void 0:n.$eq:n;if(typeof n=="object"&&n!==null&&(n==null?void 0:n.$eq)===void 0){if(n.$in!==void 0){let a=o[i];return a===void 0?false:t?!n.$in.includes(a):n.$in.includes(a)}if(n.$not!==void 0&&!t)return R(o,{[i]:n.$not},true);if(n.$gt!==void 0){let a=o[i];return typeof a!="number"?false:t?a<=n.$gt:a>n.$gt}if(n.$gte!==void 0){let a=o[i];return typeof a!="number"?false:t?a<n.$gte:a>=n.$gte}if(n.$lt!==void 0){let a=o[i];return typeof a!="number"?false:t?a>=n.$lt:a<n.$lt}if(n.$lte!==void 0){let a=o[i];return typeof a!="number"?false:t?a>n.$lte:a<=n.$lte}let s=o[i];return !s||typeof s!="object"&&!Array.isArray(s)?false:Array.isArray(s)?t?!s.some(a=>R(a,n,false)):s.some(a=>R(a,n,false)):R(s,n,t)}return t?o[i]!==r:o[i]===r}),j=o=>{if(typeof o!="object"||o===null)return false;let e=o;return "where"in e||"limit"in e||"orderBy"in e||"include"in e},C={CRITICAL:0,ERROR:1,WARN:2,INFO:3,DEBUG:4},J=class{level;prefix;constructor(e={}){this.level=e.level??C.INFO,this.prefix=e.prefix?`[${e.prefix}] `:"";}critical(...e){this.level>=C.CRITICAL&&console.error(`${this.prefix}[CRITICAL]`,...e);}error(...e){this.level>=C.ERROR&&console.error(`${this.prefix}[ERROR]`,...e);}warn(...e){this.level>=C.WARN&&console.warn(`${this.prefix}[WARN]`,...e);}info(...e){this.level>=C.INFO&&console.log(`${this.prefix}[INFO]`,...e);}debug(...e){this.level>=C.DEBUG&&console.log(`${this.prefix}[DEBUG]`,...e);}setLevel(e){this.level=e;}getLevel(){return this.level}},de=o=>new J(o);var Y=class{subscriptions=new Map;getOrStoreSubscription(e){let t=e.buildQueryRequest(),i=T(t);if(this.subscriptions.has(i))return this.subscriptions.get(i).subscribe;let n={subscribe:r=>{let s=this.subscriptions.get(i);return s.callbacks.add(r),s.unsubscribe||(s.unsubscribe=()=>{},s.unsubscribe=e.subscribe(()=>{s.callbacks.forEach(a=>{a();});})),()=>{var a;(a=this.subscriptions.get(i))==null||a.callbacks.delete(r),setTimeout(()=>{var u;let l=this.subscriptions.get(i);l&&l.callbacks.size===0&&((u=l.unsubscribe)==null||u.call(l),this.subscriptions.delete(i));},10);}},callbacks:new Set,unsubscribe:void 0};return this.subscriptions.set(i,n),this.subscriptions.get(i).subscribe}},Ce=new Y,Xe=o=>useSyncExternalStore(Ce.getOrStoreSubscription(o),o.get),Ze=o=>{let{subscribe:e,getSnapshot:t}=useMemo(()=>{let i={bootstrapStatus:o.bootstrapStatus,connected:o.ws.connected()},n=()=>{let r={bootstrapStatus:o.bootstrapStatus,connected:o.ws.connected()};(r.bootstrapStatus!==i.bootstrapStatus||r.connected!==i.connected)&&(i=r);};return {subscribe:r=>o.addEventListener(s=>{(s.type==="BOOTSTRAP_STATUS_CHANGE"||s.type==="CONNECTION_STATE_CHANGE")&&(n(),r());}),getSnapshot:()=>i}},[o]);return useSyncExternalStore(e,t,t)},et=(o,e)=>{useEffect(()=>{let t=o.load(e.buildQueryRequest());return ()=>{t();}},[e,o.load]);};var k=class o{_collection;_client;_where;_include;_limit;_single;_sort;_shouldAwait;constructor(e,t,i,n,r,s,a,l){this._collection=e,this._client=t,this._where=i??{},this._include=n??{},this._limit=r,this._single=s,this._sort=a,this._shouldAwait=l,this.get=this.get.bind(this),this.subscribe=this.subscribe.bind(this);}where(e){return new o(this._collection,this._client,{...this._where,...e},this._include,this._limit,this._single,this._sort,this._shouldAwait)}include(e){return new o(this._collection,this._client,this._where,{...this._include,...e},this._limit,this._single,this._sort,this._shouldAwait)}limit(e){return new o(this._collection,this._client,this._where,this._include,e,this._single,this._sort,this._shouldAwait)}one(e){return this.first({id:e})}first(e){return new o(this._collection,this._client,e??this._where,this._include,1,true,this._sort,this._shouldAwait)}orderBy(e,t="asc"){let i=[...this._sort??[],{key:e,direction:t}];return new o(this._collection,this._client,this._where,this._include,this._limit,this._single,i,this._shouldAwait)}toJSON(){return {resource:this._collection.name,where:this._where,include:this._include,limit:this._limit,sort:this._sort}}buildQueryRequest(){return {resource:this._collection.name,where:this._where,include:this._include,limit:this._limit,sort:this._sort}}get(){let e=this._client.get(this.buildQueryRequest());return this._shouldAwait?Promise.resolve(e).then(t=>this._single?t[0]:t):this._single?e[0]:e}subscribe(e){return this._client.subscribe(this.buildQueryRequest(),t=>{if(this._single)return e(t[0]);e(t);})}static _init(e,t,i){return new o(e,t,void 0,void 0,void 0,void 0,void 0,i??false)}};z$1.object({resource:z$1.string(),where:z$1.record(z$1.string(),z$1.any()).optional(),include:z$1.record(z$1.string(),z$1.any()).optional(),limit:z$1.coerce.number().optional(),sort:z$1.array(z$1.object({key:z$1.string(),direction:z$1.enum(["asc","desc"])})).optional()});var X=z$1.record(z$1.string(),z$1.object({value:z$1.any().nullable(),_meta:z$1.object({timestamp:z$1.string().optional().nullable()}).optional()})),xe=X.superRefine((o,e)=>{o.id&&e.addIssue({code:z$1.ZodIssueCode.custom,message:"Payload cannot have an id"});}),Le=z$1.object({id:z$1.string().optional(),type:z$1.literal("MUTATE"),resource:z$1.string(),resourceId:z$1.string().optional()}),ye=z$1.object({timestamp:z$1.string().optional(),originMutationId:z$1.string().optional()}).optional(),he=Le.extend({procedure:z$1.string(),payload:z$1.any().optional(),meta:ye}),Z=z$1.object({id:z$1.string().optional(),type:z$1.literal("SYNC"),resource:z$1.string(),resourceId:z$1.string(),op:z$1.enum(["INSERT","UPDATE","DELETE"]),payload:xe,meta:ye}),ee=(o,e)=>{o.op==="DELETE"&&Object.keys(o.payload).length>0&&e.addIssue({code:z$1.ZodIssueCode.custom,message:"DELETE delta payload must be empty"});};Z.superRefine(ee);var me=z$1.object({resource:z$1.string(),procedure:z$1.string(),input:z$1.any().optional()});var x=z$1.string(),te=me,Ee=z$1.object({id:x,type:z$1.literal("SUBSCRIBE")}).and(te),Ie=z$1.object({id:x,type:z$1.literal("UNSUBSCRIBE")}).and(te),we=z$1.object({id:x,type:z$1.literal("QUERY")}).and(te),Ae=z$1.object({id:x,type:z$1.literal("CUSTOM_QUERY"),resource:z$1.string(),procedure:z$1.string(),input:z$1.any().optional()}),Oe=he.extend({id:x}),je=Oe;z$1.union([Ee,we,Ae,je,Ie]);var _e=z$1.object({id:x,type:z$1.literal("REJECT"),resource:z$1.string(),message:z$1.string().optional()}),De=z$1.object({id:x,type:z$1.literal("REPLY"),data:z$1.any()}),Ve=Z.extend({id:x}).superRefine(ee),fe=z$1.union([_e,De,Ve]),Te=z$1.object({resource:z$1.string(),data:z$1.array(X)});var N=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 b(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(n=>{n(t);});}};var ie=o=>typeof o=="object"&&o!==null&&"value"in o&&!Array.isArray(o),O=o=>o?Array.isArray(o.value)?o.value.map(t=>ie(t)?O(t):t):typeof o.value!="object"||o.value===null||o.value instanceof Date?o.value:Object.fromEntries(Object.entries(o.value).map(([t,i])=>Array.isArray(i)?[t,i.map(n=>ie(n)?O(n):n)]:ie(i)?[t,O(i)]:[t,i])):void 0;var B=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 n={id:e,type:t,referencedBy:new Map(i.map(r=>[r,new Set])),references:new Map,subscriptions:new Set};return this.nodes.set(e,n),n}getNode(e){return this.nodes.get(e)}hasNode(e){return this.nodes.has(e)}createLink(e,t){let i=this.nodes.get(e),n=this.nodes.get(t);if(!i)throw new Error(`Source node with id ${e} does not exist`);if(!n)throw new Error(`Target node with id ${t} does not exist`);i.references.set(n.type,t);let r=n.referencedBy.get(i.type);r&&r instanceof Set?r.add(e):n.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 n=i.references.get(t);if(!n)return;i.references.delete(t);let r=this.nodes.get(n);if(!r)return;let s=r.referencedBy.get(i.type);s&&(s instanceof Set?s.delete(e):r.referencedBy.delete(i.type),this.notifySubscribers(n)),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,n])=>{(n instanceof Set?Array.from(n.values()):[n]).forEach(s=>{let a=this.nodes.get(s);!a||!a.references.get(i)||(a.references.delete(i),this.notifySubscribers(s));});}),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 n;try{i(e);}catch(r){(n=this.logger)==null||n.error(`Error in node subscription for node ${e}:`,r);}});}getAllNodes(){return Array.from(this.nodes.values())}};var ne="__meta",W="databases",$=class{db;async init(e,t){var u,d;if(typeof window>"u")return;let n=((u=(await window.indexedDB.databases()).find(c=>c.name===t))==null?void 0:u.version)??1,r=await T(e),s=Object.fromEntries(await Promise.all(Object.entries(e).map(async([c,p])=>[c,await T(p)]))),a=await openDB("live-state-databases",1,{upgrade(c){c.objectStoreNames.contains(W)||c.createObjectStore(W);}}),l=(d=await this.getAll(a,W))==null?void 0:d[t];(l==null?void 0:l.schemaHash)!==r&&n++,this.db=await openDB(t,n,{async upgrade(c){[...Object.keys(e),ne].forEach(p=>{(l==null?void 0:l.objectHashes[p])!==s[p]&&c.objectStoreNames.contains(p)&&c.deleteObjectStore(p),c.objectStoreNames.contains(p)||c.createObjectStore(p);}),await a.put(W,{schemaHash:r,objectHashes:s},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 n;return (n=this.db)==null?void 0:n.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(ne,e):new Promise(t=>t(void 0))}setMeta(e,t){var i;return (i=this.db)==null?void 0:i.put(ne,t,e)}async getAll(e,t){if(!e)return;if(e.getAllRecords)return e.getAllRecords(t);let[i,n]=await Promise.all([e.getAll(t),e.getAllKeys(t)]);return Object.fromEntries(i.map((r,s)=>[n[s],r]))}};var G=class{constructor(e,t,i,n,r,s){this.schema=e;this.logger=i,this.optimisticObjGraph=new B(i),this.kvStorage=new $,this.onQuerySubscriptionTriggered=s,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(([a,l,u])=>{a&&Object.keys(a).length>0&&(this.optimisticMutationStack=a),l&&l.length>0&&(this.customMutationStack=l),u&&Object.keys(u).length>0&&(this.customMutationIndex=u),n==null||n(this.optimisticMutationStack,this.customMutationStack,this.customMutationIndex);}).then(()=>{Object.entries(this.schema).forEach(([a])=>{this.kvStorage.get(a).then(l=>{if(!l||Object.keys(l).length===0){r==null||r(a,0);return}let u=Object.entries(l).map(([d,c])=>({...c,id:{value:d}}));r==null||r(a,u.length),this.loadConsolidatedState(a,u);});});}).catch(a=>{i.debug("Storage initialization failed (may not be available in this environment):",a);});});}rawObjPool={};optimisticMutationStack={};customMutationStack=[];optimisticObjGraph;optimisticRawObjPool={};logger;onQuerySubscriptionTriggered;customMutationIndex={};collectionSubscriptions=new Map;querySnapshots={};kvStorage;get(e,t,i=false){var l;let n=t??T(e);if(this.querySnapshots[n]&&!i){let u=this.querySnapshots[n];if(u)return u}let r,s=(l=e.where)==null?void 0:l.id;s===void 0?r=Object.keys(this.optimisticRawObjPool[e.resource]??{}):typeof s=="string"?r=[s]:typeof s=="object"&&s!==null?"$in"in s&&Array.isArray(s.$in)?r=s.$in:"$eq"in s&&typeof s.$eq=="string"?r=[s.$eq]:r=Object.keys(this.optimisticRawObjPool[e.resource]??{}):r=Object.keys(this.optimisticRawObjPool[e.resource]??{});let a=r.flatMap(u=>{let d=O(this.materializeOneWithInclude(u,e.include));return d?[d]:[]});if(e.sort&&e.sort.length>0){let u=(d,c)=>{for(let p of e.sort){let m=d[p.key],f=c[p.key];if(m<f)return p.direction==="asc"?-1:1;if(m>f)return p.direction==="asc"?1:-1}return 0};a.sort(u);}if(e.where||e.limit){let u=e.where?d=>R(d,e.where):()=>true;a=d(a,u,e.limit);}return !i&&this.collectionSubscriptions.has(n)&&(this.querySnapshots[n]=a),a}subscribe(e,t){var r;let i=T(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 s,a;(s=this.collectionSubscriptions.get(i))==null||s.callbacks.delete(t),((a=this.collectionSubscriptions.get(i))==null?void 0:a.callbacks.size)===0&&(this.collectionSubscriptions.delete(i),delete this.querySnapshots[i]);}}addMutation(e,t,i=false){var l,u,d,c,p,m,f,g;let n=this.schema[e];if(this.logger.debug("Adding mutation",t),!n)throw new Error("Schema not found");if(t.op==="DELETE"){this.removeFromPool(e,t.resourceId);return}let r=(l=this.optimisticRawObjPool[e])==null?void 0:l[t.resourceId],s=false;if(i)this.optimisticMutationStack[e]??=[],this.optimisticMutationStack[e].push(t);else {this.optimisticMutationStack[e]=((d=(u=this.optimisticMutationStack)==null?void 0:u[e])==null?void 0:d.filter(re=>re.id!==t.id))??[];let E=(c=t.meta)==null?void 0:c.originMutationId;if(this.logger.debug("Broadcast mutation received",{mutationId:t.id,resource:e,resourceId:t.resourceId,op:t.op,originMutationId:E??"(none)",customMutationIndexKeys:Object.keys(this.customMutationIndex),optimisticStackSize:((p=this.optimisticMutationStack[e])==null?void 0:p.length)??0}),E&&this.customMutationIndex[E]){let oe=this.customMutationIndex[E].filter(S=>S.resource===e),H=false;for(let S of oe){let I=(m=this.optimisticMutationStack[e])==null?void 0:m.find(V=>V.id===S.mutationId);if(I&&I.resourceId===t.resourceId&&I.op===t.op){this.logger.debug("Removing optimistic mutation (resourceId match)",{optimisticMutationId:S.mutationId,resourceId:t.resourceId}),this.undoMutation(e,S.mutationId),s=true,H=true;break}}if(!H)for(let S of oe){let I=(f=this.optimisticMutationStack[e])==null?void 0:f.find(V=>V.id===S.mutationId&&V.op===t.op);if(I){this.logger.debug("Removing optimistic mutation (resource+procedure fallback)",{optimisticMutationId:S.mutationId,optimisticResourceId:I.resourceId,broadcastResourceId:t.resourceId}),this.undoMutation(e,S.mutationId),s=true,H=true;break}}}this.rawObjPool[e]??={};let _={value:{...this.schema[e].mergeMutation("set",t.payload,this.rawObjPool[e][t.resourceId])[0].value,id:{value:t.resourceId}}};this.rawObjPool[e][t.resourceId]=_;let D=_.value;delete D.id,this.kvStorage.set(e,t.resourceId,D);}this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack);let a=s?(g=this.optimisticRawObjPool[e])==null?void 0:g[t.resourceId]:r;this.updateRawObjPool(e,t.resourceId,t.payload,a);}undoMutation(e,t){var s,a;if(!this.optimisticMutationStack[e])return;let i=(s=this.optimisticMutationStack[e])==null?void 0:s.findIndex(l=>l.id===t);if(i===-1)return;let n=this.optimisticMutationStack[e][i];this.logger.debug("Removing mutation",n);let r=(a=this.optimisticRawObjPool[e])==null?void 0:a[n.resourceId];this.optimisticMutationStack[e].splice(i,1),this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.updateRawObjPool(e,n.resourceId,Object.fromEntries(Object.entries(n.payload).map(([l])=>[l,{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:n,mutationId:r}of t){let s=!!((i=this.optimisticMutationStack[n])!=null&&i.find(a=>a.id===r));this.logger.debug("confirmCustomMutation: undoing mutation",{resource:n,mutationId:r,stillInStack:s}),this.undoMutation(n,r);}delete this.customMutationIndex[e],this.kvStorage.setMeta("customMutationIndex",this.customMutationIndex),this.customMutationStack=this.customMutationStack.filter(n=>n.id!==e),this.kvStorage.setMeta("customMutationStack",this.customMutationStack);}}undoCustomMutation(e){var n;let t=this.customMutationIndex[e];if(!t)return [];let i=[];for(let{resource:r,mutationId:s}of t){let a=(n=this.optimisticMutationStack[r])==null?void 0:n.find(l=>l.id===s);this.undoMutation(r,s),a&&i.push({resource:r,mutationId:s,resourceId:a.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 a;let n=(a=i.id)==null?void 0:a.value;if(!n)return;let{cleanedPayload:r,nestedMutations:s}=this.extractNestedRelations(e,i);s.forEach(l=>{this.addMutation(l.resource,l);}),this.addMutation(e,{id:n,type:"SYNC",resource:e,resourceId:n,op:"INSERT",payload:r});});}extractNestedRelations(e,t){let i=this.schema[e],n={...t},r=[];return i!=null&&i.relations?(Object.entries(t).forEach(([s,a])=>{var c;let l=i.relations[s];if(!l)return;let u=l.entity.name,d=a==null?void 0:a.value;if(l.type==="one"){if(d&&typeof d=="object"&&!Array.isArray(d)&&((c=d.id)!=null&&c.value)){let p=d.id.value,m={...d},{cleanedPayload:f,nestedMutations:g}=this.extractNestedRelations(u,m);r.push(...g),r.push({id:p,type:"SYNC",resource:u,resourceId:p,op:"INSERT",payload:f}),delete n[s];}}else l.type==="many"&&Array.isArray(d)&&(d.forEach(p=>{var m,f;if(p&&typeof p=="object"&&!Array.isArray(p)&&((f=(m=p.value)==null?void 0:m.id)!=null&&f.value)){let g=p.value.id.value,E={...p.value},{cleanedPayload:_,nestedMutations:D}=this.extractNestedRelations(u,E);r.push(...D),r.push({id:g,type:"SYNC",resource:u,resourceId:g,op:"INSERT",payload:_});}}),delete n[s]);}),{cleanedPayload:n,nestedMutations:r}):{cleanedPayload:n,nestedMutations:r}}removeFromPool(e,t){var i,n;this.schema[e]&&((i=this.rawObjPool[e])==null||delete i[t],(n=this.optimisticRawObjPool[e])==null||delete n[t],this.kvStorage.delete(e,t),this.optimisticObjGraph.removeNode(t),this.notifyCollectionSubscribers(e),this.optimisticObjGraph.notifySubscribers(t));}updateRawObjPool(e,t,i,n){var a;if(!this.schema[e])return;let r=(a=this.rawObjPool[e])==null?void 0:a[t],s=(this.optimisticMutationStack[e]??[]).reduce((l,u)=>u.resourceId!==t?l:this.schema[e].mergeMutation("set",u.payload,l)[0],r);if(this.optimisticRawObjPool[e]??={},s?this.optimisticRawObjPool[e][t]={value:{...s.value,id:{value:t}}}:delete this.optimisticRawObjPool[e][t],!(!this.optimisticObjGraph.hasNode(t)&&!s)){if(this.optimisticObjGraph.hasNode(t)||this.optimisticObjGraph.createNode(t,e,Object.values(this.schema[e].relations).flatMap(l=>l.type==="many"?[l.entity.name]:[])),Object.keys(this.schema[e].relations).length>0){let l=Object.fromEntries(Object.entries(this.schema[e].relations).flatMap(([u,d])=>d.type==="one"?[[d.relationalColumn,u]]:[]));Object.entries(i).forEach(([u,d])=>{let c=this.schema[e].relations[l[u]];if(!l[u])return;let p=n==null?void 0:n.value[u],[,m]=c.mergeMutation("set",d,p);if(m){if(!this.optimisticObjGraph.hasNode(m.value)){let f=c.entity.name;this.optimisticObjGraph.createNode(m.value,f,Object.values(this.schema[f].relations).flatMap(g=>g.type==="many"?[g.entity.name]:[]));}p!=null&&p.value&&this.optimisticObjGraph.removeLink(t,c.entity.name),this.optimisticObjGraph.createLink(t,m.value);}});}this.notifyCollectionSubscribers(e),this.optimisticObjGraph.notifySubscribers(t);}}materializeOneWithInclude(e,t={}){var l;if(!e)return;let i=this.optimisticObjGraph.getNode(e);if(!i)return;let n=i.type,r=(l=this.optimisticRawObjPool[n])==null?void 0:l[e];if(!r)return;let[s,a]=Object.entries(t).reduce((u,[d,c])=>{let p=this.schema[n].relations[d];return p&&(p.type==="one"?u[0].push([d,p.entity.name,c??true]):p.type==="many"&&u[1].push([d,p.entity.name,c??true])),u},[[],[]]);return {value:{...r.value,...Object.fromEntries(s.map(([u,d,c])=>[u,this.materializeOneWithInclude(i.references.get(d),j(c)?c.include??{}:typeof c=="object"&&c!==null?c:{})])),...Object.fromEntries(a.map(([u,d,c])=>{let p=i.referencedBy.get(d),m=p instanceof Set;return [u,m?{value:Array.from(p.values()).map(f=>this.materializeOneWithInclude(f,j(c)?c.include??{}:typeof c=="object"&&c!==null?c:{}))}:this.materializeOneWithInclude(p,j(c)?c.include??{}:typeof c=="object"&&c!==null?c:{})]}))}}}notifyCollectionSubscribers(e){this.collectionSubscriptions.forEach(t=>{var i,n;if(t.query.resource===e||(i=t.flatInclude)!=null&&i.includes(e)){let r=T(t.query),s=this.querySnapshots[r],a=this.get(t.query,void 0,true);if(Ge(a,s))return;this.querySnapshots[r]=a,(n=this.onQuerySubscriptionTriggered)==null||n.call(this,t.query),t.callbacks.forEach(l=>{l(a);});}});}flattenIncludes(e,t){let i=[];return Object.entries(e).forEach(([n,r])=>{var l;let s=(l=this.schema[t])==null?void 0:l.relations[n];if(!s)return;let a=s.entity.name;if(i.push(a),typeof r=="object"&&r!==null){let u=j(r)?r.include??{}:r;i.push(...this.flattenIncludes(u,a));}}),Array.from(new Set(i))}};var ve={pending:0,local:1,remote:2},z=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)}},se=class{url;ws;store;logger;optimisticMutations;remoteSubscriptions=new Map;eventListeners=new Set;replyHandlers={};_bootstrapStatus="pending";storageLoadedCount=0;expectedStorageLoads;constructor(e){var t,i,n,r;this.url=e.url,this.logger=de({level:e.logLevel??C.INFO}),this.optimisticMutations=e.optimisticMutations,this.expectedStorageLoads=e.storage===false?0:Object.keys(e.schema).length,this.store=new G(e.schema,e.storage,this.logger,()=>{this.replayCustomMutationStack();},(s,a)=>{this.emitEvent({type:"CLIENT_STORAGE_LOADED",resource:s,itemCount:a}),this.storageLoadedCount+=1,this.expectedStorageLoads>0&&this.storageLoadedCount>=this.expectedStorageLoads&&this.setBootstrapStatus("local");},s=>{this.emitEvent({type:"QUERY_SUBSCRIPTION_TRIGGERED",query:s});}),this.ws=new N({url:e.url,autoConnect:((t=e.connection)==null?void 0:t.autoConnect)??true,autoReconnect:((i=e.connection)==null?void 0:i.autoReconnect)??true,reconnectTimeout:((n=e.connection)==null?void 0:n.reconnectTimeout)??5e3,reconnectLimit:(r=e.connection)==null?void 0:r.maxReconnectAttempts,credentials:e.credentials}),this.ws.addEventListener("message",s=>{this.handleServerMessage(s.data);}),this.ws.addEventListener("connectionChange",s=>{this.emitEvent({type:"CONNECTION_STATE_CHANGE",open:s.open}),s.open&&(Array.from(this.remoteSubscriptions.values()).forEach(({query:a$1})=>{this.sendWsMessage({id:a(),type:"SUBSCRIBE",...a$1});}),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,n,r;try{this.logger.debug("Message received from the server:",e);let s=fe.parse(JSON.parse(e));if(this.logger.debug("Parsed message:",s),this.emitEvent({type:"MESSAGE_RECEIVED",message:s}),s.type==="SYNC"){let{resource:a,id:l,resourceId:u,op:d}=s;this.emitEvent({type:"MUTATION_RECEIVED",mutationId:l,resource:a,resourceId:u,procedure:d??"UNKNOWN"});try{this.store.addMutation(a,s);}catch(c){this.logger.error("Error merging sync delta from the server:",c);}}else if(s.type==="REJECT"){if(this.replyHandlers[s.id]){clearTimeout(this.replyHandlers[s.id].timeoutHandle),this.emitUndoEvents(this.store.undoCustomMutation(s.id));let u=s.message??"Mutation rejected";(i=(t=this.replyHandlers[s.id]).reject)==null||i.call(t,new Error(u)),delete this.replyHandlers[s.id];}let a=((n=this.store.optimisticMutationStack[s.resource])==null?void 0:n.length)??0,l=(r=this.store.optimisticMutationStack[s.resource])==null?void 0:r.find(u=>u.id===s.id);this.store.undoMutation(s.resource,s.id),this.emitEvent({type:"MUTATION_REJECTED",mutationId:s.id,resource:s.resource}),l&&this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:s.id,resource:s.resource,resourceId:l.resourceId,pendingMutations:a-1});}else if(s.type==="REPLY"){let{id:a,data:l}=s;if(this.replyHandlers[a]){clearTimeout(this.replyHandlers[a].timeoutHandle),this.replyHandlers[a].handler(l);return}let u=Te.parse(l);this.emitEvent({type:"DATA_LOAD_REPLY",resource:u.resource,itemCount:u.data.length}),this.store.loadConsolidatedState(u.resource,u.data),this.emitEvent({type:"STORE_STATE_UPDATED",resource:u.resource,itemCount:u.data.length}),this.setBootstrapStatus("remote");}}catch(s){this.logger.error("Error parsing message from the server:",s);}}load(e){let t=a(),i=T(e);this.emitEvent({type:"DATA_LOAD_REQUESTED",query:e,subscriptionId:t}),this.sendWsMessage({id:t,type:"SUBSCRIBE",...e});let n=!this.remoteSubscriptions.has(i);return this.remoteSubscriptions.has(i)?this.remoteSubscriptions.get(i).subCounter+=1:this.remoteSubscriptions.set(i,{query:e,subCounter:1}),n&&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:a(),type:"UNSUBSCRIBE",...e}),this.emitEvent({type:"SUBSCRIPTION_REMOVED",query:e,subscriptionKey:i}));}}}subscribe(e,t){return this.store.subscribe(e,t)}genericMutate(e,t,i){var a$2,l;let n=(a$2=this.ws)==null?void 0:a$2.connected(),r=(l=this.optimisticMutations)==null?void 0:l.getHandler(e,t);if(!n&&!r)throw new Error("WebSocket not connected");let s={id:a(),type:"MUTATE",resource:e,procedure:t,payload:i,meta:{timestamp:new Date().toISOString()}};if(r)try{let{proxy:u,getOperations:d}=a$1(this.store,this.store.schema);r({input:i,storage:u});let c=d(),p=this.applyOptimisticOperations(c);this.store.registerCustomMutation(s.id,p),this.emitEvent({type:"MUTATION_SENT",mutationId:s.id,resource:e,resourceId:"",procedure:t,optimistic:!0});}catch(u){throw this.logger.error("Error executing optimistic handler:",u),this.emitUndoEvents(this.store.undoCustomMutation(s.id)),u}else this.emitEvent({type:"MUTATION_SENT",mutationId:s.id,resource:e,resourceId:"",procedure:t,optimistic:false});return n?(this.sendWsMessage(s),new Promise((u,d)=>{this.replyHandlers[s.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[s.id],this.emitUndoEvents(this.store.undoCustomMutation(s.id)),d(new Error("Reply timeout"));},5e3),handler:c=>{delete this.replyHandlers[s.id],this.store.confirmCustomMutation(s.id),u(c);},reject:d};})):(this.store.addCustomMutationMessage(s),Promise.resolve(void 0))}applyOptimisticOperations(e){var i;let t=[];try{for(let n of e){let r=a(),s=new Date().toISOString(),a$1={id:r,type:"SYNC",resource:n.resource,resourceId:n.id,op:n.type==="insert"?"INSERT":"UPDATE",payload:this.store.schema[n.resource].encodeMutation("set",n.data,s)},l=(((i=this.store.optimisticMutationStack[n.resource])==null?void 0:i.length)??0)+1;this.store.addMutation(n.resource,a$1,!0),t.push({resource:n.resource,mutationId:r}),this.emitEvent({type:"OPTIMISTIC_MUTATION_APPLIED",mutationId:r,resource:n.resource,resourceId:n.id,procedure:n.type==="insert"?"INSERT":"UPDATE",pendingMutations:l});}return t}catch(n){for(let{resource:r,mutationId:s}of t)this.store.undoMutation(r,s);throw n}}emitUndoEvents(e){var t;for(let{resource:i,mutationId:n,resourceId:r}of e){let s=((t=this.store.optimisticMutationStack[i])==null?void 0:t.length)??0;this.emitEvent({type:"OPTIMISTIC_MUTATION_UNDONE",mutationId:n,resource:i,resourceId:r,pendingMutations:s});}}genericQuery(e,t,i){if(!this.ws||!this.ws.connected())throw new Error("WebSocket not connected");let n={id:a(),type:"CUSTOM_QUERY",resource:e,procedure:t,input:i};return this.sendWsMessage(n),new Promise((r,s)=>{this.replyHandlers[n.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[n.id],s(new Error("Reply timeout"));},5e3),handler:a=>{delete this.replyHandlers[n.id],r(a);},reject:s};})}get bootstrapStatus(){return this._bootstrapStatus}setBootstrapStatus(e){ve[e]<=ve[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);});}},ei=o=>{let e=new se(o),t=(i,n)=>new Proxy(n,{get(r,s,a){if(s in r)return Reflect.get(r,s,a);if(typeof s=="string")return l=>new z(e,{resource:i,procedure:s,input:l})}});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,n){if(typeof n=="string")return Object.hasOwn(o.schema,n)?t(n,k._init(o.schema[n],e)):new Proxy({},{get(r,s){if(typeof s=="string")return a=>new z(e,{resource:n,procedure:s,input:a})}})},has(i,n){return typeof n=="string"}}),mutate:c(()=>{},{apply:(i,n,r)=>{if(n.length<2)return;if(n.length>2)throw new Error("Trying to access an invalid path");let[s,a]=n;return e.genericMutate(s,a,r[0])}})}}};export{ei as createClient,Ze as useClientState,Xe as useLiveQuery,et as useLoadData};
@@ -1,4 +1,4 @@
1
- import { C as ClientOptions, a as ClientRouterConstraint, b as Client } from './index-C0Qm5yHg.js';
1
+ import { C as ClientOptions, a as ClientRouterConstraint, b as Client } from './index-DOU7wys1.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';
4
4
 
@@ -1 +1 @@
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};
1
+ import {c,b}from'./chunk-YPTDCIAN.js';var y=async(r,n,i)=>{let t=s=>{if(!s)return {};if(s instanceof Headers){let f={};return s.forEach((g,m)=>{f[m]=g;}),f}return Array.isArray(s)?Object.fromEntries(s):s},c=t(i==null?void 0:i.headers),a=t(n==null?void 0:n.headers),o={...i,...n,headers:{...c,...a}},e=await fetch(r,o),u;try{u=await e.json();}catch{u=await e.text().catch(()=>{});}if(!e.ok)throw new Error(`Failed to fetch: ${e.status} ${e.statusText}`,{cause:u});return u},w=r=>{let n=r.url.replace(/\/+$/,"");return {query:new Proxy({},{get(i,t){if(typeof t=="string")return new Proxy({},{get(c,a){if(typeof a=="string")return async o=>{let e=await b(r.credentials)??{};return await y(`${n}/${t}/query/${a}`,{method:"POST",headers:{...e,"Content-Type":"application/json"},body:JSON.stringify({input:o})},r.fetchOptions)}}})},has(i,t){return typeof t=="string"}}),mutate:c(()=>{},{apply:async(i,t,c)=>{if(t.length<2)return;if(t.length>2)throw new Error("Trying to access an invalid path");let[a,o]=t,e=await b(r.credentials)??{};return await y(`${n}/${a}/${o}`,{method:"POST",headers:{...e,"Content-Type":"application/json"},body:JSON.stringify({payload:c[0],meta:{timestamp:new Date().toISOString()}})},r.fetchOptions)}})}};export{w as createClient};
@@ -471,11 +471,17 @@ type ConditionalPromise<T, P extends boolean> = P extends true ? Promise<T> : T;
471
471
  type PromiseOrSync<T> = T | Promise<T>;
472
472
  type Generatable<T, Arg = never> = T | ((arg: Arg) => T);
473
473
 
474
+ /**
475
+ * Internal Tracked Query representation. A Custom Query handler returns an
476
+ * unresolved query builder; the server mints a `RawQueryRequest` from it via
477
+ * `buildQueryRequest()`, which the query engine subscribes and resolves against
478
+ * storage. This is **not** an inbound client→server message — clients can only
479
+ * invoke named Custom Query procedures (see ADR-0002).
480
+ */
474
481
  declare const querySchema: z.ZodObject<{
475
482
  resource: z.ZodString;
476
483
  where: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
477
484
  include: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
478
- lastSyncedAt: z.ZodOptional<z.ZodString>;
479
485
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
480
486
  sort: z.ZodOptional<z.ZodArray<z.ZodObject<{
481
487
  key: z.ZodString;
@@ -496,7 +502,26 @@ type CustomQueryRequest = z.infer<typeof customQuerySchema>;
496
502
  /** biome-ignore-all lint/complexity/noBannedTypes: <explanation> */
497
503
 
498
504
  type InferQueryResult<TCollection extends LiveObjectAny, TInclude extends IncludeClause<TCollection>, TSingle extends boolean = false> = TSingle extends true ? Simplify<InferLiveObject<TCollection, TInclude>> | undefined : Simplify<InferLiveObject<TCollection, TInclude>>[];
505
+ /**
506
+ * Type-only brand recording a {@link QueryBuilder}'s inferable parameters.
507
+ *
508
+ * `CustomQueryResult` (client entry point) has to recognise a query-builder
509
+ * value returned from a route handler whose type flows through the *server*
510
+ * entry point. The two entry points are emitted as separate `.d.ts` graphs, so
511
+ * each gets its own `declare class QueryBuilder`; because the class has
512
+ * `private` members, TypeScript compares those declarations *nominally* and any
513
+ * `extends QueryBuilder<...>` check across the boundary fails. Narrowing on this
514
+ * structural brand instead makes the check independent of class identity — and
515
+ * therefore also of duplicate installed package versions.
516
+ */
517
+ interface QueryBuilderBrand<TCollection extends LiveObjectAny, TInclude extends IncludeClause<TCollection>, TSingle extends boolean> {
518
+ collection: TCollection;
519
+ include: TInclude;
520
+ single: TSingle;
521
+ }
499
522
  declare class QueryBuilder<TCollection extends LiveObjectAny, TInclude extends IncludeClause<TCollection> = {}, TSingle extends boolean = false, TShouldAwait extends boolean = false> {
523
+ /** Never assigned at runtime; exists only to carry {@link QueryBuilderBrand}. */
524
+ readonly __queryBuilderBrand: QueryBuilderBrand<TCollection, TInclude, TSingle>;
500
525
  private _collection;
501
526
  private _client;
502
527
  private _where;
@@ -532,7 +557,7 @@ declare class QueryBuilder<TCollection extends LiveObjectAny, TInclude extends I
532
557
  * Supports Standard Schema (via ~standard property) and Zod schemas (via _output property for backward compatibility).
533
558
  */
534
559
  type InferSchema$1<T> = T extends {
535
- "~standard": {
560
+ '~standard': {
536
561
  types?: {
537
562
  output: infer U;
538
563
  };
@@ -553,49 +578,73 @@ type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
553
578
  type CustomQueryLoadable<TOutput> = PromiseLike<TOutput> & {
554
579
  buildQueryRequest: () => CustomQueryRequest;
555
580
  };
556
- type CustomQueryResult<TOutput, TShouldAwait extends boolean = false> = UnwrapPromise<TOutput> extends QueryBuilder<infer TCollection, infer TInclude, infer TSingle, any> ? TShouldAwait extends true ? TSingle extends true ? Promise<Simplify<InferLiveObject<TCollection, TInclude>> | undefined> : Promise<Simplify<InferLiveObject<TCollection, TInclude>>[]> : TSingle extends true ? CustomQueryLoadable<Simplify<InferLiveObject<TCollection, TInclude>> | undefined> : CustomQueryLoadable<Simplify<InferLiveObject<TCollection, TInclude>>[]> : Promisify<UnwrapPromise<TOutput>>;
581
+ /**
582
+ * Narrow a custom-query handler return type to its loadable client shape.
583
+ *
584
+ * The match keys off {@link QueryBuilderBrand} — a structural, type-only brand —
585
+ * rather than `extends QueryBuilder<...>`. `QueryBuilder` carries `private`
586
+ * members, so its class identity is nominal and the server- and client-bundle
587
+ * `.d.ts` graphs emit two incompatible declarations; a class-based check fails
588
+ * for published consumers who import the router from `@live-state/sync/server`
589
+ * and the client from `@live-state/sync/client`. The brand is compared by shape,
590
+ * so it survives that split (and duplicate installed versions).
591
+ */
592
+ type CustomQueryResult<TOutput, TShouldAwait extends boolean = false> = UnwrapPromise<TOutput> extends {
593
+ readonly __queryBuilderBrand: {
594
+ collection: infer TCollection extends LiveObjectAny;
595
+ include: infer TInclude;
596
+ single: infer TSingle;
597
+ };
598
+ } ? // `TInclude` is inferred unconstrained; intersecting with its declared
599
+ TInclude & IncludeClause<TCollection> extends infer TInc extends IncludeClause<TCollection> ? TShouldAwait extends true ? TSingle extends true ? Promise<Simplify<InferLiveObject<TCollection, TInc>> | undefined> : Promise<Simplify<InferLiveObject<TCollection, TInc>>[]> : TSingle extends true ? CustomQueryLoadable<Simplify<InferLiveObject<TCollection, TInc>> | undefined> : CustomQueryLoadable<Simplify<InferLiveObject<TCollection, TInc>>[]> : never : Promisify<UnwrapPromise<TOutput>>;
557
600
  type CustomQueryFunction<TInput, TOutput, TShouldAwait extends boolean = false> = [TInput] extends [never] | [undefined] ? () => CustomQueryResult<TOutput, TShouldAwait> : (input: TInput) => CustomQueryResult<TOutput, TShouldAwait>;
558
601
  /**
559
- * Simplified router constraint for client-side usage.
560
- * This avoids importing server-internal types like Storage and Hooks,
561
- * which can cause type incompatibilities when the package is bundled.
602
+ * Simplified, client-safe view of a route. Routes are now procedure-only
603
+ * (decoupled from the schema, see ADR-0002); a resource is queryable by virtue
604
+ * of being in the `schema`, not because a route is declared for it.
562
605
  */
563
- type ClientRouterConstraint = {
564
- routes: Record<string, {
565
- resourceSchema: LiveObjectAny | undefined;
566
- customMutations: Record<string, {
567
- _type: "mutation";
568
- inputValidator: StandardSchemaV1<any, any>;
569
- handler: (...args: any[]) => any;
570
- }>;
571
- customQueries: Record<string, {
572
- _type: "query";
573
- inputValidator: StandardSchemaV1<any, any>;
574
- handler: (...args: any[]) => any;
575
- }>;
606
+ type ClientRouteConstraint = {
607
+ customMutations: Record<string, {
608
+ _type: 'mutation';
609
+ inputValidator: StandardSchemaV1<any, any>;
610
+ handler: (...args: any[]) => any;
611
+ }>;
612
+ customQueries: Record<string, {
613
+ _type: 'query';
614
+ inputValidator: StandardSchemaV1<any, any>;
615
+ handler: (...args: any[]) => any;
576
616
  }>;
577
617
  };
578
- type CollectionQueryType<TRoute extends ClientRouterConstraint["routes"][string], TShouldAwait extends boolean> = TRoute["resourceSchema"] extends LiveObjectAny ? QueryBuilder<TRoute["resourceSchema"], {}, false, TShouldAwait> & {
579
- [K2 in keyof TRoute["customQueries"]]: CustomQueryFunction<InferSchema$1<TRoute["customQueries"][K2]["inputValidator"]>, ReturnType<TRoute["customQueries"][K2]["handler"]>, TShouldAwait>;
580
- } : {
581
- [K2 in keyof TRoute["customQueries"]]: CustomQueryFunction<InferSchema$1<TRoute["customQueries"][K2]["inputValidator"]>, ReturnType<TRoute["customQueries"][K2]["handler"]>, TShouldAwait>;
618
+ type ClientRouterConstraint = {
619
+ schema: Record<string, LiveObjectAny>;
620
+ routes: Record<string, ClientRouteConstraint>;
582
621
  };
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. */
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. */
587
- update: (id: string, value: Simplify<InferUpdate<TRoute["resourceSchema"]>>) => ConditionalPromise<void, TShouldAwait>;
588
- }, Extract<keyof TRoute["customMutations"], "insert" | "update">> & {
589
- [K2 in keyof TRoute["customMutations"]]: CustomMutationFunction<InferSchema$1<TRoute["customMutations"][K2]["inputValidator"]>, ReturnType<TRoute["customMutations"][K2]["handler"]>>;
590
- } : {
591
- [K2 in keyof TRoute["customMutations"]]: CustomMutationFunction<InferSchema$1<TRoute["customMutations"][K2]["inputValidator"]>, ReturnType<TRoute["customMutations"][K2]["handler"]>>;
622
+ type CustomQueryMethods<TRoute extends ClientRouteConstraint, TShouldAwait extends boolean> = {
623
+ [K2 in keyof TRoute['customQueries']]: CustomQueryFunction<InferSchema$1<TRoute['customQueries'][K2]['inputValidator']>, ReturnType<TRoute['customQueries'][K2]['handler']>, TShouldAwait>;
624
+ };
625
+ /**
626
+ * The client `store.query.<resource>` surface, asymmetric by client (ADR-0002):
627
+ *
628
+ * - **Websocket** (`TShouldAwait = false`): every resource in the `schema`
629
+ * exposes a `QueryBuilder` **Local Query** — `.where()/.get()/.subscribe()`
630
+ * read the optimistic store with no server round-trip (consumed by
631
+ * `useLiveQuery`) — merged with the declared **Custom Query** procedures of a
632
+ * route of the same name (if any).
633
+ * - **Fetch** (`TShouldAwait = true`): no optimistic store to back a Local
634
+ * Query, so only the declared Custom Query procedures are exposed.
635
+ */
636
+ type WsQueryType<TRouter extends ClientRouterConstraint, K> = (K extends keyof TRouter['schema'] ? TRouter['schema'][K] extends LiveObjectAny ? QueryBuilder<TRouter['schema'][K], {}, false, false> : unknown : unknown) & (K extends keyof TRouter['routes'] ? CustomQueryMethods<TRouter['routes'][K], false> : unknown);
637
+ type CollectionMutateType<TRoute extends ClientRouteConstraint> = {
638
+ [K2 in keyof TRoute['customMutations']]: CustomMutationFunction<InferSchema$1<TRoute['customMutations'][K2]['inputValidator']>, ReturnType<TRoute['customMutations'][K2]['handler']>>;
592
639
  };
593
640
  type Client$1<TRouter extends ClientRouterConstraint, TShouldAwait extends boolean = false> = {
594
- query: {
595
- [K in keyof TRouter["routes"]]: CollectionQueryType<TRouter["routes"][K], TShouldAwait>;
641
+ query: TShouldAwait extends true ? {
642
+ [K in keyof TRouter['routes']]: CustomQueryMethods<TRouter['routes'][K], true>;
643
+ } : {
644
+ [K in keyof TRouter['schema'] | keyof TRouter['routes']]: WsQueryType<TRouter, K>;
596
645
  };
597
646
  mutate: {
598
- [K in keyof TRouter["routes"]]: CollectionMutateType<TRouter["routes"][K], TShouldAwait>;
647
+ [K in keyof TRouter['routes']]: CollectionMutateType<TRouter['routes'][K]>;
599
648
  };
600
649
  };
601
650
 
@@ -691,30 +740,7 @@ type OptimisticMutationsRegistry<TSchema extends Schema<any>> = {
691
740
  getHandler: (route: string, procedure: string) => OptimisticMutationHandler<TSchema, any> | undefined;
692
741
  };
693
742
 
694
- declare const defaultMutationMsgSchema: z.ZodObject<{
695
- type: z.ZodLiteral<"MUTATE">;
696
- resource: z.ZodString;
697
- resourceId: z.ZodOptional<z.ZodString>;
698
- procedure: z.ZodEnum<{
699
- INSERT: "INSERT";
700
- UPDATE: "UPDATE";
701
- }>;
702
- payload: z.ZodRecord<z.ZodString, z.ZodObject<{
703
- value: z.ZodNullable<z.ZodAny>;
704
- _meta: z.ZodOptional<z.ZodObject<{
705
- timestamp: z.ZodNullable<z.ZodOptional<z.ZodString>>;
706
- }, z.core.$strip>>;
707
- }, z.core.$strip>>;
708
- meta: z.ZodOptional<z.ZodObject<{
709
- timestamp: z.ZodOptional<z.ZodString>;
710
- originMutationId: z.ZodOptional<z.ZodString>;
711
- }, z.core.$strip>>;
712
- id: z.ZodString;
713
- }, z.core.$strip>;
714
- type DefaultMutationMessage = Omit<z.infer<typeof defaultMutationMsgSchema>, 'resourceId'> & {
715
- resourceId: string;
716
- };
717
- declare const mutationMsgSchema: z.ZodUnion<readonly [z.ZodObject<{
743
+ declare const mutationMsgSchema: z.ZodObject<{
718
744
  type: z.ZodLiteral<"MUTATE">;
719
745
  resource: z.ZodString;
720
746
  resourceId: z.ZodOptional<z.ZodString>;
@@ -725,13 +751,16 @@ declare const mutationMsgSchema: z.ZodUnion<readonly [z.ZodObject<{
725
751
  originMutationId: z.ZodOptional<z.ZodString>;
726
752
  }, z.core.$strip>>;
727
753
  id: z.ZodString;
728
- }, z.core.$strip>, z.ZodObject<{
729
- type: z.ZodLiteral<"MUTATE">;
754
+ }, z.core.$strip>;
755
+ type MutationMessage = z.infer<typeof mutationMsgSchema>;
756
+ declare const syncDeltaMsgSchema: z.ZodObject<{
757
+ type: z.ZodLiteral<"SYNC">;
730
758
  resource: z.ZodString;
731
- resourceId: z.ZodOptional<z.ZodString>;
732
- procedure: z.ZodEnum<{
759
+ resourceId: z.ZodString;
760
+ op: z.ZodEnum<{
733
761
  INSERT: "INSERT";
734
762
  UPDATE: "UPDATE";
763
+ DELETE: "DELETE";
735
764
  }>;
736
765
  payload: z.ZodRecord<z.ZodString, z.ZodObject<{
737
766
  value: z.ZodNullable<z.ZodAny>;
@@ -744,8 +773,8 @@ declare const mutationMsgSchema: z.ZodUnion<readonly [z.ZodObject<{
744
773
  originMutationId: z.ZodOptional<z.ZodString>;
745
774
  }, z.core.$strip>>;
746
775
  id: z.ZodString;
747
- }, z.core.$strip>]>;
748
- type MutationMessage = z.infer<typeof mutationMsgSchema>;
776
+ }, z.core.$strip>;
777
+ type SyncDeltaMessage = z.infer<typeof syncDeltaMsgSchema>;
749
778
  declare const serverMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
750
779
  id: z.ZodString;
751
780
  type: z.ZodLiteral<"REJECT">;
@@ -756,12 +785,13 @@ declare const serverMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
756
785
  type: z.ZodLiteral<"REPLY">;
757
786
  data: z.ZodAny;
758
787
  }, z.core.$strip>, z.ZodObject<{
759
- type: z.ZodLiteral<"MUTATE">;
788
+ type: z.ZodLiteral<"SYNC">;
760
789
  resource: z.ZodString;
761
- resourceId: z.ZodOptional<z.ZodString>;
762
- procedure: z.ZodEnum<{
790
+ resourceId: z.ZodString;
791
+ op: z.ZodEnum<{
763
792
  INSERT: "INSERT";
764
793
  UPDATE: "UPDATE";
794
+ DELETE: "DELETE";
765
795
  }>;
766
796
  payload: z.ZodRecord<z.ZodString, z.ZodObject<{
767
797
  value: z.ZodNullable<z.ZodAny>;
@@ -780,7 +810,7 @@ type ServerMessage = z.infer<typeof serverMessageSchema>;
780
810
  declare class OptimisticStore {
781
811
  readonly schema: Schema<any>;
782
812
  private rawObjPool;
783
- optimisticMutationStack: Record<string, DefaultMutationMessage[]>;
813
+ optimisticMutationStack: Record<string, SyncDeltaMessage[]>;
784
814
  customMutationStack: MutationMessage[];
785
815
  private optimisticObjGraph;
786
816
  private optimisticRawObjPool;
@@ -796,7 +826,7 @@ declare class OptimisticStore {
796
826
  constructor(schema: Schema<any>, storage: ClientOptions["storage"], logger: Logger, afterLoadMutations?: (stack: typeof this.optimisticMutationStack, customStack: MutationMessage[], customIndex: typeof this.customMutationIndex) => void, onStorageLoaded?: (resource: string, itemCount: number) => void, onQuerySubscriptionTriggered?: (query: RawQueryRequest) => void);
797
827
  get(query: RawQueryRequest, _queryKey?: string, force?: boolean): any;
798
828
  subscribe(query: RawQueryRequest, listener: (v: any[]) => void): () => void;
799
- addMutation(routeName: string, mutation: DefaultMutationMessage, optimistic?: boolean): void;
829
+ addMutation(routeName: string, mutation: SyncDeltaMessage, optimistic?: boolean): void;
800
830
  undoMutation(routeName: string, mutationId: string): void;
801
831
  addCustomMutationMessage(message: MutationMessage): void;
802
832
  registerCustomMutation(messageId: string, mutations: Array<{
@@ -810,8 +840,15 @@ declare class OptimisticStore {
810
840
  resourceId: string;
811
841
  }>;
812
842
  getCustomMutationMutationIds(): Set<string>;
813
- loadConsolidatedState(resourceType: string, data: DefaultMutationMessage["payload"][]): void;
843
+ loadConsolidatedState(resourceType: string, data: SyncDeltaMessage["payload"][]): void;
814
844
  private extractNestedRelations;
845
+ /**
846
+ * Drop a row from every local store surface in response to a scope-out
847
+ * (`DELETE`) delta, then notify subscribers so windowed queries re-derive.
848
+ * Any pending optimistic mutation for the row is left untouched — it is
849
+ * reconciled through its own reply/reject path.
850
+ */
851
+ private removeFromPool;
815
852
  private updateRawObjPool;
816
853
  private materializeOneWithInclude;
817
854
  private notifyCollectionSubscribers;
@@ -920,7 +957,7 @@ type ClientStorageLoadedEvent = {
920
957
  };
921
958
  type DataLoadRequestedEvent = {
922
959
  type: "DATA_LOAD_REQUESTED";
923
- query: RawQueryRequest | CustomQueryRequest;
960
+ query: CustomQueryRequest;
924
961
  subscriptionId: string;
925
962
  };
926
963
  type DataLoadReplyEvent = {
@@ -951,13 +988,13 @@ type MutationRejectedEvent = {
951
988
  };
952
989
  type SubscriptionCreatedEvent = {
953
990
  type: "SUBSCRIPTION_CREATED";
954
- query: RawQueryRequest | CustomQueryRequest;
991
+ query: CustomQueryRequest;
955
992
  subscriptionKey: string;
956
993
  subscriberCount: number;
957
994
  };
958
995
  type SubscriptionRemovedEvent = {
959
996
  type: "SUBSCRIPTION_REMOVED";
960
- query: RawQueryRequest | CustomQueryRequest;
997
+ query: CustomQueryRequest;
961
998
  subscriptionKey: string;
962
999
  };
963
1000
  type QueryExecutedEvent = {
@@ -1000,7 +1037,7 @@ type Client<TRouter extends ClientRouterConstraint> = {
1000
1037
  ws: WebSocketClient;
1001
1038
  readonly bootstrapStatus: ClientBootstrapStatus;
1002
1039
  addEventListener: (listener: (event: ClientEvents) => void) => () => void;
1003
- load: (query: RawQueryRequest | CustomQueryRequest) => () => void;
1040
+ load: (query: CustomQueryRequest) => () => void;
1004
1041
  };
1005
1042
  store: Client$1<TRouter>;
1006
1043
  };
@@ -1016,7 +1053,7 @@ type ClientState = {
1016
1053
  };
1017
1054
  declare const useClientState: (client: Client<ClientRouterConstraint>["client"]) => ClientState;
1018
1055
  declare const useLoadData: (client: Client<ClientRouterConstraint>["client"], query: {
1019
- buildQueryRequest: () => RawQueryRequest | CustomQueryRequest;
1056
+ buildQueryRequest: () => CustomQueryRequest;
1020
1057
  }) => void;
1021
1058
 
1022
1059
  type ClientOptions<TSchema extends Schema<any> = Schema<any>> = {
@@ -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-C0Qm5yHg.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-DOU7wys1.js';
2
2
  import '@standard-schema/spec';
3
3
  import 'zod';