@live-state/sync 0.0.1 → 0.0.3

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 L="0123456789ABCDEFGHJKMNPQRSTVWXYZ";var l;(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";})(l||(l={}));var u=class extends Error{constructor(t,n){super(`${n} (${t})`),this.name="ULIDError",this.code=t;}};function I(e){let t=Math.floor(e()*32);return t===32&&(t=31),L.charAt(t)}function M(e){let t=E(),n=t&&(t.crypto||t.msCrypto)||null;if(typeof(n==null?void 0:n.getRandomValues)=="function")return ()=>{let i=new Uint8Array(1);return n.getRandomValues(i),i[0]/255};if(typeof(n==null?void 0:n.randomBytes)=="function")return ()=>n.randomBytes(1).readUInt8()/255;throw new u(l.PRNGDetectFailure,"Failed to find a reliable PRNG")}function E(){return O()?self:typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:null}function A(e,t){let n="";for(;e>0;e--)n=I(t)+n;return n}function _(e,t=10){if(isNaN(e))throw new u(l.EncodeTimeValueMalformed,`Time must be a number: ${e}`);if(e>0xffffffffffff)throw new u(l.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${0xffffffffffff}: ${e}`);if(e<0)throw new u(l.EncodeTimeNegative,`Time must be positive: ${e}`);if(Number.isInteger(e)===false)throw new u(l.EncodeTimeValueMalformed,`Time must be an integer: ${e}`);let n,i="";for(let r=t;r>0;r--)n=e%32,i=L.charAt(n)+i,e=(e-n)/32;return i}function O(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function b(e,t){let n=M(),i=Date.now();return _(i,10)+A(16,n)}var j=()=>b().toLowerCase(),V=(e,t)=>typeof e=="function"?e(t):e;var w=(e,t,n=[])=>new Proxy(e,{get:(i,r)=>{var p,T;if(r==="__isProxy__")return true;let o=(p=t.get)==null?void 0:p.call(t,i,[...n,r]);if(o!==void 0)return o;let a=i,s=r;return (T=a[s])!=null&&T.__isProxy__||(a[s]=w(typeof a[s]=="object"?a[s]:()=>{},t,[...n,r])),a[s]},apply:(i,r,o)=>{var a;return (a=t.apply)==null?void 0:a.call(t,i,n,o)}}),f=(e,t,n=false)=>Object.entries(t).every(([i,r])=>{if(i==="$and")return r.every(a=>f(e,a,n));if(i==="$or")return r.some(a=>f(e,a,n));let o=(r==null?void 0:r.$eq)!==void 0?r==null?void 0:r.$eq:r;if(typeof r=="object"&&r!==null&&(r==null?void 0:r.$eq)===void 0){if(r.$in!==void 0){let a=e[i];return a===void 0?false:n?!r.$in.includes(a):r.$in.includes(a)}if(r.$not!==void 0&&!n)return f(e,{[i]:r.$not},true);if(r.$gt!==void 0){let a=e[i];return typeof a!="number"?false:n?a<=r.$gt:a>r.$gt}if(r.$gte!==void 0){let a=e[i];return typeof a!="number"?false:n?a<r.$gte:a>=r.$gte}if(r.$lt!==void 0){let a=e[i];return typeof a!="number"?false:n?a>=r.$lt:a<r.$lt}if(r.$lte!==void 0){let a=e[i];return typeof a!="number"?false:n?a>r.$lte:a<=r.$lte}return !e[i]||typeof e[i]!="object"?false:f(e[i],r)}return n?e[i]!==o:e[i]===o}),D=(e,t,n)=>{let i=[],r=0;for(let o=0;o<e.length&&(n===void 0||r<n);o++)t(e[o],o)&&(i.push(e[o]),r++);return i};var R=e=>{if(e)return Array.isArray(e.value)?e.value.map(t=>R(t)):typeof e.value!="object"||e.value===null||e.value instanceof Date?e.value:Object.fromEntries(Object.entries(e.value).map(([t,n])=>[t,R(n)]))};export{j as a,V as b,w as c,f as d,D as e,R as f};
@@ -0,0 +1 @@
1
+ var L=Object.create;var h=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var M=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var j=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var O=(t,e,n,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of b(e))!I.call(t,i)&&i!==n&&h(t,i,{get:()=>e[i],enumerable:!(a=g(e,i))||a.enumerable});return t};var S=(t,e,n)=>(n=t!=null?L(M(t)):{},O(e||!t||!t.__esModule?h(n,"default",{value:t,enumerable:true}):n,t));var s=class{_value;_meta;_encodeInput;_decodeInput};var c=class extends s{inner;constructor(e){super(),this.inner=e;}encodeMutation(e,n,a){return this.inner.encodeMutation(e,n,a)}mergeMutation(e,n,a){return this.inner.mergeMutation(e,n,a)}getStorageFieldType(){return {...this.inner.getStorageFieldType(),nullable:true}}},o=class t extends s{storageType;convertFunc;isIndex;isUnique;defaultValue;foreignReference;isPrimary;constructor(e,n,a,i,r,u,y){super(),this.storageType=e,this.convertFunc=n,this.isIndex=a??false,this.isUnique=i??false,this.defaultValue=r,this.foreignReference=u,this.isPrimary=y??false;}encodeMutation(e,n,a){return {value:n,_meta:{timestamp:a}}}mergeMutation(e,n,a){return a&&a._meta.timestamp&&n._meta.timestamp&&a._meta.timestamp.localeCompare(n._meta.timestamp)>=0?[a,null]:[{value:this.convertFunc?this.convertFunc(n.value):n.value,_meta:n._meta},n]}getStorageFieldType(){return {type:this.storageType,nullable:false,index:this.isIndex,unique:this.isUnique,default:this.defaultValue,references:this.foreignReference,primary:this.isPrimary}}unique(){return new t(this.storageType,this.convertFunc,this.isIndex,true,this.defaultValue,this.foreignReference,this.isPrimary)}index(){return new t(this.storageType,this.convertFunc,true,this.isUnique,this.defaultValue,this.foreignReference,this.isPrimary)}default(e){return new t(this.storageType,this.convertFunc,this.isIndex,this.isUnique,e,this.foreignReference,this.isPrimary)}primary(){return new t(this.storageType,this.convertFunc,this.isIndex,this.isUnique,this.defaultValue,this.foreignReference,true)}nullable(){return new c(this)}},p=class t extends o{constructor(){super("integer",e=>Number(e));}static create(){return new t}},_=p.create,l=class t extends o{constructor(e){super("varchar",void 0,void 0,void 0,void 0,e);}static create(){return new t}static createId(){return new t().index().unique().primary()}static createReference(e){return new t(e)}},V=l.create,E=l.createId,C=l.createReference,d=class t extends o{constructor(){super("boolean",e=>typeof e=="string"?e.toLowerCase()==="true":!!e);}static create(){return new t}},F=d.create,m=class t extends o{constructor(){super("timestamp",e=>typeof e=="string"?new Date(e):e);}static create(){return new t}},q=m.create;var v=class t extends s{name;fields;relations;constructor(e,n,a){super(),this.name=e,this.fields=n,this.relations=a??{};}encodeMutation(e,n,a){return Object.fromEntries(Object.entries(n).map(([i,r])=>[i,(this.fields[i]??this.relations[i]).encodeMutation("set",r,a)]))}mergeMutation(e,n,a){let i={};return [{value:{...(a==null?void 0:a.value)??{},...Object.fromEntries(Object.entries(n).map(([r,u])=>{let y=this.fields[r]??this.relations[r];if(!y)return [r,u];let[R,f]=y.mergeMutation(e,u,a==null?void 0:a.value[r]);return f&&(i[r]=f),[r,R]}))}},i]}setRelations(e){return new t(this.name,this.fields,e)}getStorageFieldType(){throw new Error("Method not implemented.")}static create(e,n){return new t(e,n)}},$=v.create,T=class t extends s{entity;type;required;relationalColumn;foreignColumn;sourceEntity;constructor(e,n,a,i,r){super(),this.entity=e,this.type=n,this.required=r??false,this.relationalColumn=a,this.foreignColumn=i;}encodeMutation(e,n,a){if(e!=="set")throw new Error("Mutation type not implemented.");if(this.type==="many")throw new Error("Many not implemented.");return {value:n,_meta:{timestamp:a}}}mergeMutation(e,n,a){if(this.type==="many")throw new Error("Many not implemented.");return a&&a._meta.timestamp&&n._meta.timestamp&&a._meta.timestamp.localeCompare(n._meta.timestamp)>=0?[a,null]:[n,n]}getStorageFieldType(){return {type:"varchar",nullable:!this.required,references:`${this.entity.name}.${String(this.foreignColumn??this.relationalColumn??"id")}`}}toJSON(){return {entityName:this.entity.name,type:this.type,required:this.required,relationalColumn:this.relationalColumn,foreignColumn:this.foreignColumn}}static createOneFactory(){return (e,n,a)=>new t(e,"one",n,void 0,a??false)}static createManyFactory(){return (e,n,a)=>new t(e,"many",void 0,n,a??false)}},D=(t,e)=>({$type:"relations",objectName:t.name,relations:e({one:T.createOneFactory(),many:T.createManyFactory()})}),x=t=>{if(t)return Array.isArray(t.value)?t.value.map(e=>x(e)):typeof t.value!="object"||t.value===null||t.value instanceof Date?t.value:Object.fromEntries(Object.entries(t.value).map(([e,n])=>[e,x(n)]))},k=t=>Object.fromEntries(Object.entries(t).flatMap(([e,n])=>{if(n.$type==="relations")return [];let a=n,i=Object.values(t).find(r=>r.$type==="relations"&&r.objectName===n.name);return i&&(a=a.setRelations(i.relations)),[[a.name,a]]}));export{j as a,S as b,s as c,p as d,_ as e,l as f,V as g,E as h,C as i,d as j,F as k,m as l,q as m,v as n,$ as o,T as p,D as q,x as r,k as s};
package/dist/client.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { d as Client, C as ClientOptions, c as SubscriptionProvider, e as createClient, u as useLiveQuery } from './index-BS5EvFM-.js';
1
+ export { f as Client, e as ClientEvents, C as ClientOptions, d as ConnectionStateChangeEvent, M as MessageReceivedEvent, c as SubscriptionProvider, g as createClient, u as useLiveQuery } from './index-4Y_YcJTJ.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'zod';
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import {c,a,d,b}from'./chunk-2W2QGOPU.js';import {useState,useEffect}from'react';import {jsx,Fragment}from'react/jsx-runtime';import {z}from'zod';import {stringify}from'qs';import {openDB}from'idb';var X=d=>{let[e,t]=useState(()=>d.get());return useEffect(()=>d.subscribe(()=>{let i=d.get();t(i);}),[]),e},ee=({children:d,client:e})=>(useEffect(()=>{e.subscribe();},[]),jsx(Fragment,{children:d}));z.object({type:z.literal("QUERY"),resource:z.string(),where:z.record(z.any()).optional(),include:z.record(z.any()).optional()});var j=z.record(z.object({value:z.string().or(z.number()).or(z.boolean()).or(z.date()),_meta:z.object({timestamp:z.string().optional()}).optional()})).superRefine((d,e)=>{d.id&&e.addIssue({code:z.ZodIssueCode.custom,message:"Payload cannot have an id"});}),K=z.object({id:z.string().optional(),type:z.literal("MUTATE"),resource:z.string()}),C=K.extend({procedure:z.string(),payload:z.any().optional()}),L=K.extend({resourceId:z.string(),payload:j});z.union([C,L]);var v=z.string(),H=z.object({id:v,type:z.literal("SUBSCRIBE"),resource:z.string()}),_=z.object({id:v,type:z.literal("SYNC"),lastSyncedAt:z.string().optional(),resources:z.string().array().optional(),where:z.record(z.any()).optional()}),N=L.extend({id:v}),V=C.extend({id:v}),Y=z.union([V,N]);z.union([H,_,Y]);var $=z.object({id:v,type:z.literal("SYNC"),resource:z.string(),data:z.record(j)}),J=z.object({id:v,type:z.literal("REJECT"),resource:z.string(),message:z.string().optional()}),q=z.object({id:v,type:z.literal("REPLY"),data:z.any()}),W=z.union([$,J,q,N]);var w=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){this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t);}removeEventListener(e,t){this.eventListeners.has(e)&&this.eventListeners.get(e).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){this.dispatchEvent("error",e);}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){this.eventListeners.has(e)&&this.eventListeners.get(e).forEach(i=>{i(t);});}};var O=class{nodes;constructor(){this.nodes=new Map;}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,i){let s=this.nodes.get(e),r=this.nodes.get(t);if(!s)throw new Error(`Source node with id ${e} does not exist`);if(!r)throw new Error(`Target node with id ${t} does not exist`);s.references.set(i,t);let n=r.referencedBy.get(i);n&&n instanceof Set?n.add(e):r.referencedBy.set(i,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(t);n&&(n instanceof Set?n.delete(e):r.referencedBy.delete(t),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 c=this.nodes.get(n);!c||!c.references.get(i)||(c.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=>{try{i(e);}catch(s){console.error(`Error in node subscription for node ${e}:`,s);}});}getAllNodes(){return Array.from(this.nodes.values())}};var x="__meta",T=class{db;async init(e){this.db=await openDB("live-state",1,{upgrade(t){Object.keys(e).forEach(i=>t.createObjectStore(i)),t.createObjectStore(x);}});}async get(e){if(this.db.getAllRecords)return this.db.getAllRecords(e);let[t,i]=await Promise.all([this.db.getAll(e),this.db.getAllKeys(e)]);return Object.fromEntries(t.map((s,r)=>[i[r],s]))}getOne(e,t){return this.db.get(e,t)}set(e,t,i){return this.db.put(e,i,t)}delete(e,t){return this.db.delete(e,t)}getMeta(e){return this.db.get(x,e)}setMeta(e,t){return this.db.put(x,t,e)}};var R=class{constructor(e,t){this.schema=e;this.kvStorage=new T,this.kvStorage.init(this.schema).then(()=>{this.kvStorage.getMeta("mutationStack").then(i=>{!i||Object.keys(i).length===0||(this.optimisticMutationStack=i,t==null||t(this.optimisticMutationStack));}).then(()=>{Object.entries(this.schema).forEach(([i,s])=>{this.kvStorage.get(i).then(r=>{!r||Object.keys(r).length===0||this.loadConsolidatedState(i,r);});});}).catch(i=>{console.error("Failed to load state from storage",i);});});}rawObjPool={};optimisticMutationStack={};optimisticObjGraph=new O;optimisticRawObjPool={};resourceTypeSubscriptions={};kvStorage;get(e){return Object.fromEntries(Object.entries(this.optimisticRawObjPool[e]??{}).map(([t,i])=>[t,d(i)]))}getOne(e,t){var n;let i=this.optimisticObjGraph.getNode(t);if(!i)return;let s=(n=this.optimisticRawObjPool[e])==null?void 0:n[t];if(!s)return;let r={value:{...s.value,...Object.fromEntries(Array.from(i.references.entries()).map(([c,h])=>{var l;let g=this.optimisticObjGraph.getNode(h);if(!g)return [c,void 0];let[y,m]=Object.entries(this.schema[e].relations).find(u=>u[1].relationalColumn===c||u[1].foreignColumn===c)??[],f=m==null?void 0:m.entity.name;return !f||!m?[c,void 0]:[y,(l=this.optimisticRawObjPool[f])==null?void 0:l[g.id]]})),...Object.fromEntries(Array.from(i.referencedBy.entries()).map(([c,h])=>{var u;let g=h instanceof Set,y=g?Array.from(h.values()).flatMap(p=>{let b=this.optimisticObjGraph.getNode(p);return b?[b]:[]}):this.optimisticObjGraph.getNode(h);if(!y)return [c,void 0];let[m,f]=Object.entries(this.schema[e].relations).find(p=>p[1].relationalColumn===c||p[1].foreignColumn===c)??[],l=f==null?void 0:f.entity.name;return !l||!f?[c,g?[]:void 0]:[m,g?{value:y.map(p=>{var b;return (b=this.optimisticRawObjPool[l])==null?void 0:b[p.id]})}:(u=this.optimisticRawObjPool[l])==null?void 0:u[y.id]]}))}};return d(r)}subscribe(e,t){if(e.length===1)return this.resourceTypeSubscriptions[e[0]]||(this.resourceTypeSubscriptions[e[0]]=new Set),this.resourceTypeSubscriptions[e[0]].add(t),()=>{this.resourceTypeSubscriptions[e[0]].delete(t);};if(e.length===2){if(!this.optimisticObjGraph.getNode(e[1]))throw new Error("Node not found");return this.optimisticObjGraph.subscribe(e[1],t)}throw new Error("Not implemented")}addMutation(e,t,i=false){var h,g,y,m,f;let s=this.schema[e];if(console.log("Adding mutation",t),!s)throw new Error("Schema not found");let r=(h=this.optimisticRawObjPool[e])==null?void 0:h[t.resourceId];if(i)(this.optimisticMutationStack[e]??=[]).push(t);else {this.optimisticMutationStack[e]=(y=(g=this.optimisticMutationStack)==null?void 0:g[e])==null?void 0:y.filter(p=>p.id!==t.id),this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack),this.rawObjPool[e]??={};let l={value:{...this.schema[e].mergeMutation("set",t.payload,this.rawObjPool[e][t.resourceId])[0].value,id:{value:t.resourceId}}};this.rawObjPool[e][t.resourceId]=l;let u=l.value;delete u.id,this.kvStorage.set(e,t.resourceId,u);}let n=(m=this.rawObjPool[e])==null?void 0:m[t.resourceId],c=(this.optimisticMutationStack[e]??[]).reduce((l,u)=>u.resourceId!==t.resourceId?l:this.schema[e].mergeMutation("set",u.payload,l)[0],n);if(c&&((this.optimisticRawObjPool[e]??={})[t.resourceId]={value:{...c.value,id:{value:t.resourceId}}}),this.optimisticObjGraph.hasNode(t.resourceId)||this.optimisticObjGraph.createNode(t.resourceId,e,Object.values(s.relations).flatMap(l=>l.type==="many"?[l.foreignColumn]:[])),Object.keys(s.relations).length>0){let l=Object.fromEntries(Object.entries(s.relations).flatMap(([u,p])=>p.type==="one"?[[p.relationalColumn,u]]:[]));Object.entries(t.payload).forEach(([u,p])=>{if(!p||!l[u])return;let b=r==null?void 0:r.value[u],[,M]=s.relations[l[u]].mergeMutation("set",p,b);if(M){if(!this.optimisticObjGraph.hasNode(M.value)){let P=s.relations[l[u]].entity.name;this.optimisticObjGraph.createNode(M.value,P,Object.values(this.schema[P].relations).flatMap(k=>k.type==="many"?[k.foreignColumn]:[]));}b!=null&&b.value&&this.optimisticObjGraph.removeLink(t.resourceId,u),this.optimisticObjGraph.createLink(t.resourceId,M.value,u);}});}(f=this.resourceTypeSubscriptions[e])==null||f.forEach(l=>l()),this.optimisticObjGraph.notifySubscribers(t.resourceId);}loadConsolidatedState(e,t){Object.entries(t).forEach(([i,s])=>{this.addMutation(e,{id:i,type:"MUTATE",resource:e,resourceId:i,payload:s});});}};var A=class{url;ws;store;routeSubscriptions={};replyHandlers={};constructor(e){this.url=e.url,this.store=new R(e.schema,t=>{var i,s;(s=(i=Object.values(t))==null?void 0:i.flat())==null||s.forEach(r=>this.sendWsMessage(r));}),this.ws=new w({url:e.url,autoConnect:true,autoReconnect:true,reconnectTimeout:5e3,credentials:e.credentials}),this.ws.addEventListener("message",t=>{this.handleServerMessage(t.data);}),this.ws.addEventListener("connectionChange",t=>{t.open&&(this.sendWsMessage({id:a(),type:"SYNC"}),Object.entries(this.routeSubscriptions).forEach(([i,s])=>{s>0&&this.sendWsMessage({id:a(),type:"SUBSCRIBE",resource:i});}),Object.values(this.store.optimisticMutationStack).forEach(i=>{i&&i.forEach(s=>this.sendWsMessage(s));}));});}get(e){if(e.length===0)throw new Error("Path must not be empty");return e.length===1?this.store.get(e[0]):this.store.getOne(e[0],e[1])}handleServerMessage(e){try{console.log("Message received from the server:",e);let t=W.parse(JSON.parse(e));if(console.log("Parsed message:",t),t.type==="MUTATE"){let{resource:i}=t;try{this.store.addMutation(i,t);}catch(s){console.error("Error parsing mutation from the server:",s);}}else if(t.type==="SYNC"){let{resource:i,data:s}=t;console.log("Syncing resource:",s,t),this.store.loadConsolidatedState(i,s);}else if(t.type!=="REJECT"){if(t.type==="REPLY"){let{id:i,data:s}=t;if(!this.replyHandlers[i])return;clearTimeout(this.replyHandlers[i].timeoutHandle),this.replyHandlers[i].handler(s);}}}catch(t){console.error("Error parsing message from the server:",t);}}subscribeToRemote(e){return this.routeSubscriptions[e]=(this.routeSubscriptions[e]??0)+1,this.sendWsMessage({id:a(),type:"SUBSCRIBE",resource:e}),()=>{this.routeSubscriptions[e]-=1,this.routeSubscriptions[e];}}subscribeToStore(e,t){this.store.subscribe(e,t);}mutate(e,t,i){let s={id:a(),type:"MUTATE",resource:e,payload:this.store.schema[e].encodeMutation("set",i,new Date().toISOString()),resourceId:t};this.store.addMutation(e,s,true),this.sendWsMessage(s);}genericMutate(e,t,i){if(!this.ws||!this.ws.connected())throw new Error("WebSocket not connected");let s={id:a(),type:"MUTATE",resource:e,procedure:t,payload: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:c=>{delete this.replyHandlers[s.id],r(c);}};})}sendWsMessage(e){this.ws&&this.ws.connected()&&this.ws.send(JSON.stringify(e));}},Ne=d=>{let e=new A(d);return {client:{ws:e.ws,subscribe:t=>{let i=[];for(let s of t??Object.keys(e.store.schema))i.push(e.subscribeToRemote(s));return ()=>{console.log("Removing listeners",i),i.forEach(s=>s());}}},store:c(()=>{},{apply:(t,i,s)=>{let r=i.slice(0,-1),n=i[i.length-1];if(n==="get")return e.get(r);if(n==="subscribe")return e.subscribeToStore(r,s[0]);if(n==="subscribeToRemote")return e.subscribeToRemote(r[0]);if(n==="insert"){let{id:c,...h}=s[0];return e.mutate(r[0],c,h)}if(n==="update"){let[c,h]=s;return e.mutate(r[0],c,h)}return e.genericMutate(r[0],n,s[0])}})}};export{ee as SubscriptionProvider,Ne as createClient,X as useLiveQuery};
1
+ import {c,a,f,d,e,b}from'./chunk-G5SVBG4B.js';import {useSyncExternalStore,useEffect}from'react';import {xxHash32}from'js-xxhash';import {jsx,Fragment}from'react/jsx-runtime';import {z}from'zod';import {stringify}from'qs';import ae from'fast-deep-equal';import {openDB}from'idb';var m=d=>xxHash32(JSON.stringify(d)).toString(32);var k=class{subscriptions=new Map;getOrStoreSubscription(e){let t=m(e);return this.subscriptions.has(t)?this.subscriptions.get(t).subscribe:(this.subscriptions.set(t,{subscribe:i=>{var n;(n=this.subscriptions.get(t))==null||n.callbacks.add(i);let s=e.subscribe(()=>{var r;(r=this.subscriptions.get(t))==null||r.callbacks.forEach(o=>{o();});});return ()=>{var r;(r=this.subscriptions.get(t))==null||r.callbacks.delete(i),setTimeout(()=>{var o;((o=this.subscriptions.get(t))==null?void 0:o.callbacks.size)===0&&(this.subscriptions.delete(t),s());},10);}},callbacks:new Set}),this.subscriptions.get(t).subscribe)}},F=new k,he=d=>useSyncExternalStore(F.getOrStoreSubscription(d),d.get),pe=({children:d,client:e})=>(useEffect(()=>{e.subscribe();},[e.subscribe]),jsx(Fragment,{children:d}));var N=z.object({resource:z.string(),where:z.record(z.any()).optional(),include:z.record(z.any()).optional(),lastSyncedAt:z.string().optional(),limit:z.number().optional(),sort:z.array(z.object({key:z.string(),direction:z.enum(["asc","desc"])})).optional()}),x=z.record(z.object({value:z.string().or(z.number()).or(z.boolean()).or(z.date()).nullable(),_meta:z.object({timestamp:z.string().optional().nullable()}).optional()})).superRefine((d,e)=>{d.id&&e.addIssue({code:z.ZodIssueCode.custom,message:"Payload cannot have an id"});}),H=z.object({id:z.string().optional(),type:z.literal("MUTATE"),resource:z.string()}),_=H.extend({procedure:z.string(),payload:z.any().optional()}),L=H.extend({resourceId:z.string(),payload:x});z.union([_,L]);var v=z.string(),ee=z.object({id:v,type:z.literal("SUBSCRIBE"),resource:z.string()}),te=N.extend({id:v,type:z.literal("QUERY")}),q=L.extend({id:v}),ie=_.extend({id:v}),se=z.union([ie,q]);z.union([ee,te,se]);var ne=z.object({id:v,type:z.literal("REJECT"),resource:z.string(),message:z.string().optional()}),re=z.object({id:v,type:z.literal("REPLY"),data:z.any()}),K=z.union([ne,re,q]),U=z.object({resource:z.string(),data:z.record(x)});var M=class d{_collection;_client;_where;_include;_limit;_single;_sort;constructor(e,t,i,s,n,r,o){this._collection=e,this._client=t,this._where=i??{},this._include=s??{},this._limit=n,this._single=r,this._sort=o,this.get=this.get.bind(this),this.subscribe=this.subscribe.bind(this);}where(e){return new d(this._collection,this._client,{...this._where,...e},this._include,this._limit,this._single,this._sort)}include(e){return new d(this._collection,this._client,this._where,{...this._include,...e},this._limit,this._single,this._sort)}get(){let e=this._client.get({resource:this._collection.name,where:this._where,include:this._include,limit:this._limit,sort:this._sort});return this._single?e[0]:e}subscribe(e){return this._client.subscribe({resource:this._collection.name,where:this._where,include:this._include,limit:this._limit,sort:this._sort},t=>{if(this._single)return e(t[0]);e(t);})}limit(e){return new d(this._collection,this._client,this._where,this._include,e,this._single,this._sort)}one(e){return this.first({id:e})}first(e){return new d(this._collection,this._client,e??this._where,this._include,1,true,this._sort)}orderBy(e,t="asc"){let i=[...this._sort??[],{key:e,direction:t}];return new d(this._collection,this._client,this._where,this._include,this._limit,this._single,i)}toJSON(){return {resource:this._collection.name,where:this._where,include:this._include,limit:this._limit,sort:this._sort}}static _init(e,t){return new d(e,t)}};var E=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(s=>{s(t);});}};var T=class{nodes;constructor(){this.nodes=new Map;}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(n=>[n,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 n=s.referencedBy.get(i.type);n&&n instanceof Set?n.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 n=this.nodes.get(s);if(!n)return;let r=n.referencedBy.get(i.type);r&&(r instanceof Set?r.delete(e):n.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(r=>{let o=this.nodes.get(r);!o||!o.references.get(i)||(o.references.delete(i),this.notifySubscribers(r));});}),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=>{try{i(e);}catch(s){console.error(`Error in node subscription for node ${e}:`,s);}});}getAllNodes(){return Array.from(this.nodes.values())}};var A="__meta",C="databases",R=class{db;async init(e,t){var y,h;if(typeof window>"u")return;let s=((y=(await window.indexedDB.databases()).find(l=>l.name===t))==null?void 0:y.version)??1,n=await m(e),r=Object.fromEntries(await Promise.all(Object.entries(e).map(async([l,u])=>[l,await m(u)]))),o=await openDB("live-state-databases",1,{upgrade(l){l.objectStoreNames.contains(C)||l.createObjectStore(C);}}),c=(h=await this.getAll(o,C))==null?void 0:h[t];(c==null?void 0:c.schemaHash)!==n&&s++,this.db=await openDB(t,s,{async upgrade(l){[...Object.keys(e),A].forEach(u=>{(c==null?void 0:c.objectHashes[u])!==r[u]&&l.objectStoreNames.contains(u)&&l.deleteObjectStore(u),l.objectStoreNames.contains(u)||l.createObjectStore(u);}),await o.put(C,{schemaHash:n,objectHashes:r},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(A,e):new Promise(t=>t(void 0))}setMeta(e,t){var i;return (i=this.db)==null?void 0:i.put(A,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((n,r)=>[s[r],n]))}};var O=class{constructor(e,t,i){this.schema=e;this.kvStorage=new R,t!==false&&this.kvStorage.init(this.schema,t.name).then(()=>{this.kvStorage.getMeta("mutationStack").then(s=>{!s||Object.keys(s).length===0||(this.optimisticMutationStack=s,i==null||i(this.optimisticMutationStack));}).then(()=>{Object.entries(this.schema).forEach(([s,n])=>{this.kvStorage.get(s).then(r=>{!r||Object.keys(r).length===0||this.loadConsolidatedState(s,r);});});}).catch(s=>{console.error("Failed to load state from storage",s);});});}rawObjPool={};optimisticMutationStack={};optimisticObjGraph=new T;optimisticRawObjPool={};collectionSubscriptions=new Map;querySnapshots={};kvStorage;get(e$1,t,i=false){var r;let s=t??m(e$1);if(this.querySnapshots[s]&&!i){let o=this.querySnapshots[s];if(o)return o}let n=((r=e$1.where)!=null&&r.id?[e$1.where.id]:Object.keys(this.optimisticRawObjPool[e$1.resource]??{})).flatMap(o=>{let c=f(this.materializeOneWithInclude(o,e$1.include));return c?[c]:[]});if(e$1.sort&&e$1.sort.length>0){let o=(c,y)=>{for(let h of e$1.sort){let l=c[h.key],u=y[h.key];if(l<u)return h.direction==="asc"?-1:1;if(l>u)return h.direction==="asc"?1:-1}return 0};n.sort(o);}if(e$1.where||e$1.limit){let o=e$1.where?c=>d(c,e$1.where):()=>true;n=e(n,o,e$1.limit);}return i||(this.querySnapshots[s]=n),n}subscribe(e,t){var r;let i=m(e),s=this.collectionSubscriptions.get(i),n=this.schema[e.resource];return s||this.collectionSubscriptions.set(i,{callbacks:new Set,query:e,flatInclude:e.include?Object.keys(e.include).map(o=>n.relations[o].entity.name):void 0}),(r=this.collectionSubscriptions.get(i))==null||r.callbacks.add(t),()=>{var o,c;(o=this.collectionSubscriptions.get(i))==null||o.callbacks.delete(t),((c=this.collectionSubscriptions.get(i))==null?void 0:c.callbacks.size)===0&&(this.collectionSubscriptions.delete(i),delete this.querySnapshots[i]);}}addMutation(e,t,i=false){var c,y,h,l;let s=this.schema[e];if(console.log("Adding mutation",t),!s)throw new Error("Schema not found");let n=(c=this.optimisticRawObjPool[e])==null?void 0:c[t.resourceId];if(i)this.optimisticMutationStack[e]??=[],this.optimisticMutationStack[e].push(t);else {this.optimisticMutationStack[e]=((h=(y=this.optimisticMutationStack)==null?void 0:y[e])==null?void 0:h.filter(b=>b.id!==t.id))??[],this.rawObjPool[e]??={};let u={value:{...this.schema[e].mergeMutation("set",t.payload,this.rawObjPool[e][t.resourceId])[0].value,id:{value:t.resourceId}}};this.rawObjPool[e][t.resourceId]=u;let f=u.value;delete f.id,this.kvStorage.set(e,t.resourceId,f);}this.kvStorage.setMeta("mutationStack",this.optimisticMutationStack);let r=(l=this.rawObjPool[e])==null?void 0:l[t.resourceId],o=(this.optimisticMutationStack[e]??[]).reduce((u,f)=>f.resourceId!==t.resourceId?u:this.schema[e].mergeMutation("set",f.payload,u)[0],r);if(o&&(this.optimisticRawObjPool[e]??={},this.optimisticRawObjPool[e][t.resourceId]={value:{...o.value,id:{value:t.resourceId}}}),this.optimisticObjGraph.hasNode(t.resourceId)||this.optimisticObjGraph.createNode(t.resourceId,e,Object.values(s.relations).flatMap(u=>u.type==="many"?[u.entity.name]:[])),Object.keys(s.relations).length>0){let u=Object.fromEntries(Object.entries(s.relations).flatMap(([f,b])=>b.type==="one"?[[b.relationalColumn,f]]:[]));Object.entries(t.payload).forEach(([f,b])=>{let j=s.relations[u[f]];if(!b||!u[f])return;let S=n==null?void 0:n.value[f],[,w]=j.mergeMutation("set",b,S);if(w){if(!this.optimisticObjGraph.hasNode(w.value)){let W=j.entity.name;this.optimisticObjGraph.createNode(w.value,W,Object.values(this.schema[W].relations).flatMap(P=>P.type==="many"?[P.entity.name]:[]));}S!=null&&S.value&&this.optimisticObjGraph.removeLink(t.resourceId,j.entity.name),this.optimisticObjGraph.createLink(t.resourceId,w.value);}});}this.notifyCollectionSubscribers(e),this.optimisticObjGraph.notifySubscribers(t.resourceId);}loadConsolidatedState(e,t){Object.entries(t).forEach(([i,s])=>{this.addMutation(e,{id:i,type:"MUTATE",resource:e,resourceId:i,payload:s});});}materializeOneWithInclude(e,t={}){var c;if(!e)return;let i=this.optimisticObjGraph.getNode(e);if(!i)return;let s=i.type,n=(c=this.optimisticRawObjPool[s])==null?void 0:c[e];if(!n)return;let[r,o]=Object.keys(t).reduce((y,h)=>{let l=this.schema[s].relations[h];return l.type==="one"?y[0].push([h,l.entity.name]):l.type==="many"&&y[1].push([h,l.entity.name]),y},[[],[]]);return {value:{...n.value,...Object.fromEntries(r.map(([y,h])=>[y,this.materializeOneWithInclude(i.references.get(h))])),...Object.fromEntries(o.map(([y,h])=>{let l=i.referencedBy.get(h),u=l instanceof Set;return [y,u?{value:Array.from(l.values()).map(f=>this.materializeOneWithInclude(f))}:this.materializeOneWithInclude(l)]}))}}}notifyCollectionSubscribers(e){this.collectionSubscriptions.forEach(t=>{if(t.query.resource===e||t.flatInclude&&t.flatInclude.includes(e)){let i=m(t.query),s=this.querySnapshots[i],n=this.get(t.query,void 0,true);if(ae(n,s))return;this.querySnapshots[i]=n,t.callbacks.forEach(r=>{r(n);});}});}};var I=class{url;ws;store;remoteSubCounters={};eventListeners=new Set;replyHandlers={};constructor(e){this.url=e.url,this.store=new O(e.schema,e.storage,t=>{var i,s;(s=(i=Object.values(t))==null?void 0:i.flat())==null||s.forEach(n=>{this.sendWsMessage(n);});}),this.ws=new E({url:e.url,autoConnect:true,autoReconnect:true,reconnectTimeout:5e3,credentials:e.credentials}),this.ws.addEventListener("message",t=>{this.handleServerMessage(t.data);}),this.ws.addEventListener("connectionChange",t=>{this.emitEvent({type:"CONNECTION_STATE_CHANGE",open:t.open}),t.open&&(Object.keys(this.store.schema).forEach(i=>{this.sendWsMessage({id:a(),type:"QUERY",resource:i});}),Object.entries(this.remoteSubCounters).forEach(([i,s])=>{s>0&&this.sendWsMessage({id:a(),type:"SUBSCRIBE",resource:i});}),Object.values(this.store.optimisticMutationStack).forEach(i=>{i&&i.forEach(s=>{this.sendWsMessage(s);});}));});}get(e){return this.store.get(e)}handleServerMessage(e){try{console.log("Message received from the server:",e);let t=K.parse(JSON.parse(e));if(console.log("Parsed message:",t),this.emitEvent({type:"MESSAGE_RECEIVED",message:t}),t.type==="MUTATE"){let{resource:i}=t;try{this.store.addMutation(i,t);}catch(s){console.error("Error merging mutation from the server:",s);}}else if(t.type!=="REJECT"){if(t.type==="REPLY"){let{id:i,data:s}=t;if(this.replyHandlers[i]){clearTimeout(this.replyHandlers[i].timeoutHandle),this.replyHandlers[i].handler(s);return}let n=U.parse(s);this.store.loadConsolidatedState(n.resource,n.data);}}}catch(t){console.error("Error parsing message from the server:",t);}}subscribeToRemote(e){return this.remoteSubCounters[e]=(this.remoteSubCounters[e]??0)+1,this.sendWsMessage({id:a(),type:"SUBSCRIBE",resource:e}),()=>{this.remoteSubCounters[e]-=1,this.remoteSubCounters[e];}}subscribe(e,t){return this.store.subscribe(e,t)}mutate(e,t,i){var n;let s={id:a(),type:"MUTATE",resource:e,payload:this.store.schema[e].encodeMutation("set",i,new Date().toISOString()),resourceId:t};(n=this.store)==null||n.addMutation(e,s,true),this.sendWsMessage(s);}genericMutate(e,t,i){if(!this.ws||!this.ws.connected())throw new Error("WebSocket not connected");let s={id:a(),type:"MUTATE",resource:e,procedure:t,payload:i};return this.sendWsMessage(s),new Promise((n,r)=>{this.replyHandlers[s.id]={timeoutHandle:setTimeout(()=>{delete this.replyHandlers[s.id],r(new Error("Reply timeout"));},5e3),handler:o=>{delete this.replyHandlers[s.id],n(o);}};})}addEventListener(e){return this.eventListeners.add(e),()=>{this.eventListeners.delete(e);}}sendWsMessage(e){var t;(t=this.ws)!=null&&t.connected()&&this.ws.send(JSON.stringify(e));}emitEvent(e){this.eventListeners.forEach(t=>{t(e);});}},qe=d=>{let e=new I(d);return {client:{ws:e.ws,subscribe:t=>{let i=[];for(let s of t??Object.keys(e.store.schema))i.push(e.subscribeToRemote(s));return ()=>{console.log("Removing listeners",i),i.forEach(s=>{s();});}},addEventListener:t=>e.addEventListener(t)},store:{query:Object.entries(d.schema).reduce((t,[i,s])=>(t[i]=M._init(s,e),t),{}),mutate:c(()=>{},{apply:(t,i,s)=>{if(i.length<2)return;if(i.length>2)throw new Error("Trying to access an invalid path");let[n,r]=i;if(r==="insert"){let{id:o,...c}=s[0];return e.mutate(n,o,c)}if(r==="update"){let[o,c]=s;return e.mutate(n,o,c)}return e.genericMutate(n,r,s[0])}})}}};export{pe as SubscriptionProvider,qe as createClient,he as useLiveQuery};
@@ -1,4 +1,4 @@
1
- import { A as AnyRouter, C as ClientOptions, L as LiveObjectAny, W as WhereClause, I as IncludeClause, S as Simplify, a as InferLiveObject, b as LiveObjectMutationInput } from './index-BS5EvFM-.js';
1
+ import { A as AnyRouter, C as ClientOptions, L as LiveObjectAny, W as WhereClause, I as IncludeClause, S as Simplify, a as InferLiveObject, b as LiveObjectMutationInput } from './index-4Y_YcJTJ.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'zod';
4
4
 
@@ -13,6 +13,6 @@ type FetchClient<TRouter extends AnyRouter> = {
13
13
  upsert: (input: Simplify<LiveObjectMutationInput<TRouter["routes"][K]["_resourceSchema"]>>) => Promise<void>;
14
14
  };
15
15
  };
16
- declare const createClient: <TRouter extends AnyRouter>(opts: ClientOptions) => FetchClient<TRouter>;
16
+ declare const createClient: <TRouter extends AnyRouter>(opts: Omit<ClientOptions, "storage">) => FetchClient<TRouter>;
17
17
 
18
18
  export { createClient };
@@ -1 +1 @@
1
- import {c,b,d}from'./chunk-2W2QGOPU.js';import {stringify}from'qs';var v=r=>c(()=>{},{apply:async(f,c,i)=>{if(c.length>2)throw new Error("Trying to access invalid property");let[n,o]=c,s=await b(r.credentials)??{};if(o==="get"){let e=i[0],t={};return e!=null&&e.where&&(t.where=e.where),e!=null&&e.include&&(t.include=e.include),fetch(`${r.url}/${n}${Object.keys(t).length>0?`?${stringify(t)}`:""}`,{headers:s}).then(async y=>Object.fromEntries(Object.entries(await y.json()??{}).map(([l,d$1])=>[l,d(d$1)])))}if(o==="upsert"){let{id:e,...t}=i[0];return fetch(`${r.url}/${n}/set`,{method:"POST",headers:{...s,"Content-Type":"application/json"},body:JSON.stringify({resourceId:e,payload:r.schema[n].encodeMutation("set",t,new Date().toISOString())})})}return fetch(`${r.url}/${n}/${o}`,{method:"POST",headers:{...s,"Content-Type":"application/json"},body:JSON.stringify(i[0])})}});export{v as createClient};
1
+ import {c,b,f}from'./chunk-G5SVBG4B.js';import {stringify}from'qs';var v=r=>c(()=>{},{apply:async(f$1,c,i)=>{if(c.length>2)throw new Error("Trying to access invalid property");let[n,o]=c,s=await b(r.credentials)??{};if(o==="get"){let e=i[0],t={};return e!=null&&e.where&&(t.where=e.where),e!=null&&e.include&&(t.include=e.include),fetch(`${r.url}/${n}${Object.keys(t).length>0?`?${stringify(t)}`:""}`,{headers:s}).then(async y=>Object.fromEntries(Object.entries(await y.json()??{}).map(([l,d])=>[l,f(d)])))}if(o==="upsert"){let{id:e,...t}=i[0];return fetch(`${r.url}/${n}/set`,{method:"POST",headers:{...s,"Content-Type":"application/json"},body:JSON.stringify({resourceId:e,payload:r.schema[n].encodeMutation("set",t,new Date().toISOString())})})}return fetch(`${r.url}/${n}/${o}`,{method:"POST",headers:{...s,"Content-Type":"application/json"},body:JSON.stringify(i[0])})}});export{v as createClient};
@@ -41,18 +41,18 @@ type InferLiveType<T extends LiveTypeAny> = T["_value"] extends Record<string, L
41
41
  } : T["_value"];
42
42
  type InferIndex<T extends LiveTypeAny> = string;
43
43
 
44
- declare class OptionalLiveType<T extends LiveTypeAny> extends LiveType<T["_value"] | undefined, T["_meta"], T["_encodeInput"], T["_decodeInput"]> {
44
+ declare class NullableLiveType<T extends LiveTypeAny> extends LiveType<T["_value"] | null, T["_meta"], T["_encodeInput"], T["_decodeInput"]> {
45
45
  readonly inner: T;
46
46
  constructor(inner: T);
47
- encodeMutation(mutationType: MutationType, input: T["_value"] | undefined, timestamp: string): T["_decodeInput"];
48
- mergeMutation(mutationType: MutationType, encodedMutation: T["_decodeInput"], materializedShape?: MaterializedLiveType<LiveType<T["_value"] | undefined, T["_meta"], T["_value"] | Partial<T["_value"] | undefined>, T["_decodeInput"]>> | undefined): [
49
- MaterializedLiveType<LiveType<T["_value"] | undefined, T["_meta"], T["_value"] | Partial<T["_value"] | undefined>, T["_decodeInput"]>>,
47
+ encodeMutation(mutationType: MutationType, input: T["_value"] | null, timestamp: string): T["_decodeInput"];
48
+ mergeMutation(mutationType: MutationType, encodedMutation: T["_decodeInput"], materializedShape?: MaterializedLiveType<LiveType<T["_value"] | null, T["_meta"], T["_value"] | Partial<T["_value"] | null>, T["_decodeInput"]>> | undefined): [
49
+ MaterializedLiveType<LiveType<T["_value"] | null, T["_meta"], T["_value"] | Partial<T["_value"] | null>, T["_decodeInput"]>>,
50
50
  T["_decodeInput"] | null
51
51
  ];
52
52
  getStorageFieldType(): StorageFieldType;
53
53
  }
54
54
  type LiveAtomicTypeMeta = {
55
- timestamp: string;
55
+ timestamp: string | null;
56
56
  } & LiveTypeMeta;
57
57
  declare class LiveAtomicType<Value> extends LiveType<Value, LiveAtomicTypeMeta, Value, {
58
58
  value: Value;
@@ -91,7 +91,7 @@ declare class LiveAtomicType<Value> extends LiveType<Value, LiveAtomicTypeMeta,
91
91
  index(): LiveAtomicType<Value>;
92
92
  default(value: Value): LiveAtomicType<Value>;
93
93
  primary(): LiveAtomicType<Value>;
94
- optional(): OptionalLiveType<this>;
94
+ nullable(): NullableLiveType<this>;
95
95
  }
96
96
  declare class LiveString extends LiveAtomicType<string> {
97
97
  private constructor();
@@ -100,12 +100,14 @@ declare class LiveString extends LiveAtomicType<string> {
100
100
  static createReference(foreignField: `${string}.${string}`): LiveString;
101
101
  }
102
102
 
103
+ /** biome-ignore-all lint/complexity/noBannedTypes: false positive */
104
+
103
105
  type InferLiveObjectWithoutRelations<T extends LiveObjectAny> = {
104
106
  [K in keyof T["fields"]]: InferLiveType<T["fields"][K]>;
105
107
  };
106
- type InferLiveObject<T extends LiveObjectAny> = InferLiveObjectWithoutRelations<T> & {
107
- [K in keyof T["relations"]]: T["relations"][K]["type"] extends "one" ? InferLiveObject<T["relations"][K]["entity"]> : InferLiveObject<T["relations"][K]["entity"]>[];
108
- };
108
+ type InferLiveObject<T extends LiveObjectAny, Include extends IncludeClause<T> | undefined = undefined> = InferLiveObjectWithoutRelations<T> & (Include extends IncludeClause<T> ? {
109
+ [K in keyof T["relations"] as Include[K] extends true ? K : never]: T["relations"][K]["type"] extends "one" ? InferLiveObject<T["relations"][K]["entity"]> : InferLiveObject<T["relations"][K]["entity"]>[];
110
+ } : {});
109
111
  type InferRelationalColumns<T extends Record<string, RelationAny>> = {
110
112
  [K in keyof T as T[K] extends Relation<any, any, any, infer ColumnName, any, any> ? ColumnName extends string ? ColumnName : never : never]: T[K]["type"] extends "one" ? T[K] extends Relation<infer Entity, any, any, any, any, any> ? T[K]["required"] extends true ? InferIndex<Entity> : InferIndex<Entity> | undefined : never : never;
111
113
  };
@@ -124,7 +126,7 @@ declare class LiveObject<TName extends string, TSchema extends Record<string, Li
124
126
  }
125
127
  type LiveObjectAny = LiveObject<string, Record<string, LiveTypeAny>, any>;
126
128
  declare class Relation<TEntity extends LiveObjectAny, TSourceEntity extends LiveObjectAny, TType extends "one" | "many", TRelationalColumn extends keyof TSourceEntity["fields"], TForeignColumn extends keyof TEntity["fields"], TRequired extends boolean> extends LiveType<InferIndex<TEntity>, {
127
- timestamp: string;
129
+ timestamp: string | null;
128
130
  } & LiveTypeMeta> {
129
131
  readonly entity: TEntity;
130
132
  readonly type: TType;
@@ -154,6 +156,13 @@ declare class Relation<TEntity extends LiveObjectAny, TSourceEntity extends Live
154
156
  } | null
155
157
  ];
156
158
  getStorageFieldType(): StorageFieldType;
159
+ toJSON(): {
160
+ entityName: string;
161
+ type: TType;
162
+ required: TRequired;
163
+ relationalColumn: TRelationalColumn | undefined;
164
+ foreignColumn: TForeignColumn | undefined;
165
+ };
157
166
  static createOneFactory<TOriginEntity extends LiveObjectAny>(): <TEntity extends LiveObjectAny, TColumn extends keyof TOriginEntity["fields"], TRequired extends boolean = false>(entity: TEntity, column: TColumn, required?: TRequired) => Relation<TEntity, TOriginEntity, "one", TColumn, never, TRequired>;
158
167
  static createManyFactory<TOriginEntity extends LiveObjectAny>(): <TEntity extends LiveObjectAny, TColumn extends keyof TEntity["fields"], TRequired extends boolean = false>(entity: TEntity, foreignColumn: TColumn, required?: TRequired) => Relation<TEntity, TOriginEntity, "many", never, TColumn, TRequired>;
159
168
  }
@@ -182,10 +191,25 @@ type RawSchema = Record<string, LiveObjectAny | RelationsDecl>;
182
191
  type Schema<TRawSchema extends RawSchema> = {
183
192
  [K in keyof TRawSchema as TRawSchema[K] extends LiveObjectAny ? TRawSchema[K]["name"] : never]: TRawSchema[K] extends LiveObjectAny ? ParseObjectFromSchema<TRawSchema, TRawSchema[K]["name"]> : never;
184
193
  };
185
- type WhereClause<T extends LiveObjectAny> = {
186
- [K in keyof T["fields"]]?: InferLiveType<T["fields"][K]>;
194
+ type WhereClause<T extends LiveObjectAny> = ({
195
+ [K in keyof T["fields"]]?: InferLiveType<T["fields"][K]> | ({
196
+ $eq?: InferLiveType<T["fields"][K]>;
197
+ $in?: InferLiveType<T["fields"][K]>[];
198
+ $not?: InferLiveType<T["fields"][K]> | {
199
+ $in?: InferLiveType<T["fields"][K]>[];
200
+ $eq?: InferLiveType<T["fields"][K]>;
201
+ };
202
+ } & (InferLiveType<T["fields"][K]> extends number ? {
203
+ $gt?: InferLiveType<T["fields"][K]>;
204
+ $gte?: InferLiveType<T["fields"][K]>;
205
+ $lt?: InferLiveType<T["fields"][K]>;
206
+ $lte?: InferLiveType<T["fields"][K]>;
207
+ } : {}));
187
208
  } & {
188
209
  [K in keyof T["relations"]]?: WhereClause<T["relations"][K]["entity"]>;
210
+ }) | {
211
+ $and?: WhereClause<T>[];
212
+ $or?: WhereClause<T>[];
189
213
  };
190
214
  type IncludeClause<T extends LiveObjectAny> = {
191
215
  [K in keyof T["relations"]]?: boolean;
@@ -233,11 +257,20 @@ declare class Route<TResourceSchema extends LiveObjectAny, TMiddleware extends M
233
257
  }
234
258
  type AnyRoute = Route<LiveObjectAny, Middleware<any>, Record<string, any>>;
235
259
 
260
+ type Simplify<T> = T extends Record<string, unknown> ? {
261
+ [K in keyof T]: Simplify<T[K]>;
262
+ } : T;
263
+
236
264
  declare abstract class Storage {
237
- abstract updateSchema(opts: Schema<any>): Promise<void>;
238
- abstract findById<T extends LiveObjectAny>(resourceName: string, id: string): Promise<MaterializedLiveType<T> | undefined>;
239
- abstract find<T extends LiveObjectAny>(resourceName: string, where?: Record<string, any>, include?: Record<string, any>): Promise<Record<string, MaterializedLiveType<T>>>;
240
- abstract upsert<T extends LiveObjectAny>(resourceName: string, resourceId: string, value: MaterializedLiveType<T>): Promise<MaterializedLiveType<T>>;
265
+ abstract findOne<T extends LiveObjectAny>(resource: T, id: string, options?: {
266
+ include?: IncludeClause<T>;
267
+ }): Promise<InferLiveObject<T> | undefined>;
268
+ abstract find<T extends LiveObjectAny>(resource: T, options?: {
269
+ where?: WhereClause<T>;
270
+ include?: IncludeClause<T>;
271
+ }): Promise<Record<string, InferLiveObject<T>>>;
272
+ insert<T extends LiveObjectAny>(resource: T, value: Simplify<LiveObjectMutationInput<T>>): Promise<InferLiveObject<T>>;
273
+ update<T extends LiveObjectAny>(resource: T, resourceId: string, value: LiveObjectMutationInput<T>): Promise<InferLiveObject<T>>;
241
274
  }
242
275
 
243
276
  type ParsedRequest<TInput = any> = {
@@ -259,23 +292,151 @@ type Middleware<T = any> = (opts: {
259
292
  next: NextFunction<T>;
260
293
  }) => ReturnType<NextFunction<T>>;
261
294
 
262
- type Simplify<T> = T extends Record<string, any> ? {
263
- [K in keyof T]: Simplify<T[K]>;
264
- } : T;
265
-
266
- type DeepSubscribable<T> = {
267
- [K in keyof T]: DeepSubscribable<T[K]>;
268
- } & {
269
- get: () => T;
270
- subscribe: (callback: (value: T) => void) => () => void;
271
- };
272
-
273
- declare const useLiveQuery: <T extends DeepSubscribable<U>, U>(observable: T) => Simplify<ReturnType<T["get"]>>;
295
+ declare const useLiveQuery: <T extends {
296
+ get: () => U;
297
+ subscribe: (cb: (v: U) => void) => () => void;
298
+ }, U>(observable: T) => ReturnType<T["get"]>;
274
299
  declare const SubscriptionProvider: ({ children, client, }: {
275
300
  children: React.ReactNode;
276
301
  client: Client<AnyRouter>["client"];
277
302
  }) => react_jsx_runtime.JSX.Element;
278
303
 
304
+ declare const serverMessageSchema: z.ZodUnion<[z.ZodObject<{
305
+ id: z.ZodString;
306
+ type: z.ZodLiteral<"REJECT">;
307
+ resource: z.ZodString;
308
+ message: z.ZodOptional<z.ZodString>;
309
+ }, "strip", z.ZodTypeAny, {
310
+ type: "REJECT";
311
+ id: string;
312
+ resource: string;
313
+ message?: string | undefined;
314
+ }, {
315
+ type: "REJECT";
316
+ id: string;
317
+ resource: string;
318
+ message?: string | undefined;
319
+ }>, z.ZodObject<{
320
+ id: z.ZodString;
321
+ type: z.ZodLiteral<"REPLY">;
322
+ data: z.ZodAny;
323
+ }, "strip", z.ZodTypeAny, {
324
+ type: "REPLY";
325
+ id: string;
326
+ data?: any;
327
+ }, {
328
+ type: "REPLY";
329
+ id: string;
330
+ data?: any;
331
+ }>, z.ZodObject<z.objectUtil.extendShape<z.objectUtil.extendShape<{
332
+ id: z.ZodOptional<z.ZodString>;
333
+ type: z.ZodLiteral<"MUTATE">;
334
+ resource: z.ZodString;
335
+ }, {
336
+ resourceId: z.ZodString;
337
+ payload: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodObject<{
338
+ value: z.ZodNullable<z.ZodUnion<[z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodNumber]>, z.ZodBoolean]>, z.ZodDate]>>;
339
+ _meta: z.ZodOptional<z.ZodObject<{
340
+ timestamp: z.ZodNullable<z.ZodOptional<z.ZodString>>;
341
+ }, "strip", z.ZodTypeAny, {
342
+ timestamp?: string | null | undefined;
343
+ }, {
344
+ timestamp?: string | null | undefined;
345
+ }>>;
346
+ }, "strip", z.ZodTypeAny, {
347
+ value: string | number | boolean | Date | null;
348
+ _meta?: {
349
+ timestamp?: string | null | undefined;
350
+ } | undefined;
351
+ }, {
352
+ value: string | number | boolean | Date | null;
353
+ _meta?: {
354
+ timestamp?: string | null | undefined;
355
+ } | undefined;
356
+ }>>, Record<string, {
357
+ value: string | number | boolean | Date | null;
358
+ _meta?: {
359
+ timestamp?: string | null | undefined;
360
+ } | undefined;
361
+ }>, Record<string, {
362
+ value: string | number | boolean | Date | null;
363
+ _meta?: {
364
+ timestamp?: string | null | undefined;
365
+ } | undefined;
366
+ }>>;
367
+ }>, {
368
+ id: z.ZodString;
369
+ }>, "strip", z.ZodTypeAny, {
370
+ type: "MUTATE";
371
+ id: string;
372
+ resource: string;
373
+ payload: Record<string, {
374
+ value: string | number | boolean | Date | null;
375
+ _meta?: {
376
+ timestamp?: string | null | undefined;
377
+ } | undefined;
378
+ }>;
379
+ resourceId: string;
380
+ }, {
381
+ type: "MUTATE";
382
+ id: string;
383
+ resource: string;
384
+ payload: Record<string, {
385
+ value: string | number | boolean | Date | null;
386
+ _meta?: {
387
+ timestamp?: string | null | undefined;
388
+ } | undefined;
389
+ }>;
390
+ resourceId: string;
391
+ }>]>;
392
+ type ServerMessage = z.infer<typeof serverMessageSchema>;
393
+
394
+ /** biome-ignore-all lint/complexity/noBannedTypes: <explanation> */
395
+
396
+ 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>>[];
397
+ declare class QueryBuilder<TCollection extends LiveObjectAny, TInclude extends IncludeClause<TCollection> = {}, TSingle extends boolean = false> {
398
+ private _collection;
399
+ private _client;
400
+ private _where;
401
+ private _include;
402
+ private _limit?;
403
+ private _single?;
404
+ private _sort?;
405
+ private constructor();
406
+ where(where: WhereClause<TCollection>): QueryBuilder<TCollection, TInclude, TSingle>;
407
+ include<TNewInclude extends IncludeClause<TCollection>>(include: TNewInclude): QueryBuilder<TCollection, TInclude & TNewInclude, TSingle>;
408
+ get(): InferQueryResult<TCollection, TInclude, TSingle>;
409
+ subscribe(callback: (value: InferQueryResult<TCollection, TInclude, TSingle>) => void): () => void;
410
+ limit(limit: number): QueryBuilder<TCollection, TInclude, TSingle>;
411
+ one(id: string): QueryBuilder<TCollection, TInclude, true>;
412
+ first(where?: WhereClause<TCollection>): QueryBuilder<TCollection, TInclude, true>;
413
+ orderBy(key: keyof TCollection["fields"], direction?: "asc" | "desc"): QueryBuilder<TCollection, TInclude, TSingle>;
414
+ toJSON(): {
415
+ resource: string;
416
+ where: WhereClause<TCollection>;
417
+ include: TInclude;
418
+ limit: number | undefined;
419
+ sort: {
420
+ key: string;
421
+ direction: "asc" | "desc";
422
+ }[] | undefined;
423
+ };
424
+ }
425
+
426
+ type Client$1<TRouter extends AnyRouter> = {
427
+ query: {
428
+ [K in keyof TRouter["routes"]]: QueryBuilder<TRouter["routes"][K]["_resourceSchema"]>;
429
+ };
430
+ mutate: {
431
+ [K in keyof TRouter["routes"]]: {
432
+ insert: (input: Simplify<LiveObjectMutationInput<TRouter["routes"][K]["_resourceSchema"]>>) => void;
433
+ update: (id: string, value: Omit<Simplify<LiveObjectMutationInput<TRouter["routes"][K]["_resourceSchema"]>>, "id">) => void;
434
+ } & {
435
+ [K2 in keyof TRouter["routes"][K]["customMutations"]]: (input: z.infer<TRouter["routes"][K]["customMutations"][K2]["inputValidator"]>) => Promisify<ReturnType<TRouter["routes"][K]["customMutations"][K2]["handler"]>>;
436
+ };
437
+ };
438
+ };
439
+
279
440
  type WebSocketClientEventMap = WebSocketEventMap & {
280
441
  connectionChange: {
281
442
  open: boolean;
@@ -315,24 +476,22 @@ declare class WebSocketClient {
315
476
  private dispatchEvent;
316
477
  }
317
478
 
318
- type ClientState<TRouter extends AnyRouter> = {
319
- [K in keyof TRouter["routes"]]: Record<InferIndex<TRouter["routes"][K]["_resourceSchema"]>, InferLiveObject<TRouter["routes"][K]["_resourceSchema"]>> | undefined;
479
+ type ConnectionStateChangeEvent = {
480
+ type: "CONNECTION_STATE_CHANGE";
481
+ open: boolean;
320
482
  };
483
+ type MessageReceivedEvent = {
484
+ type: "MESSAGE_RECEIVED";
485
+ message: ServerMessage;
486
+ };
487
+ type ClientEvents = ConnectionStateChangeEvent | MessageReceivedEvent;
321
488
  type Client<TRouter extends AnyRouter> = {
322
489
  client: {
323
490
  ws: WebSocketClient;
324
491
  subscribe: (resourceType?: string[]) => () => void;
492
+ addEventListener: (listener: (event: ClientEvents) => void) => () => void;
325
493
  };
326
- store: DeepSubscribable<ClientState<TRouter>> & {
327
- [K in keyof TRouter["routes"]]: {
328
- insert: (input: Simplify<LiveObjectMutationInput<TRouter["routes"][K]["_resourceSchema"]>>) => void;
329
- update: (id: string, value: Omit<Simplify<LiveObjectMutationInput<TRouter["routes"][K]["_resourceSchema"]>>, "id">) => void;
330
- };
331
- } & {
332
- [K in keyof TRouter["routes"]]: {
333
- [K2 in keyof TRouter["routes"][K]["customMutations"]]: (input: z.infer<TRouter["routes"][K]["customMutations"][K2]["inputValidator"]>) => Promisify<ReturnType<TRouter["routes"][K]["customMutations"][K2]["handler"]>>;
334
- };
335
- };
494
+ store: Client$1<TRouter>;
336
495
  };
337
496
  declare const createClient: <TRouter extends AnyRouter>(opts: ClientOptions) => Client<TRouter>;
338
497
 
@@ -340,6 +499,9 @@ type ClientOptions = {
340
499
  url: string;
341
500
  schema: Schema<any>;
342
501
  credentials?: Generatable<Awaitable<Record<string, string>>>;
502
+ storage: {
503
+ name: string;
504
+ } | false;
343
505
  };
344
506
 
345
- export { type AnyRouter as A, type ClientOptions as C, type IncludeClause as I, type LiveObjectAny as L, type Simplify as S, type WhereClause as W, type InferLiveObject as a, type LiveObjectMutationInput as b, SubscriptionProvider as c, type Client as d, createClient as e, useLiveQuery as u };
507
+ export { type AnyRouter as A, type ClientOptions as C, type IncludeClause as I, type LiveObjectAny as L, type MessageReceivedEvent as M, type Simplify as S, type WhereClause as W, type InferLiveObject as a, type LiveObjectMutationInput as b, SubscriptionProvider as c, type ConnectionStateChangeEvent as d, type ClientEvents as e, type Client as f, createClient as g, useLiveQuery as u };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- 'use strict';var o=class{_value;_meta;_encodeInput;_decodeInput};var T=class extends o{inner;constructor(e){super(),this.inner=e;}encodeMutation(e,t,n){return this.inner.encodeMutation(e,t,n)}mergeMutation(e,t,n){return this.inner.mergeMutation(e,t,n)}getStorageFieldType(){return {...this.inner.getStorageFieldType(),nullable:true}}},s=class a extends o{storageType;convertFunc;isIndex;isUnique;defaultValue;foreignReference;isPrimary;constructor(e,t,n,r,i,y,c){super(),this.storageType=e,this.convertFunc=t,this.isIndex=n??false,this.isUnique=r??false,this.defaultValue=i,this.foreignReference=y,this.isPrimary=c??false;}encodeMutation(e,t,n){return {value:t,_meta:{timestamp:n}}}mergeMutation(e,t,n){return n&&n._meta.timestamp.localeCompare(t._meta.timestamp)>=0?[n,null]:[{value:this.convertFunc?this.convertFunc(t.value):t.value,_meta:t._meta},t]}getStorageFieldType(){return {type:this.storageType,nullable:false,index:this.isIndex,unique:this.isUnique,default:this.defaultValue,references:this.foreignReference,primary:this.isPrimary}}unique(){return new a(this.storageType,this.convertFunc,this.isIndex,true,this.defaultValue,this.foreignReference,this.isPrimary)}index(){return new a(this.storageType,this.convertFunc,true,this.isUnique,this.defaultValue,this.foreignReference,this.isPrimary)}default(e){return new a(this.storageType,this.convertFunc,this.isIndex,this.isUnique,e,this.foreignReference,this.isPrimary)}primary(){return new a(this.storageType,this.convertFunc,this.isIndex,this.isUnique,this.defaultValue,this.foreignReference,true)}optional(){return new T(this)}},d=class a extends s{constructor(){super("integer",e=>Number(e));}static create(){return new a}},O=d.create,l=class a extends s{constructor(e){super("varchar",void 0,void 0,void 0,void 0,e);}static create(){return new a}static createId(){return new a().index().unique().primary()}static createReference(e){return new a(e)}},j=l.create,S=l.createId,I=l.createReference,p=class a extends s{constructor(){super("boolean",e=>typeof e=="string"?e.toLowerCase()==="true":!!e);}static create(){return new a}},w=p.create,m=class a extends s{constructor(){super("timestamp",e=>typeof e=="string"?new Date(e):e);}static create(){return new a}},A=m.create;var v=class a extends o{name;fields;relations;constructor(e,t,n){super(),this.name=e,this.fields=t,this.relations=n??{};}encodeMutation(e,t,n){return Object.fromEntries(Object.entries(t).map(([r,i])=>[r,(this.fields[r]??this.relations[r]).encodeMutation("set",i,n)]))}mergeMutation(e,t,n){let r={};return [{value:{...(n==null?void 0:n.value)??{},...Object.fromEntries(Object.entries(t).map(([i,y])=>{let[c,f]=(this.fields[i]??this.relations[i]).mergeMutation(e,y,n==null?void 0:n.value[i]);return f&&(r[i]=f),[i,c]}))}},r]}setRelations(e){return new a(this.name,this.fields,e)}getStorageFieldType(){throw new Error("Method not implemented.")}static create(e,t){return new a(e,t)}},P=v.create,u=class a extends o{entity;type;required;relationalColumn;foreignColumn;sourceEntity;constructor(e,t,n,r,i){super(),this.entity=e,this.type=t,this.required=i??false,this.relationalColumn=n,this.foreignColumn=r;}encodeMutation(e,t,n){if(e!=="set")throw new Error("Mutation type not implemented.");if(this.type==="many")throw new Error("Many not implemented.");return {value:t,_meta:{timestamp:n}}}mergeMutation(e,t,n){if(this.type==="many")throw new Error("Many not implemented.");return n&&n._meta.timestamp.localeCompare(t._meta.timestamp)>=0?[n,null]:[t,t]}getStorageFieldType(){return {type:"varchar",nullable:!this.required,references:`${this.entity.name}.${String(this.foreignColumn??this.relationalColumn??"id")}`}}static createOneFactory(){return (e,t,n)=>new a(e,"one",t,void 0,n??false)}static createManyFactory(){return (e,t,n)=>new a(e,"many",void 0,t,n??false)}},D=(a,e)=>({$type:"relations",objectName:a.name,relations:e({one:u.createOneFactory(),many:u.createManyFactory()})}),h=a=>{if(a)return Array.isArray(a.value)?a.value.map(e=>h(e)):typeof a.value!="object"?a.value:Object.fromEntries(Object.entries(a.value).map(([e,t])=>[e,h(t)]))},k=a=>Object.fromEntries(Object.entries(a).flatMap(([e,t])=>{if(t.$type==="relations")return [];let n=t,r=Object.values(a).find(i=>i.$type==="relations"&&i.objectName===t.name);return r&&(n=n.setRelations(r.relations)),[[n.name,n]]}));exports.LiveBoolean=p;exports.LiveNumber=d;exports.LiveObject=v;exports.LiveString=l;exports.LiveTimestamp=m;exports.LiveType=o;exports.Relation=u;exports.boolean=w;exports.createRelations=D;exports.createSchema=k;exports.id=S;exports.inferValue=h;exports.number=O;exports.object=P;exports.reference=I;exports.string=j;exports.timestamp=A;
1
+ 'use strict';var s=class{_value;_meta;_encodeInput;_decodeInput};var c=class extends s{inner;constructor(e){super(),this.inner=e;}encodeMutation(e,t,n){return this.inner.encodeMutation(e,t,n)}mergeMutation(e,t,n){return this.inner.mergeMutation(e,t,n)}getStorageFieldType(){return {...this.inner.getStorageFieldType(),nullable:true}}},o=class a extends s{storageType;convertFunc;isIndex;isUnique;defaultValue;foreignReference;isPrimary;constructor(e,t,n,r,i,u,y){super(),this.storageType=e,this.convertFunc=t,this.isIndex=n??false,this.isUnique=r??false,this.defaultValue=i,this.foreignReference=u,this.isPrimary=y??false;}encodeMutation(e,t,n){return {value:t,_meta:{timestamp:n}}}mergeMutation(e,t,n){return n&&n._meta.timestamp&&t._meta.timestamp&&n._meta.timestamp.localeCompare(t._meta.timestamp)>=0?[n,null]:[{value:this.convertFunc?this.convertFunc(t.value):t.value,_meta:t._meta},t]}getStorageFieldType(){return {type:this.storageType,nullable:false,index:this.isIndex,unique:this.isUnique,default:this.defaultValue,references:this.foreignReference,primary:this.isPrimary}}unique(){return new a(this.storageType,this.convertFunc,this.isIndex,true,this.defaultValue,this.foreignReference,this.isPrimary)}index(){return new a(this.storageType,this.convertFunc,true,this.isUnique,this.defaultValue,this.foreignReference,this.isPrimary)}default(e){return new a(this.storageType,this.convertFunc,this.isIndex,this.isUnique,e,this.foreignReference,this.isPrimary)}primary(){return new a(this.storageType,this.convertFunc,this.isIndex,this.isUnique,this.defaultValue,this.foreignReference,true)}nullable(){return new c(this)}},p=class a extends o{constructor(){super("integer",e=>Number(e));}static create(){return new a}},g=p.create,l=class a extends o{constructor(e){super("varchar",void 0,void 0,void 0,void 0,e);}static create(){return new a}static createId(){return new a().index().unique().primary()}static createReference(e){return new a(e)}},b=l.create,M=l.createId,I=l.createReference,d=class a extends o{constructor(){super("boolean",e=>typeof e=="string"?e.toLowerCase()==="true":!!e);}static create(){return new a}},O=d.create,m=class a extends o{constructor(){super("timestamp",e=>typeof e=="string"?new Date(e):e);}static create(){return new a}},j=m.create;var v=class a extends s{name;fields;relations;constructor(e,t,n){super(),this.name=e,this.fields=t,this.relations=n??{};}encodeMutation(e,t,n){return Object.fromEntries(Object.entries(t).map(([r,i])=>[r,(this.fields[r]??this.relations[r]).encodeMutation("set",i,n)]))}mergeMutation(e,t,n){let r={};return [{value:{...(n==null?void 0:n.value)??{},...Object.fromEntries(Object.entries(t).map(([i,u])=>{let y=this.fields[i]??this.relations[i];if(!y)return [i,u];let[x,f]=y.mergeMutation(e,u,n==null?void 0:n.value[i]);return f&&(r[i]=f),[i,x]}))}},r]}setRelations(e){return new a(this.name,this.fields,e)}getStorageFieldType(){throw new Error("Method not implemented.")}static create(e,t){return new a(e,t)}},K=v.create,T=class a extends s{entity;type;required;relationalColumn;foreignColumn;sourceEntity;constructor(e,t,n,r,i){super(),this.entity=e,this.type=t,this.required=i??false,this.relationalColumn=n,this.foreignColumn=r;}encodeMutation(e,t,n){if(e!=="set")throw new Error("Mutation type not implemented.");if(this.type==="many")throw new Error("Many not implemented.");return {value:t,_meta:{timestamp:n}}}mergeMutation(e,t,n){if(this.type==="many")throw new Error("Many not implemented.");return n&&n._meta.timestamp&&t._meta.timestamp&&n._meta.timestamp.localeCompare(t._meta.timestamp)>=0?[n,null]:[t,t]}getStorageFieldType(){return {type:"varchar",nullable:!this.required,references:`${this.entity.name}.${String(this.foreignColumn??this.relationalColumn??"id")}`}}toJSON(){return {entityName:this.entity.name,type:this.type,required:this.required,relationalColumn:this.relationalColumn,foreignColumn:this.foreignColumn}}static createOneFactory(){return (e,t,n)=>new a(e,"one",t,void 0,n??false)}static createManyFactory(){return (e,t,n)=>new a(e,"many",void 0,t,n??false)}},A=(a,e)=>({$type:"relations",objectName:a.name,relations:e({one:T.createOneFactory(),many:T.createManyFactory()})}),h=a=>{if(a)return Array.isArray(a.value)?a.value.map(e=>h(e)):typeof a.value!="object"||a.value===null||a.value instanceof Date?a.value:Object.fromEntries(Object.entries(a.value).map(([e,t])=>[e,h(t)]))},_=a=>Object.fromEntries(Object.entries(a).flatMap(([e,t])=>{if(t.$type==="relations")return [];let n=t,r=Object.values(a).find(i=>i.$type==="relations"&&i.objectName===t.name);return r&&(n=n.setRelations(r.relations)),[[n.name,n]]}));exports.LiveBoolean=d;exports.LiveNumber=p;exports.LiveObject=v;exports.LiveString=l;exports.LiveTimestamp=m;exports.LiveType=s;exports.Relation=T;exports.boolean=O;exports.createRelations=A;exports.createSchema=_;exports.id=M;exports.inferValue=h;exports.number=g;exports.object=K;exports.reference=I;exports.string=b;exports.timestamp=j;
package/dist/index.d.cts CHANGED
@@ -34,18 +34,18 @@ type InferLiveType<T extends LiveTypeAny> = T["_value"] extends Record<string, L
34
34
  } : T["_value"];
35
35
  type InferIndex<T extends LiveTypeAny> = string;
36
36
 
37
- declare class OptionalLiveType<T extends LiveTypeAny> extends LiveType<T["_value"] | undefined, T["_meta"], T["_encodeInput"], T["_decodeInput"]> {
37
+ declare class NullableLiveType<T extends LiveTypeAny> extends LiveType<T["_value"] | null, T["_meta"], T["_encodeInput"], T["_decodeInput"]> {
38
38
  readonly inner: T;
39
39
  constructor(inner: T);
40
- encodeMutation(mutationType: MutationType, input: T["_value"] | undefined, timestamp: string): T["_decodeInput"];
41
- mergeMutation(mutationType: MutationType, encodedMutation: T["_decodeInput"], materializedShape?: MaterializedLiveType<LiveType<T["_value"] | undefined, T["_meta"], T["_value"] | Partial<T["_value"] | undefined>, T["_decodeInput"]>> | undefined): [
42
- MaterializedLiveType<LiveType<T["_value"] | undefined, T["_meta"], T["_value"] | Partial<T["_value"] | undefined>, T["_decodeInput"]>>,
40
+ encodeMutation(mutationType: MutationType, input: T["_value"] | null, timestamp: string): T["_decodeInput"];
41
+ mergeMutation(mutationType: MutationType, encodedMutation: T["_decodeInput"], materializedShape?: MaterializedLiveType<LiveType<T["_value"] | null, T["_meta"], T["_value"] | Partial<T["_value"] | null>, T["_decodeInput"]>> | undefined): [
42
+ MaterializedLiveType<LiveType<T["_value"] | null, T["_meta"], T["_value"] | Partial<T["_value"] | null>, T["_decodeInput"]>>,
43
43
  T["_decodeInput"] | null
44
44
  ];
45
45
  getStorageFieldType(): StorageFieldType;
46
46
  }
47
47
  type LiveAtomicTypeMeta = {
48
- timestamp: string;
48
+ timestamp: string | null;
49
49
  } & LiveTypeMeta;
50
50
  declare class LiveAtomicType<Value> extends LiveType<Value, LiveAtomicTypeMeta, Value, {
51
51
  value: Value;
@@ -84,7 +84,7 @@ declare class LiveAtomicType<Value> extends LiveType<Value, LiveAtomicTypeMeta,
84
84
  index(): LiveAtomicType<Value>;
85
85
  default(value: Value): LiveAtomicType<Value>;
86
86
  primary(): LiveAtomicType<Value>;
87
- optional(): OptionalLiveType<this>;
87
+ nullable(): NullableLiveType<this>;
88
88
  }
89
89
  declare class LiveNumber extends LiveAtomicType<number> {
90
90
  private constructor();
@@ -111,12 +111,14 @@ declare class LiveTimestamp extends LiveAtomicType<Date> {
111
111
  }
112
112
  declare const timestamp: typeof LiveTimestamp.create;
113
113
 
114
+ /** biome-ignore-all lint/complexity/noBannedTypes: false positive */
115
+
114
116
  type InferLiveObjectWithoutRelations<T extends LiveObjectAny> = {
115
117
  [K in keyof T["fields"]]: InferLiveType<T["fields"][K]>;
116
118
  };
117
- type InferLiveObject<T extends LiveObjectAny> = InferLiveObjectWithoutRelations<T> & {
118
- [K in keyof T["relations"]]: T["relations"][K]["type"] extends "one" ? InferLiveObject<T["relations"][K]["entity"]> : InferLiveObject<T["relations"][K]["entity"]>[];
119
- };
119
+ type InferLiveObject<T extends LiveObjectAny, Include extends IncludeClause<T> | undefined = undefined> = InferLiveObjectWithoutRelations<T> & (Include extends IncludeClause<T> ? {
120
+ [K in keyof T["relations"] as Include[K] extends true ? K : never]: T["relations"][K]["type"] extends "one" ? InferLiveObject<T["relations"][K]["entity"]> : InferLiveObject<T["relations"][K]["entity"]>[];
121
+ } : {});
120
122
  type InferRelationalColumns<T extends Record<string, RelationAny>> = {
121
123
  [K in keyof T as T[K] extends Relation<any, any, any, infer ColumnName, any, any> ? ColumnName extends string ? ColumnName : never : never]: T[K]["type"] extends "one" ? T[K] extends Relation<infer Entity, any, any, any, any, any> ? T[K]["required"] extends true ? InferIndex<Entity> : InferIndex<Entity> | undefined : never : never;
122
124
  };
@@ -136,7 +138,7 @@ declare class LiveObject<TName extends string, TSchema extends Record<string, Li
136
138
  declare const object: typeof LiveObject.create;
137
139
  type LiveObjectAny = LiveObject<string, Record<string, LiveTypeAny>, any>;
138
140
  declare class Relation<TEntity extends LiveObjectAny, TSourceEntity extends LiveObjectAny, TType extends "one" | "many", TRelationalColumn extends keyof TSourceEntity["fields"], TForeignColumn extends keyof TEntity["fields"], TRequired extends boolean> extends LiveType<InferIndex<TEntity>, {
139
- timestamp: string;
141
+ timestamp: string | null;
140
142
  } & LiveTypeMeta> {
141
143
  readonly entity: TEntity;
142
144
  readonly type: TType;
@@ -166,6 +168,13 @@ declare class Relation<TEntity extends LiveObjectAny, TSourceEntity extends Live
166
168
  } | null
167
169
  ];
168
170
  getStorageFieldType(): StorageFieldType;
171
+ toJSON(): {
172
+ entityName: string;
173
+ type: TType;
174
+ required: TRequired;
175
+ relationalColumn: TRelationalColumn | undefined;
176
+ foreignColumn: TForeignColumn | undefined;
177
+ };
169
178
  static createOneFactory<TOriginEntity extends LiveObjectAny>(): <TEntity extends LiveObjectAny, TColumn extends keyof TOriginEntity["fields"], TRequired extends boolean = false>(entity: TEntity, column: TColumn, required?: TRequired) => Relation<TEntity, TOriginEntity, "one", TColumn, never, TRequired>;
170
179
  static createManyFactory<TOriginEntity extends LiveObjectAny>(): <TEntity extends LiveObjectAny, TColumn extends keyof TEntity["fields"], TRequired extends boolean = false>(entity: TEntity, foreignColumn: TColumn, required?: TRequired) => Relation<TEntity, TOriginEntity, "many", never, TColumn, TRequired>;
171
180
  }
@@ -200,10 +209,25 @@ type Schema<TRawSchema extends RawSchema> = {
200
209
  [K in keyof TRawSchema as TRawSchema[K] extends LiveObjectAny ? TRawSchema[K]["name"] : never]: TRawSchema[K] extends LiveObjectAny ? ParseObjectFromSchema<TRawSchema, TRawSchema[K]["name"]> : never;
201
210
  };
202
211
  declare const createSchema: <TRawSchema extends RawSchema>(schema: TRawSchema) => Schema<TRawSchema>;
203
- type WhereClause<T extends LiveObjectAny> = {
204
- [K in keyof T["fields"]]?: InferLiveType<T["fields"][K]>;
212
+ type WhereClause<T extends LiveObjectAny> = ({
213
+ [K in keyof T["fields"]]?: InferLiveType<T["fields"][K]> | ({
214
+ $eq?: InferLiveType<T["fields"][K]>;
215
+ $in?: InferLiveType<T["fields"][K]>[];
216
+ $not?: InferLiveType<T["fields"][K]> | {
217
+ $in?: InferLiveType<T["fields"][K]>[];
218
+ $eq?: InferLiveType<T["fields"][K]>;
219
+ };
220
+ } & (InferLiveType<T["fields"][K]> extends number ? {
221
+ $gt?: InferLiveType<T["fields"][K]>;
222
+ $gte?: InferLiveType<T["fields"][K]>;
223
+ $lt?: InferLiveType<T["fields"][K]>;
224
+ $lte?: InferLiveType<T["fields"][K]>;
225
+ } : {}));
205
226
  } & {
206
227
  [K in keyof T["relations"]]?: WhereClause<T["relations"][K]["entity"]>;
228
+ }) | {
229
+ $and?: WhereClause<T>[];
230
+ $or?: WhereClause<T>[];
207
231
  };
208
232
  type IncludeClause<T extends LiveObjectAny> = {
209
233
  [K in keyof T["relations"]]?: boolean;