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