tinybase 4.5.0 → 4.5.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.
@@ -1 +1 @@
1
- "use strict";const t=t=>typeof t,e=t(""),a="t",s=(t,e)=>t.startsWith(e),n=Promise,r=t=>null==t,i=(t,e,a)=>r(t)?a?.():e(t),o=(t,e,a)=>t.slice(e,a),c=t=>t.length,l=async t=>n.all(t),g=(t,e)=>t.map(e),h=(t,...e)=>t.push(...e),u=Object,w=(t=[])=>u.fromEntries(t),f=(t,e)=>g(u.entries(t),(([t,a])=>e(a,t))),y=(t,e,a)=>(((t,e)=>!r(((t,e)=>i(t,(t=>t[e])))(t,e)))(t,e)||(t[e]=a()),t[e]),p=t=>JSON.stringify(t,((t,e)=>e instanceof Map?u.fromEntries([...e]):e)),S=JSON.parse,d=(a,s,n)=>a+s+(t(n)==e?n:p(n)),P=(t,e,a)=>{const n=c(t);return s(e,t)?[e[n],(a?S:String)(o(e,n+1))]:void 0},x=(t,e)=>((t,e)=>t?.forEach(e))(t,((t,a)=>e(a,t))),m="hasStore",D=w(g(["Origin","Methods","Headers"],(t=>["Access-Control-Allow-"+t,"*"]))),R=async(t,e="")=>!!await t.get(e+m),b=async(t,e="")=>{const s={},n={};return x(await t.list(),((t,r)=>i(P(e,t),(([t,e])=>{if(t==a){const[t,a,n]=S("["+e+"]");y(y(s,t,w),a,w)[n]=r}else"v"==t&&(n[e]=r)})))),[s,n]},T=async(t,e,n,i)=>{const o=t.party.storage,g=t.config.storagePrefix,u={[g+m]:1},w=[],y=[];await l(f(e[0],(async(e,s)=>r(e)?!n&&t.canDelTable(s,i)&&((t,...e)=>t.unshift(...e))(y,v(g,a,s)):t.canSetTable(s,n,i)&&await l(f(e,(async(e,c)=>r(e)?!n&&t.canDelRow(s,c,i)&&h(y,v(g,a,s,c)):t.canSetRow(s,c,n,i)&&await l(f(e,(async(e,l)=>{const f=[s,c,l],y=v(g,a,...f);r(e)?!n&&t.canDelCell(...f,i)&&h(w,y):t.canSetCell(...f,e,n,i,await o.get(y))&&(u[y]=e)}))))))))),await l(f(e[1],(async(e,a)=>{const s=g+"v"+a;r(e)?!n&&t.canDelValue(a,i)&&h(w,s):t.canSetValue(a,e,n,i,await o.get(s))&&(u[s]=e)}))),0!=c(y)&&x(await o.list(),(t=>y.every((e=>!s(t,e)||h(w,t)&&0)))),await o.delete(w),await o.put(u)},v=(t,e,...a)=>d(t,e,o(p(a),1,-1)),C=async(t,e,a=null)=>new Response(a,{status:e,headers:t.config.responseHeaders});exports.TinyBasePartyKitServer=class{constructor(t){this.party=t,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=D}async onRequest(t){const{party:{storage:e},config:{storePath:a,storagePrefix:s}}=this;if(new URL(t.url).pathname.endsWith(a)){const a=await R(e,s),n=await t.text();return"PUT"==t.method?a?C(this,205):(await T(this,S(n),!0,t),C(this,201)):C(this,200,a?p(await b(e,s)):"")}return C(this,404)}async onMessage(t,e){const{party:{storage:a,broadcast:s},config:{messagePrefix:n,storagePrefix:r}}=this;await i(P(n,t,1),(async([t,i])=>{"s"==t&&await R(a,r)&&(await T(this,i,!1,e),s(d(n,"s",i),[e.id]))}))}canSetTable(t,e,a){return!0}canDelTable(t,e){return!0}canSetRow(t,e,a,s){return!0}canDelRow(t,e,a){return!0}canSetCell(t,e,a,s,n,r,i){return!0}canDelCell(t,e,a,s){return!0}canSetValue(t,e,a,s,n){return!0}canDelValue(t,e){return!0}},exports.hasStoreInStorage=R,exports.loadStoreFromStorage=b;
1
+ "use strict";const t=t=>typeof t,e=t(""),a="t",s=(t,e)=>t.startsWith(e),n=Promise,r=t=>null==t,i=(t,e,a)=>r(t)?a?.():e(t),o=(t,e,a)=>t.slice(e,a),c=t=>t.length,l=async t=>n.all(t),g=(t,e)=>t.map(e),h=(t,...e)=>t.push(...e),f=Object,u=(t=[])=>f.fromEntries(t),w=(t,e)=>g(f.entries(t),(([t,a])=>e(a,t))),y=(t,e,a)=>(((t,e)=>!r(((t,e)=>i(t,(t=>t[e])))(t,e)))(t,e)||(t[e]=a()),t[e]),p=t=>JSON.stringify(t,((t,e)=>e instanceof Map?f.fromEntries([...e]):e)),S=JSON.parse,d=(a,s,n)=>a+s+(t(n)==e?n:p(n)),x=(t,e,a)=>{const n=c(t);return s(e,t)?[e[n],(a?S:String)(o(e,n+1))]:void 0},P=(t,e)=>((t,e)=>t?.forEach(e))(t,((t,a)=>e(a,t))),m="hasStore",D=u(g(["Origin","Methods","Headers"],(t=>["Access-Control-Allow-"+t,"*"]))),b=async(t,e="")=>!!await t.get(e+m),R=async(t,e="")=>{const s={},n={};return P(await t.list(),((t,r)=>i(x(e,t),(([t,e])=>{if(t==a){const[t,a,n]=S("["+e+"]");y(y(s,t,u),a,u)[n]=r}else"v"==t&&(n[e]=r)})))),[s,n]},T=async(t,e,a)=>t.party.broadcast(d(t.config.messagePrefix,"s",e),a),C=async(t,e,n,i)=>{const o=t.party.storage,g=t.config.storagePrefix,f={[g+m]:1},u=[],y=[];await l(w(e[0],(async(e,s)=>r(e)?!n&&t.canDelTable(s,i)&&((t,...e)=>t.unshift(...e))(y,v(g,a,s)):t.canSetTable(s,n,i)&&await l(w(e,(async(e,c)=>r(e)?!n&&t.canDelRow(s,c,i)&&h(y,v(g,a,s,c)):t.canSetRow(s,c,n,i)&&await l(w(e,(async(e,l)=>{const w=[s,c,l],y=v(g,a,...w);r(e)?!n&&t.canDelCell(...w,i)&&h(u,y):t.canSetCell(...w,e,n,i,await o.get(y))&&(f[y]=e)}))))))))),await l(w(e[1],(async(e,a)=>{const s=g+"v"+a;r(e)?!n&&t.canDelValue(a,i)&&h(u,s):t.canSetValue(a,e,n,i,await o.get(s))&&(f[s]=e)}))),0!=c(y)&&P(await o.list(),(t=>y.every((e=>!s(t,e)||h(u,t)&&0)))),await o.delete(u),await o.put(f)},v=(t,e,...a)=>d(t,e,o(p(a),1,-1)),O=async(t,e,a=null)=>new Response(a,{status:e,headers:t.config.responseHeaders});exports.TinyBasePartyKitServer=class{constructor(t){this.party=t,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=D}async onRequest(t){const{party:{storage:e},config:{storePath:a,storagePrefix:s}}=this;if(new URL(t.url).pathname.endsWith(a)){const a=await b(e,s),n=await t.text();return"PUT"==t.method?a?O(this,205):(await C(this,S(n),!0,t),O(this,201)):O(this,200,a?p(await R(e,s)):"")}return O(this,404)}async onMessage(t,e){const{config:{messagePrefix:a,storagePrefix:s}}=this;await i(x(a,t,1),(async([t,a])=>{"s"==t&&await b(this.party.storage,s)&&(await C(this,a,!1,e),T(this,a,[e.id]))}))}canSetTable(t,e,a){return!0}canDelTable(t,e){return!0}canSetRow(t,e,a,s){return!0}canDelRow(t,e,a){return!0}canSetCell(t,e,a,s,n,r,i){return!0}canDelCell(t,e,a,s){return!0}canSetValue(t,e,a,s,n){return!0}canDelValue(t,e){return!0}},exports.broadcastTransactionChanges=T,exports.hasStoreInStorage=b,exports.loadStoreFromStorage=R;
@@ -1 +1 @@
1
- "use strict";const e=e=>typeof e,t=e(""),n="t",r=(e,t)=>e.startsWith(t),s=Promise,i=e=>null==e,o=(e,t,n)=>i(e)?null==n?void 0:n():t(e),l=(e,t,n)=>e.slice(t,n),a=e=>e.length,c=e=>{return t=function*(){return s.all(e)},new Promise(((e,n)=>{var r=e=>{try{i(t.next(e))}catch(e){n(e)}},s=e=>{try{i(t.throw(e))}catch(e){n(e)}},i=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,s);i((t=t.apply(void 0,null)).next())}));var t},u=(e,t)=>e.map(t),d=(e,...t)=>e.push(...t),h=Object,f=(e=[])=>h.fromEntries(e),y=(e,t)=>u(h.entries(e),(([e,n])=>t(n,e))),g=(e,t,n)=>(((e,t)=>!i(((e,t)=>o(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),v=e=>JSON.stringify(e,((e,t)=>t instanceof Map?h.fromEntries([...t]):t)),p=JSON.parse,P=(n,r,s)=>n+r+(e(s)==t?s:v(s)),S=(e,t,n)=>{const s=a(e);return r(t,e)?[t[s],(n?p:String)(l(t,s+1))]:void 0},x=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var m=(e,t,n)=>new Promise(((r,s)=>{var i=e=>{try{l(n.next(e))}catch(e){s(e)}},o=e=>{try{l(n.throw(e))}catch(e){s(e)}},l=e=>e.done?r(e.value):Promise.resolve(e.value).then(i,o);l((n=n.apply(e,t)).next())}));const w="hasStore",D=f(u(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),R=(e,...t)=>m(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+w))})),b=(e,...t)=>m(void 0,[e,...t],(function*(e,t=""){const r={},s={};return x(yield e.list(),((e,i)=>o(S(t,e),(([e,t])=>{if(e==n){const[e,n,s]=p("["+t+"]");g(g(r,e,f),n,f)[s]=i}else"v"==e&&(s[t]=i)})))),[r,s]})),T=(e,t,s,o)=>m(void 0,null,(function*(){const l=e.party.storage,u=e.config.storagePrefix,h={[u+w]:1},f=[],g=[];yield c(y(t[0],((t,r)=>m(void 0,null,(function*(){return i(t)?!s&&e.canDelTable(r,o)&&((e,...t)=>e.unshift(...t))(g,C(u,n,r)):e.canSetTable(r,s,o)&&(yield c(y(t,((t,a)=>m(void 0,null,(function*(){return i(t)?!s&&e.canDelRow(r,a,o)&&d(g,C(u,n,r,a)):e.canSetRow(r,a,s,o)&&(yield c(y(t,((t,c)=>m(void 0,null,(function*(){const y=[r,a,c],g=C(u,n,...y);i(t)?!s&&e.canDelCell(...y,o)&&d(f,g):e.canSetCell(...y,t,s,o,yield l.get(g))&&(h[g]=t)}))))))}))))))}))))),yield c(y(t[1],((t,n)=>m(void 0,null,(function*(){const r=u+"v"+n;i(t)?!s&&e.canDelValue(n,o)&&d(f,r):e.canSetValue(n,t,s,o,yield l.get(r))&&(h[r]=t)}))))),0!=a(g)&&x(yield l.list(),(e=>g.every((t=>!r(e,t)||d(f,e)&&0)))),yield l.delete(f),yield l.put(h)})),C=(e,t,...n)=>P(e,t,l(v(n),1,-1)),H=(e,t,n=null)=>m(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));exports.TinyBasePartyKitServer=class{constructor(e){var t,n,r,s;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(s=this.config).responseHeaders||(s.responseHeaders=D)}onRequest(e){return m(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield R(t,r),s=yield e.text();return"PUT"==e.method?n?H(this,205):(yield T(this,p(s),!0,e),H(this,201)):H(this,200,n?v(yield b(t,r)):"")}return H(this,404)}))}onMessage(e,t){return m(this,null,(function*(){const{party:{storage:n,broadcast:r},config:{messagePrefix:s,storagePrefix:i}}=this;yield o(S(s,e,1),(e=>m(this,[e],(function*([e,o]){"s"==e&&(yield R(n,i))&&(yield T(this,o,!1,t),r(P(s,"s",o),[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,s,i,o){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,s){return!0}canDelValue(e,t){return!0}},exports.hasStoreInStorage=R,exports.loadStoreFromStorage=b;
1
+ "use strict";const e=e=>typeof e,t=e(""),n="t",r=(e,t)=>e.startsWith(t),s=Promise,i=e=>null==e,o=(e,t,n)=>i(e)?null==n?void 0:n():t(e),l=(e,t,n)=>e.slice(t,n),a=e=>e.length,c=e=>{return t=function*(){return s.all(e)},new Promise(((e,n)=>{var r=e=>{try{i(t.next(e))}catch(e){n(e)}},s=e=>{try{i(t.throw(e))}catch(e){n(e)}},i=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,s);i((t=t.apply(void 0,null)).next())}));var t},u=(e,t)=>e.map(t),d=(e,...t)=>e.push(...t),h=Object,f=(e=[])=>h.fromEntries(e),y=(e,t)=>u(h.entries(e),(([e,n])=>t(n,e))),g=(e,t,n)=>(((e,t)=>!i(((e,t)=>o(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),v=e=>JSON.stringify(e,((e,t)=>t instanceof Map?h.fromEntries([...t]):t)),p=JSON.parse,P=(n,r,s)=>n+r+(e(s)==t?s:v(s)),x=(e,t,n)=>{const s=a(e);return r(t,e)?[t[s],(n?p:String)(l(t,s+1))]:void 0},S=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var m=(e,t,n)=>new Promise(((r,s)=>{var i=e=>{try{l(n.next(e))}catch(e){s(e)}},o=e=>{try{l(n.throw(e))}catch(e){s(e)}},l=e=>e.done?r(e.value):Promise.resolve(e.value).then(i,o);l((n=n.apply(e,t)).next())}));const w="hasStore",D=f(u(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),b=(e,...t)=>m(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+w))})),R=(e,...t)=>m(void 0,[e,...t],(function*(e,t=""){const r={},s={};return S(yield e.list(),((e,i)=>o(x(t,e),(([e,t])=>{if(e==n){const[e,n,s]=p("["+t+"]");g(g(r,e,f),n,f)[s]=i}else"v"==e&&(s[t]=i)})))),[r,s]})),T=(e,t,n)=>m(void 0,null,(function*(){return e.party.broadcast(P(e.config.messagePrefix,"s",t),n)})),C=(e,t,s,o)=>m(void 0,null,(function*(){const l=e.party.storage,u=e.config.storagePrefix,h={[u+w]:1},f=[],g=[];yield c(y(t[0],((t,r)=>m(void 0,null,(function*(){return i(t)?!s&&e.canDelTable(r,o)&&((e,...t)=>e.unshift(...t))(g,H(u,n,r)):e.canSetTable(r,s,o)&&(yield c(y(t,((t,a)=>m(void 0,null,(function*(){return i(t)?!s&&e.canDelRow(r,a,o)&&d(g,H(u,n,r,a)):e.canSetRow(r,a,s,o)&&(yield c(y(t,((t,c)=>m(void 0,null,(function*(){const y=[r,a,c],g=H(u,n,...y);i(t)?!s&&e.canDelCell(...y,o)&&d(f,g):e.canSetCell(...y,t,s,o,yield l.get(g))&&(h[g]=t)}))))))}))))))}))))),yield c(y(t[1],((t,n)=>m(void 0,null,(function*(){const r=u+"v"+n;i(t)?!s&&e.canDelValue(n,o)&&d(f,r):e.canSetValue(n,t,s,o,yield l.get(r))&&(h[r]=t)}))))),0!=a(g)&&S(yield l.list(),(e=>g.every((t=>!r(e,t)||d(f,e)&&0)))),yield l.delete(f),yield l.put(h)})),H=(e,t,...n)=>P(e,t,l(v(n),1,-1)),O=(e,t,n=null)=>m(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));exports.TinyBasePartyKitServer=class{constructor(e){var t,n,r,s;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(s=this.config).responseHeaders||(s.responseHeaders=D)}onRequest(e){return m(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield b(t,r),s=yield e.text();return"PUT"==e.method?n?O(this,205):(yield C(this,p(s),!0,e),O(this,201)):O(this,200,n?v(yield R(t,r)):"")}return O(this,404)}))}onMessage(e,t){return m(this,null,(function*(){const{config:{messagePrefix:n,storagePrefix:r}}=this;yield o(x(n,e,1),(e=>m(this,[e],(function*([e,n]){"s"==e&&(yield b(this.party.storage,r))&&(yield C(this,n,!1,t),T(this,n,[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,s,i,o){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,s){return!0}canDelValue(e,t){return!0}},exports.broadcastTransactionChanges=T,exports.hasStoreInStorage=b,exports.loadStoreFromStorage=R;
@@ -85,6 +85,15 @@ const loadStoreFromStorage = async (storage, storagePrefix = EMPTY_STRING) => {
85
85
  );
86
86
  return [tables, values];
87
87
  };
88
+ const broadcastTransactionChanges = async (
89
+ server,
90
+ transactionChanges,
91
+ without,
92
+ ) =>
93
+ server.party.broadcast(
94
+ construct(server.config.messagePrefix, SET_CHANGES, transactionChanges),
95
+ without,
96
+ );
88
97
  const saveStore = async (
89
98
  that,
90
99
  transactionChanges,
@@ -216,7 +225,6 @@ class TinyBasePartyKitServer {
216
225
  }
217
226
  async onMessage(message, connection) {
218
227
  const {
219
- party: {storage, broadcast},
220
228
  config: {messagePrefix, storagePrefix},
221
229
  } = this;
222
230
  await ifNotUndefined(
@@ -224,12 +232,10 @@ class TinyBasePartyKitServer {
224
232
  async ([type, payload]) => {
225
233
  if (
226
234
  type == SET_CHANGES &&
227
- (await hasStoreInStorage(storage, storagePrefix))
235
+ (await hasStoreInStorage(this.party.storage, storagePrefix))
228
236
  ) {
229
237
  await saveStore(this, payload, false, connection);
230
- broadcast(construct(messagePrefix, SET_CHANGES, payload), [
231
- connection.id,
232
- ]);
238
+ broadcastTransactionChanges(this, payload, [connection.id]);
233
239
  }
234
240
  },
235
241
  );
@@ -268,4 +274,9 @@ class TinyBasePartyKitServer {
268
274
  }
269
275
  }
270
276
 
271
- export {TinyBasePartyKitServer, hasStoreInStorage, loadStoreFromStorage};
277
+ export {
278
+ TinyBasePartyKitServer,
279
+ broadcastTransactionChanges,
280
+ hasStoreInStorage,
281
+ loadStoreFromStorage,
282
+ };
@@ -1 +1 @@
1
- const e=e=>typeof e,t=e(""),n="t",r=(e,t)=>e.startsWith(t),i=Promise,l=e=>null==e,s=(e,t,n)=>l(e)?null==n?void 0:n():t(e),o=(e,t,n)=>e.slice(t,n),a=e=>e.length,c=e=>{return t=function*(){return i.all(e)},new Promise(((e,n)=>{var r=e=>{try{l(t.next(e))}catch(e){n(e)}},i=e=>{try{l(t.throw(e))}catch(e){n(e)}},l=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,i);l((t=t.apply(void 0,null)).next())}));var t},u=(e,t)=>e.map(t),d=(e,...t)=>e.push(...t),h=Object,f=(e=[])=>h.fromEntries(e),y=(e,t)=>u(h.entries(e),(([e,n])=>t(n,e))),g=(e,t,n)=>(((e,t)=>!l(((e,t)=>s(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),v=e=>JSON.stringify(e,((e,t)=>t instanceof Map?h.fromEntries([...t]):t)),p=JSON.parse,P=(n,r,i)=>n+r+(e(i)==t?i:v(i)),x=(e,t,n)=>{const i=a(e);return r(t,e)?[t[i],(n?p:String)(o(t,i+1))]:void 0},m=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var S=(e,t,n)=>new Promise(((r,i)=>{var l=e=>{try{o(n.next(e))}catch(e){i(e)}},s=e=>{try{o(n.throw(e))}catch(e){i(e)}},o=e=>e.done?r(e.value):Promise.resolve(e.value).then(l,s);o((n=n.apply(e,t)).next())}));const w="hasStore",D=f(u(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),R=(e,...t)=>S(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+w))})),b=(e,...t)=>S(void 0,[e,...t],(function*(e,t=""){const r={},i={};return m(yield e.list(),((e,l)=>s(x(t,e),(([e,t])=>{if(e==n){const[e,n,i]=p("["+t+"]");g(g(r,e,f),n,f)[i]=l}else"v"==e&&(i[t]=l)})))),[r,i]})),C=(e,t,i,s)=>S(void 0,null,(function*(){const o=e.party.storage,u=e.config.storagePrefix,h={[u+w]:1},f=[],g=[];yield c(y(t[0],((t,r)=>S(void 0,null,(function*(){return l(t)?!i&&e.canDelTable(r,s)&&((e,...t)=>e.unshift(...t))(g,T(u,n,r)):e.canSetTable(r,i,s)&&(yield c(y(t,((t,a)=>S(void 0,null,(function*(){return l(t)?!i&&e.canDelRow(r,a,s)&&d(g,T(u,n,r,a)):e.canSetRow(r,a,i,s)&&(yield c(y(t,((t,c)=>S(void 0,null,(function*(){const y=[r,a,c],g=T(u,n,...y);l(t)?!i&&e.canDelCell(...y,s)&&d(f,g):e.canSetCell(...y,t,i,s,yield o.get(g))&&(h[g]=t)}))))))}))))))}))))),yield c(y(t[1],((t,n)=>S(void 0,null,(function*(){const r=u+"v"+n;l(t)?!i&&e.canDelValue(n,s)&&d(f,r):e.canSetValue(n,t,i,s,yield o.get(r))&&(h[r]=t)}))))),0!=a(g)&&m(yield o.list(),(e=>g.every((t=>!r(e,t)||d(f,e)&&0)))),yield o.delete(f),yield o.put(h)})),T=(e,t,...n)=>P(e,t,o(v(n),1,-1)),H=(e,t,n=null)=>S(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));class O{constructor(e){var t,n,r,i;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(i=this.config).responseHeaders||(i.responseHeaders=D)}onRequest(e){return S(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield R(t,r),i=yield e.text();return"PUT"==e.method?n?H(this,205):(yield C(this,p(i),!0,e),H(this,201)):H(this,200,n?v(yield b(t,r)):"")}return H(this,404)}))}onMessage(e,t){return S(this,null,(function*(){const{party:{storage:n,broadcast:r},config:{messagePrefix:i,storagePrefix:l}}=this;yield s(x(i,e,1),(e=>S(this,[e],(function*([e,s]){"s"==e&&(yield R(n,l))&&(yield C(this,s,!1,t),r(P(i,"s",s),[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,i,l,s){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,i){return!0}canDelValue(e,t){return!0}}export{O as TinyBasePartyKitServer,R as hasStoreInStorage,b as loadStoreFromStorage};
1
+ const e=e=>typeof e,t=e(""),n="t",r=(e,t)=>e.startsWith(t),i=Promise,s=e=>null==e,l=(e,t,n)=>s(e)?null==n?void 0:n():t(e),o=(e,t,n)=>e.slice(t,n),a=e=>e.length,c=e=>{return t=function*(){return i.all(e)},new Promise(((e,n)=>{var r=e=>{try{s(t.next(e))}catch(e){n(e)}},i=e=>{try{s(t.throw(e))}catch(e){n(e)}},s=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,i);s((t=t.apply(void 0,null)).next())}));var t},u=(e,t)=>e.map(t),d=(e,...t)=>e.push(...t),f=Object,h=(e=[])=>f.fromEntries(e),y=(e,t)=>u(f.entries(e),(([e,n])=>t(n,e))),g=(e,t,n)=>(((e,t)=>!s(((e,t)=>l(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),v=e=>JSON.stringify(e,((e,t)=>t instanceof Map?f.fromEntries([...t]):t)),p=JSON.parse,P=(n,r,i)=>n+r+(e(i)==t?i:v(i)),x=(e,t,n)=>{const i=a(e);return r(t,e)?[t[i],(n?p:String)(o(t,i+1))]:void 0},m=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var S=(e,t,n)=>new Promise(((r,i)=>{var s=e=>{try{o(n.next(e))}catch(e){i(e)}},l=e=>{try{o(n.throw(e))}catch(e){i(e)}},o=e=>e.done?r(e.value):Promise.resolve(e.value).then(s,l);o((n=n.apply(e,t)).next())}));const w="hasStore",D=h(u(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),R=(e,...t)=>S(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+w))})),b=(e,...t)=>S(void 0,[e,...t],(function*(e,t=""){const r={},i={};return m(yield e.list(),((e,s)=>l(x(t,e),(([e,t])=>{if(e==n){const[e,n,i]=p("["+t+"]");g(g(r,e,h),n,h)[i]=s}else"v"==e&&(i[t]=s)})))),[r,i]})),C=(e,t,n)=>S(void 0,null,(function*(){return e.party.broadcast(P(e.config.messagePrefix,"s",t),n)})),T=(e,t,i,l)=>S(void 0,null,(function*(){const o=e.party.storage,u=e.config.storagePrefix,f={[u+w]:1},h=[],g=[];yield c(y(t[0],((t,r)=>S(void 0,null,(function*(){return s(t)?!i&&e.canDelTable(r,l)&&((e,...t)=>e.unshift(...t))(g,H(u,n,r)):e.canSetTable(r,i,l)&&(yield c(y(t,((t,a)=>S(void 0,null,(function*(){return s(t)?!i&&e.canDelRow(r,a,l)&&d(g,H(u,n,r,a)):e.canSetRow(r,a,i,l)&&(yield c(y(t,((t,c)=>S(void 0,null,(function*(){const y=[r,a,c],g=H(u,n,...y);s(t)?!i&&e.canDelCell(...y,l)&&d(h,g):e.canSetCell(...y,t,i,l,yield o.get(g))&&(f[g]=t)}))))))}))))))}))))),yield c(y(t[1],((t,n)=>S(void 0,null,(function*(){const r=u+"v"+n;s(t)?!i&&e.canDelValue(n,l)&&d(h,r):e.canSetValue(n,t,i,l,yield o.get(r))&&(f[r]=t)}))))),0!=a(g)&&m(yield o.list(),(e=>g.every((t=>!r(e,t)||d(h,e)&&0)))),yield o.delete(h),yield o.put(f)})),H=(e,t,...n)=>P(e,t,o(v(n),1,-1)),O=(e,t,n=null)=>S(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));class V{constructor(e){var t,n,r,i;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(i=this.config).responseHeaders||(i.responseHeaders=D)}onRequest(e){return S(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield R(t,r),i=yield e.text();return"PUT"==e.method?n?O(this,205):(yield T(this,p(i),!0,e),O(this,201)):O(this,200,n?v(yield b(t,r)):"")}return O(this,404)}))}onMessage(e,t){return S(this,null,(function*(){const{config:{messagePrefix:n,storagePrefix:r}}=this;yield l(x(n,e,1),(e=>S(this,[e],(function*([e,n]){"s"==e&&(yield R(this.party.storage,r))&&(yield T(this,n,!1,t),C(this,n,[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,i,s,l){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,i){return!0}canDelValue(e,t){return!0}}export{V as TinyBasePartyKitServer,C as broadcastTransactionChanges,R as hasStoreInStorage,b as loadStoreFromStorage};
@@ -1 +1 @@
1
- const t=t=>typeof t,e=t(""),a="t",s=(t,e)=>t.startsWith(e),n=Promise,r=t=>null==t,i=(t,e,a)=>r(t)?a?.():e(t),c=(t,e,a)=>t.slice(e,a),o=t=>t.length,l=async t=>n.all(t),h=(t,e)=>t.map(e),g=(t,...e)=>t.push(...e),u=Object,w=(t=[])=>u.fromEntries(t),f=(t,e)=>h(u.entries(t),(([t,a])=>e(a,t))),y=(t,e,a)=>(((t,e)=>!r(((t,e)=>i(t,(t=>t[e])))(t,e)))(t,e)||(t[e]=a()),t[e]),p=t=>JSON.stringify(t,((t,e)=>e instanceof Map?u.fromEntries([...e]):e)),S=JSON.parse,d=(a,s,n)=>a+s+(t(n)==e?n:p(n)),P=(t,e,a)=>{const n=o(t);return s(e,t)?[e[n],(a?S:String)(c(e,n+1))]:void 0},m=(t,e)=>((t,e)=>t?.forEach(e))(t,((t,a)=>e(a,t))),x="hasStore",D=w(h(["Origin","Methods","Headers"],(t=>["Access-Control-Allow-"+t,"*"]))),R=async(t,e="")=>!!await t.get(e+x),b=async(t,e="")=>{const s={},n={};return m(await t.list(),((t,r)=>i(P(e,t),(([t,e])=>{if(t==a){const[t,a,n]=S("["+e+"]");y(y(s,t,w),a,w)[n]=r}else"v"==t&&(n[e]=r)})))),[s,n]},C=async(t,e,n,i)=>{const c=t.party.storage,h=t.config.storagePrefix,u={[h+x]:1},w=[],y=[];await l(f(e[0],(async(e,s)=>r(e)?!n&&t.canDelTable(s,i)&&((t,...e)=>t.unshift(...e))(y,T(h,a,s)):t.canSetTable(s,n,i)&&await l(f(e,(async(e,o)=>r(e)?!n&&t.canDelRow(s,o,i)&&g(y,T(h,a,s,o)):t.canSetRow(s,o,n,i)&&await l(f(e,(async(e,l)=>{const f=[s,o,l],y=T(h,a,...f);r(e)?!n&&t.canDelCell(...f,i)&&g(w,y):t.canSetCell(...f,e,n,i,await c.get(y))&&(u[y]=e)}))))))))),await l(f(e[1],(async(e,a)=>{const s=h+"v"+a;r(e)?!n&&t.canDelValue(a,i)&&g(w,s):t.canSetValue(a,e,n,i,await c.get(s))&&(u[s]=e)}))),0!=o(y)&&m(await c.list(),(t=>y.every((e=>!s(t,e)||g(w,t)&&0)))),await c.delete(w),await c.put(u)},T=(t,e,...a)=>d(t,e,c(p(a),1,-1)),v=async(t,e,a=null)=>new Response(a,{status:e,headers:t.config.responseHeaders});class O{constructor(t){this.party=t,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=D}async onRequest(t){const{party:{storage:e},config:{storePath:a,storagePrefix:s}}=this;if(new URL(t.url).pathname.endsWith(a)){const a=await R(e,s),n=await t.text();return"PUT"==t.method?a?v(this,205):(await C(this,S(n),!0,t),v(this,201)):v(this,200,a?p(await b(e,s)):"")}return v(this,404)}async onMessage(t,e){const{party:{storage:a,broadcast:s},config:{messagePrefix:n,storagePrefix:r}}=this;await i(P(n,t,1),(async([t,i])=>{"s"==t&&await R(a,r)&&(await C(this,i,!1,e),s(d(n,"s",i),[e.id]))}))}canSetTable(t,e,a){return!0}canDelTable(t,e){return!0}canSetRow(t,e,a,s){return!0}canDelRow(t,e,a){return!0}canSetCell(t,e,a,s,n,r,i){return!0}canDelCell(t,e,a,s){return!0}canSetValue(t,e,a,s,n){return!0}canDelValue(t,e){return!0}}export{O as TinyBasePartyKitServer,R as hasStoreInStorage,b as loadStoreFromStorage};
1
+ const t=t=>typeof t,e=t(""),a="t",s=(t,e)=>t.startsWith(e),n=Promise,r=t=>null==t,i=(t,e,a)=>r(t)?a?.():e(t),c=(t,e,a)=>t.slice(e,a),o=t=>t.length,l=async t=>n.all(t),h=(t,e)=>t.map(e),g=(t,...e)=>t.push(...e),f=Object,u=(t=[])=>f.fromEntries(t),w=(t,e)=>h(f.entries(t),(([t,a])=>e(a,t))),y=(t,e,a)=>(((t,e)=>!r(((t,e)=>i(t,(t=>t[e])))(t,e)))(t,e)||(t[e]=a()),t[e]),p=t=>JSON.stringify(t,((t,e)=>e instanceof Map?f.fromEntries([...e]):e)),S=JSON.parse,d=(a,s,n)=>a+s+(t(n)==e?n:p(n)),P=(t,e,a)=>{const n=o(t);return s(e,t)?[e[n],(a?S:String)(c(e,n+1))]:void 0},m=(t,e)=>((t,e)=>t?.forEach(e))(t,((t,a)=>e(a,t))),x="hasStore",D=u(h(["Origin","Methods","Headers"],(t=>["Access-Control-Allow-"+t,"*"]))),R=async(t,e="")=>!!await t.get(e+x),b=async(t,e="")=>{const s={},n={};return m(await t.list(),((t,r)=>i(P(e,t),(([t,e])=>{if(t==a){const[t,a,n]=S("["+e+"]");y(y(s,t,u),a,u)[n]=r}else"v"==t&&(n[e]=r)})))),[s,n]},C=async(t,e,a)=>t.party.broadcast(d(t.config.messagePrefix,"s",e),a),T=async(t,e,n,i)=>{const c=t.party.storage,h=t.config.storagePrefix,f={[h+x]:1},u=[],y=[];await l(w(e[0],(async(e,s)=>r(e)?!n&&t.canDelTable(s,i)&&((t,...e)=>t.unshift(...e))(y,v(h,a,s)):t.canSetTable(s,n,i)&&await l(w(e,(async(e,o)=>r(e)?!n&&t.canDelRow(s,o,i)&&g(y,v(h,a,s,o)):t.canSetRow(s,o,n,i)&&await l(w(e,(async(e,l)=>{const w=[s,o,l],y=v(h,a,...w);r(e)?!n&&t.canDelCell(...w,i)&&g(u,y):t.canSetCell(...w,e,n,i,await c.get(y))&&(f[y]=e)}))))))))),await l(w(e[1],(async(e,a)=>{const s=h+"v"+a;r(e)?!n&&t.canDelValue(a,i)&&g(u,s):t.canSetValue(a,e,n,i,await c.get(s))&&(f[s]=e)}))),0!=o(y)&&m(await c.list(),(t=>y.every((e=>!s(t,e)||g(u,t)&&0)))),await c.delete(u),await c.put(f)},v=(t,e,...a)=>d(t,e,c(p(a),1,-1)),O=async(t,e,a=null)=>new Response(a,{status:e,headers:t.config.responseHeaders});class V{constructor(t){this.party=t,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=D}async onRequest(t){const{party:{storage:e},config:{storePath:a,storagePrefix:s}}=this;if(new URL(t.url).pathname.endsWith(a)){const a=await R(e,s),n=await t.text();return"PUT"==t.method?a?O(this,205):(await T(this,S(n),!0,t),O(this,201)):O(this,200,a?p(await b(e,s)):"")}return O(this,404)}async onMessage(t,e){const{config:{messagePrefix:a,storagePrefix:s}}=this;await i(P(a,t,1),(async([t,a])=>{"s"==t&&await R(this.party.storage,s)&&(await T(this,a,!1,e),C(this,a,[e.id]))}))}canSetTable(t,e,a){return!0}canDelTable(t,e){return!0}canSetRow(t,e,a,s){return!0}canDelRow(t,e,a){return!0}canSetCell(t,e,a,s,n,r,i){return!0}canDelCell(t,e,a,s){return!0}canSetValue(t,e,a,s,n){return!0}canDelValue(t,e){return!0}}export{V as TinyBasePartyKitServer,C as broadcastTransactionChanges,R as hasStoreInStorage,b as loadStoreFromStorage};
@@ -22,6 +22,7 @@ import {
22
22
  Cell,
23
23
  CellOrUndefined,
24
24
  Tables,
25
+ TransactionChanges,
25
26
  Value,
26
27
  ValueOrUndefined,
27
28
  Values,
@@ -573,3 +574,26 @@ export function loadStoreFromStorage(
573
574
  storage: Storage,
574
575
  storagePrefix?: string,
575
576
  ): Promise<[Tables, Values]>;
577
+
578
+ /**
579
+ * The broadcastTransactionChanges function allows you to broadcast Store
580
+ * changes to all the client connections of a TinyBasePartyKitServer.
581
+ *
582
+ * This is intended for specialist applications that require the ability to
583
+ * update clients of a TinyBasePartyKitServer in their own custom ways.
584
+ *
585
+ * The function is asynchronous, so you should use the `await` keyword or handle
586
+ * its completion as a promise.
587
+ * @param server A reference to the TinyBasePartyKitServer object.
588
+ * @param transactionChanges The Store changes to broadcast to the server's
589
+ * clients.
590
+ * @param without An optional array of client connection Ids to exclude from the
591
+ * broadcast.
592
+ * @category Connection
593
+ * @since v4.5.1
594
+ */
595
+ export function broadcastTransactionChanges(
596
+ server: TinyBasePartyKitServer,
597
+ transactionChanges: TransactionChanges,
598
+ without?: string[],
599
+ ): Promise<void>;
@@ -25,6 +25,7 @@ import {
25
25
  NoValuesSchema,
26
26
  OptionalSchemas,
27
27
  Tables,
28
+ TransactionChanges,
28
29
  Value,
29
30
  ValueOrUndefined,
30
31
  Values,
@@ -611,3 +612,36 @@ export function loadStoreFromStorage<Schemas extends OptionalSchemas>(
611
612
  storage: Storage,
612
613
  storagePrefix?: string,
613
614
  ): Promise<[Tables<Schemas[0]>, Values<Schemas[1]>]>;
615
+
616
+ /**
617
+ * The broadcastTransactionChanges function allows you to broadcast Store
618
+ * changes to all the client connections of a TinyBasePartyKitServer.
619
+ *
620
+ * This has schema-based typing. The following is a simplified representation:
621
+ *
622
+ * ```ts override
623
+ * broadcastTransactionChanges(
624
+ * server: TinyBasePartyKitServer,
625
+ * transactionChanges: TransactionChanges,
626
+ * without?: string[],
627
+ * ): Promise<void>;
628
+ * ```
629
+ *
630
+ * This is intended for specialist applications that require the ability to
631
+ * update clients of a TinyBasePartyKitServer in their own custom ways.
632
+ *
633
+ * The function is asynchronous, so you should use the `await` keyword or handle
634
+ * its completion as a promise.
635
+ * @param server A reference to the TinyBasePartyKitServer object.
636
+ * @param transactionChanges The Store changes to broadcast to the server's
637
+ * clients.
638
+ * @param without An optional array of client connection Ids to exclude from the
639
+ * broadcast.
640
+ * @category Connection
641
+ * @since v4.5.1
642
+ */
643
+ export function broadcastTransactionChanges<Schemas extends OptionalSchemas>(
644
+ server: TinyBasePartyKitServer,
645
+ transactionChanges: TransactionChanges<Schemas>,
646
+ without?: string[],
647
+ ): Promise<void>;
@@ -1 +1 @@
1
- var e,t;e=this,t=function(e){"use strict";const t=e=>typeof e,a=t(""),s="t",n=(e,t)=>e.startsWith(t),r=Promise,i=e=>null==e,o=(e,t,a)=>i(e)?a?.():t(e),c=(e,t,a)=>e.slice(t,a),l=e=>e.length,f=async e=>r.all(e),h=(e,t)=>e.map(t),u=(e,...t)=>e.push(...t),g=Object,y=(e=[])=>g.fromEntries(e),w=(e,t)=>h(g.entries(e),(([e,a])=>t(a,e))),d=(e,t,a)=>(((e,t)=>!i(((e,t)=>o(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=a()),e[t]),p=e=>JSON.stringify(e,((e,t)=>t instanceof Map?g.fromEntries([...t]):t)),S=JSON.parse,P=(e,s,n)=>e+s+(t(n)==a?n:p(n)),m=(e,t,a)=>{const s=l(e);return n(t,e)?[t[s],(a?S:String)(c(t,s+1))]:void 0},x=(e,t)=>((e,t)=>e?.forEach(t))(e,((e,a)=>t(a,e))),b="hasStore",T=y(h(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),D=async(e,t="")=>!!await e.get(t+b),v=async(e,t="")=>{const a={},n={};return x(await e.list(),((e,r)=>o(m(t,e),(([e,t])=>{if(e==s){const[e,s,n]=S("["+t+"]");d(d(a,e,y),s,y)[n]=r}else"v"==e&&(n[t]=r)})))),[a,n]},R=async(e,t,a,r)=>{const o=e.party.storage,c=e.config.storagePrefix,h={[c+b]:1},g=[],y=[];await f(w(t[0],(async(t,n)=>i(t)?!a&&e.canDelTable(n,r)&&((e,...t)=>e.unshift(...t))(y,C(c,s,n)):e.canSetTable(n,a,r)&&await f(w(t,(async(t,l)=>i(t)?!a&&e.canDelRow(n,l,r)&&u(y,C(c,s,n,l)):e.canSetRow(n,l,a,r)&&await f(w(t,(async(t,f)=>{const y=[n,l,f],w=C(c,s,...y);i(t)?!a&&e.canDelCell(...y,r)&&u(g,w):e.canSetCell(...y,t,a,r,await o.get(w))&&(h[w]=t)}))))))))),await f(w(t[1],(async(t,s)=>{const n=c+"v"+s;i(t)?!a&&e.canDelValue(s,r)&&u(g,n):e.canSetValue(s,t,a,r,await o.get(n))&&(h[n]=t)}))),0!=l(y)&&x(await o.list(),(e=>y.every((t=>!n(e,t)||u(g,e)&&0)))),await o.delete(g),await o.put(h)},C=(e,t,...a)=>P(e,t,c(p(a),1,-1)),O=async(e,t,a=null)=>new Response(a,{status:t,headers:e.config.responseHeaders});e.TinyBasePartyKitServer=class{constructor(e){this.party=e,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=T}async onRequest(e){const{party:{storage:t},config:{storePath:a,storagePrefix:s}}=this;if(new URL(e.url).pathname.endsWith(a)){const a=await D(t,s),n=await e.text();return"PUT"==e.method?a?O(this,205):(await R(this,S(n),!0,e),O(this,201)):O(this,200,a?p(await v(t,s)):"")}return O(this,404)}async onMessage(e,t){const{party:{storage:a,broadcast:s},config:{messagePrefix:n,storagePrefix:r}}=this;await o(m(n,e,1),(async([e,i])=>{"s"==e&&await D(a,r)&&(await R(this,i,!1,t),s(P(n,"s",i),[t.id]))}))}canSetTable(e,t,a){return!0}canDelTable(e,t){return!0}canSetRow(e,t,a,s){return!0}canDelRow(e,t,a){return!0}canSetCell(e,t,a,s,n,r,i){return!0}canDelCell(e,t,a,s){return!0}canSetValue(e,t,a,s,n){return!0}canDelValue(e,t){return!0}},e.hasStoreInStorage=D,e.loadStoreFromStorage=v},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterPartyKitServer={});
1
+ var e,t;e=this,t=function(e){"use strict";const t=e=>typeof e,a=t(""),s="t",n=(e,t)=>e.startsWith(t),r=Promise,i=e=>null==e,o=(e,t,a)=>i(e)?a?.():t(e),c=(e,t,a)=>e.slice(t,a),l=e=>e.length,f=async e=>r.all(e),h=(e,t)=>e.map(t),g=(e,...t)=>e.push(...t),u=Object,y=(e=[])=>u.fromEntries(e),w=(e,t)=>h(u.entries(e),(([e,a])=>t(a,e))),d=(e,t,a)=>(((e,t)=>!i(((e,t)=>o(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=a()),e[t]),p=e=>JSON.stringify(e,((e,t)=>t instanceof Map?u.fromEntries([...t]):t)),S=JSON.parse,P=(e,s,n)=>e+s+(t(n)==a?n:p(n)),m=(e,t,a)=>{const s=l(e);return n(t,e)?[t[s],(a?S:String)(c(t,s+1))]:void 0},x=(e,t)=>((e,t)=>e?.forEach(t))(e,((e,a)=>t(a,e))),b="hasStore",T=y(h(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),D=async(e,t="")=>!!await e.get(t+b),v=async(e,t="")=>{const a={},n={};return x(await e.list(),((e,r)=>o(m(t,e),(([e,t])=>{if(e==s){const[e,s,n]=S("["+t+"]");d(d(a,e,y),s,y)[n]=r}else"v"==e&&(n[t]=r)})))),[a,n]},R=async(e,t,a)=>e.party.broadcast(P(e.config.messagePrefix,"s",t),a),C=async(e,t,a,r)=>{const o=e.party.storage,c=e.config.storagePrefix,h={[c+b]:1},u=[],y=[];await f(w(t[0],(async(t,n)=>i(t)?!a&&e.canDelTable(n,r)&&((e,...t)=>e.unshift(...t))(y,O(c,s,n)):e.canSetTable(n,a,r)&&await f(w(t,(async(t,l)=>i(t)?!a&&e.canDelRow(n,l,r)&&g(y,O(c,s,n,l)):e.canSetRow(n,l,a,r)&&await f(w(t,(async(t,f)=>{const y=[n,l,f],w=O(c,s,...y);i(t)?!a&&e.canDelCell(...y,r)&&g(u,w):e.canSetCell(...y,t,a,r,await o.get(w))&&(h[w]=t)}))))))))),await f(w(t[1],(async(t,s)=>{const n=c+"v"+s;i(t)?!a&&e.canDelValue(s,r)&&g(u,n):e.canSetValue(s,t,a,r,await o.get(n))&&(h[n]=t)}))),0!=l(y)&&x(await o.list(),(e=>y.every((t=>!n(e,t)||g(u,e)&&0)))),await o.delete(u),await o.put(h)},O=(e,t,...a)=>P(e,t,c(p(a),1,-1)),V=async(e,t,a=null)=>new Response(a,{status:t,headers:e.config.responseHeaders});e.TinyBasePartyKitServer=class{constructor(e){this.party=e,this.config={},this.config.storePath??="/store",this.config.messagePrefix??="",this.config.storagePrefix??="",this.config.responseHeaders??=T}async onRequest(e){const{party:{storage:t},config:{storePath:a,storagePrefix:s}}=this;if(new URL(e.url).pathname.endsWith(a)){const a=await D(t,s),n=await e.text();return"PUT"==e.method?a?V(this,205):(await C(this,S(n),!0,e),V(this,201)):V(this,200,a?p(await v(t,s)):"")}return V(this,404)}async onMessage(e,t){const{config:{messagePrefix:a,storagePrefix:s}}=this;await o(m(a,e,1),(async([e,a])=>{"s"==e&&await D(this.party.storage,s)&&(await C(this,a,!1,t),R(this,a,[t.id]))}))}canSetTable(e,t,a){return!0}canDelTable(e,t){return!0}canSetRow(e,t,a,s){return!0}canDelRow(e,t,a){return!0}canSetCell(e,t,a,s,n,r,i){return!0}canDelCell(e,t,a,s){return!0}canSetValue(e,t,a,s,n){return!0}canDelValue(e,t){return!0}},e.broadcastTransactionChanges=R,e.hasStoreInStorage=D,e.loadStoreFromStorage=v},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterPartyKitServer={});
@@ -1 +1 @@
1
- var e,t;e=this,t=function(e){"use strict";const t=e=>typeof e,n=t(""),r="t",i=(e,t)=>e.startsWith(t),o=Promise,s=e=>null==e,l=(e,t,n)=>s(e)?null==n?void 0:n():t(e),a=(e,t,n)=>e.slice(t,n),c=e=>e.length,u=e=>{return t=function*(){return o.all(e)},new Promise(((e,n)=>{var r=e=>{try{o(t.next(e))}catch(e){n(e)}},i=e=>{try{o(t.throw(e))}catch(e){n(e)}},o=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,i);o((t=t.apply(void 0,null)).next())}));var t},d=(e,t)=>e.map(t),f=(e,...t)=>e.push(...t),h=Object,y=(e=[])=>h.fromEntries(e),g=(e,t)=>d(h.entries(e),(([e,n])=>t(n,e))),v=(e,t,n)=>(((e,t)=>!s(((e,t)=>l(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),p=e=>JSON.stringify(e,((e,t)=>t instanceof Map?h.fromEntries([...t]):t)),P=JSON.parse,S=(e,r,i)=>e+r+(t(i)==n?i:p(i)),m=(e,t,n)=>{const r=c(e);return i(t,e)?[t[r],(n?P:String)(a(t,r+1))]:void 0},x=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var w=(e,t,n)=>new Promise(((r,i)=>{var o=e=>{try{l(n.next(e))}catch(e){i(e)}},s=e=>{try{l(n.throw(e))}catch(e){i(e)}},l=e=>e.done?r(e.value):Promise.resolve(e.value).then(o,s);l((n=n.apply(e,t)).next())}));const b="hasStore",T=y(d(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),D=(e,...t)=>w(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+b))})),R=(e,...t)=>w(void 0,[e,...t],(function*(e,t=""){const n={},i={};return x(yield e.list(),((e,o)=>l(m(t,e),(([e,t])=>{if(e==r){const[e,r,i]=P("["+t+"]");v(v(n,e,y),r,y)[i]=o}else"v"==e&&(i[t]=o)})))),[n,i]})),C=(e,t,n,o)=>w(void 0,null,(function*(){const l=e.party.storage,a=e.config.storagePrefix,d={[a+b]:1},h=[],y=[];yield u(g(t[0],((t,i)=>w(void 0,null,(function*(){return s(t)?!n&&e.canDelTable(i,o)&&((e,...t)=>e.unshift(...t))(y,H(a,r,i)):e.canSetTable(i,n,o)&&(yield u(g(t,((t,c)=>w(void 0,null,(function*(){return s(t)?!n&&e.canDelRow(i,c,o)&&f(y,H(a,r,i,c)):e.canSetRow(i,c,n,o)&&(yield u(g(t,((t,u)=>w(void 0,null,(function*(){const y=[i,c,u],g=H(a,r,...y);s(t)?!n&&e.canDelCell(...y,o)&&f(h,g):e.canSetCell(...y,t,n,o,yield l.get(g))&&(d[g]=t)}))))))}))))))}))))),yield u(g(t[1],((t,r)=>w(void 0,null,(function*(){const i=a+"v"+r;s(t)?!n&&e.canDelValue(r,o)&&f(h,i):e.canSetValue(r,t,n,o,yield l.get(i))&&(d[i]=t)}))))),0!=c(y)&&x(yield l.list(),(e=>y.every((t=>!i(e,t)||f(h,e)&&0)))),yield l.delete(h),yield l.put(d)})),H=(e,t,...n)=>S(e,t,a(p(n),1,-1)),O=(e,t,n=null)=>w(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));e.TinyBasePartyKitServer=class{constructor(e){var t,n,r,i;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(i=this.config).responseHeaders||(i.responseHeaders=T)}onRequest(e){return w(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield D(t,r),i=yield e.text();return"PUT"==e.method?n?O(this,205):(yield C(this,P(i),!0,e),O(this,201)):O(this,200,n?p(yield R(t,r)):"")}return O(this,404)}))}onMessage(e,t){return w(this,null,(function*(){const{party:{storage:n,broadcast:r},config:{messagePrefix:i,storagePrefix:o}}=this;yield l(m(i,e,1),(e=>w(this,[e],(function*([e,s]){"s"==e&&(yield D(n,o))&&(yield C(this,s,!1,t),r(S(i,"s",s),[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,i,o,s){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,i){return!0}canDelValue(e,t){return!0}},e.hasStoreInStorage=D,e.loadStoreFromStorage=R},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterPartyKitServer={});
1
+ var e,t;e=this,t=function(e){"use strict";const t=e=>typeof e,n=t(""),r="t",i=(e,t)=>e.startsWith(t),s=Promise,o=e=>null==e,l=(e,t,n)=>o(e)?null==n?void 0:n():t(e),a=(e,t,n)=>e.slice(t,n),c=e=>e.length,u=e=>{return t=function*(){return s.all(e)},new Promise(((e,n)=>{var r=e=>{try{s(t.next(e))}catch(e){n(e)}},i=e=>{try{s(t.throw(e))}catch(e){n(e)}},s=t=>t.done?e(t.value):Promise.resolve(t.value).then(r,i);s((t=t.apply(void 0,null)).next())}));var t},d=(e,t)=>e.map(t),f=(e,...t)=>e.push(...t),h=Object,y=(e=[])=>h.fromEntries(e),g=(e,t)=>d(h.entries(e),(([e,n])=>t(n,e))),v=(e,t,n)=>(((e,t)=>!o(((e,t)=>l(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=n()),e[t]),p=e=>JSON.stringify(e,((e,t)=>t instanceof Map?h.fromEntries([...t]):t)),P=JSON.parse,S=(e,r,i)=>e+r+(t(i)==n?i:p(i)),m=(e,t,n)=>{const r=c(e);return i(t,e)?[t[r],(n?P:String)(a(t,r+1))]:void 0},x=(e,t)=>((e,t)=>null==e?void 0:e.forEach(t))(e,((e,n)=>t(n,e)));var w=(e,t,n)=>new Promise(((r,i)=>{var s=e=>{try{l(n.next(e))}catch(e){i(e)}},o=e=>{try{l(n.throw(e))}catch(e){i(e)}},l=e=>e.done?r(e.value):Promise.resolve(e.value).then(s,o);l((n=n.apply(e,t)).next())}));const b="hasStore",T=y(d(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),D=(e,...t)=>w(void 0,[e,...t],(function*(e,t=""){return!!(yield e.get(t+b))})),R=(e,...t)=>w(void 0,[e,...t],(function*(e,t=""){const n={},i={};return x(yield e.list(),((e,s)=>l(m(t,e),(([e,t])=>{if(e==r){const[e,r,i]=P("["+t+"]");v(v(n,e,y),r,y)[i]=s}else"v"==e&&(i[t]=s)})))),[n,i]})),C=(e,t,n)=>w(void 0,null,(function*(){return e.party.broadcast(S(e.config.messagePrefix,"s",t),n)})),H=(e,t,n,s)=>w(void 0,null,(function*(){const l=e.party.storage,a=e.config.storagePrefix,d={[a+b]:1},h=[],y=[];yield u(g(t[0],((t,i)=>w(void 0,null,(function*(){return o(t)?!n&&e.canDelTable(i,s)&&((e,...t)=>e.unshift(...t))(y,O(a,r,i)):e.canSetTable(i,n,s)&&(yield u(g(t,((t,c)=>w(void 0,null,(function*(){return o(t)?!n&&e.canDelRow(i,c,s)&&f(y,O(a,r,i,c)):e.canSetRow(i,c,n,s)&&(yield u(g(t,((t,u)=>w(void 0,null,(function*(){const y=[i,c,u],g=O(a,r,...y);o(t)?!n&&e.canDelCell(...y,s)&&f(h,g):e.canSetCell(...y,t,n,s,yield l.get(g))&&(d[g]=t)}))))))}))))))}))))),yield u(g(t[1],((t,r)=>w(void 0,null,(function*(){const i=a+"v"+r;o(t)?!n&&e.canDelValue(r,s)&&f(h,i):e.canSetValue(r,t,n,s,yield l.get(i))&&(d[i]=t)}))))),0!=c(y)&&x(yield l.list(),(e=>y.every((t=>!i(e,t)||f(h,e)&&0)))),yield l.delete(h),yield l.put(d)})),O=(e,t,...n)=>S(e,t,a(p(n),1,-1)),V=(e,t,n=null)=>w(void 0,null,(function*(){return new Response(n,{status:t,headers:e.config.responseHeaders})}));e.TinyBasePartyKitServer=class{constructor(e){var t,n,r,i;this.party=e,this.config={},null!=(t=this.config).storePath||(t.storePath="/store"),null!=(n=this.config).messagePrefix||(n.messagePrefix=""),null!=(r=this.config).storagePrefix||(r.storagePrefix=""),null!=(i=this.config).responseHeaders||(i.responseHeaders=T)}onRequest(e){return w(this,null,(function*(){const{party:{storage:t},config:{storePath:n,storagePrefix:r}}=this;if(new URL(e.url).pathname.endsWith(n)){const n=yield D(t,r),i=yield e.text();return"PUT"==e.method?n?V(this,205):(yield H(this,P(i),!0,e),V(this,201)):V(this,200,n?p(yield R(t,r)):"")}return V(this,404)}))}onMessage(e,t){return w(this,null,(function*(){const{config:{messagePrefix:n,storagePrefix:r}}=this;yield l(m(n,e,1),(e=>w(this,[e],(function*([e,n]){"s"==e&&(yield D(this.party.storage,r))&&(yield H(this,n,!1,t),C(this,n,[t.id]))}))))}))}canSetTable(e,t,n){return!0}canDelTable(e,t){return!0}canSetRow(e,t,n,r){return!0}canDelRow(e,t,n){return!0}canSetCell(e,t,n,r,i,s,o){return!0}canDelCell(e,t,n,r){return!0}canSetValue(e,t,n,r,i){return!0}canDelValue(e,t){return!0}},e.broadcastTransactionChanges=C,e.hasStoreInStorage=D,e.loadStoreFromStorage=R},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterPartyKitServer={});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
@@ -214,7 +214,7 @@
214
214
  },
215
215
  "devDependencies": {
216
216
  "@automerge/automerge": "^2.1.7",
217
- "@babel/cli": "^7.23.0",
217
+ "@babel/cli": "^7.23.4",
218
218
  "@babel/core": "^7.23.3",
219
219
  "@babel/preset-env": "^7.23.3",
220
220
  "@babel/preset-react": "^7.23.3",
@@ -223,21 +223,21 @@
223
223
  "@rollup/plugin-image": "^3.0.3",
224
224
  "@rollup/plugin-replace": "^5.0.5",
225
225
  "@rollup/plugin-terser": "^0.4.4",
226
- "@sqlite.org/sqlite-wasm": "^3.44.0-build2",
226
+ "@sqlite.org/sqlite-wasm": "^3.44.1-build2",
227
227
  "@types/asciichart": "^1.5.8",
228
228
  "@types/expect-puppeteer": "^5.0.6",
229
229
  "@types/http-server": "^0.12.4",
230
- "@types/jest": "^29.5.8",
230
+ "@types/jest": "^29.5.10",
231
231
  "@types/jest-environment-puppeteer": "^5.0.6",
232
232
  "@types/less": "^3.0.6",
233
- "@types/node": "^20.9.0",
233
+ "@types/node": "^20.9.4",
234
234
  "@types/puppeteer": "^5.4.7",
235
- "@types/react": "^18.2.37",
236
- "@types/react-dom": "^18.2.15",
237
- "@types/react-test-renderer": "^18.0.6",
235
+ "@types/react": "^18.2.38",
236
+ "@types/react-dom": "^18.2.17",
237
+ "@types/react-test-renderer": "^18.0.7",
238
238
  "@types/tmp": "^0.2.6",
239
- "@typescript-eslint/eslint-plugin": "^6.11.0",
240
- "@typescript-eslint/parser": "^6.11.0",
239
+ "@typescript-eslint/eslint-plugin": "^6.12.0",
240
+ "@typescript-eslint/parser": "^6.12.0",
241
241
  "@vlcn.io/crsqlite-wasm": "^0.15.2",
242
242
  "asciichart": "^1.5.25",
243
243
  "automerge-repo": "^0.1.0",
@@ -249,8 +249,8 @@
249
249
  "buffer-replace": "^1.0.0",
250
250
  "country-flag-emoji-json": "^2.0.0",
251
251
  "cspell": "^8.0.0",
252
- "esbuild": "^0.19.5",
253
- "eslint": "^8.53.0",
252
+ "esbuild": "^0.19.7",
253
+ "eslint": "^8.54.0",
254
254
  "eslint-config-prettier": "^9.0.0",
255
255
  "eslint-plugin-jest": "^27.6.0",
256
256
  "eslint-plugin-jsdoc": "^46.9.0",
@@ -267,14 +267,14 @@
267
267
  "jest-fetch-mock": "^3.0.3",
268
268
  "jest-puppeteer": "^9.0.1",
269
269
  "less": "^4.2.0",
270
- "partykit": "^0.0.37",
271
- "partysocket": "^0.0.15",
270
+ "partykit": "^0.0.39",
271
+ "partysocket": "^0.0.16",
272
272
  "prettier": "^3.1.0",
273
273
  "puppeteer": "21.1.1",
274
274
  "react": "^18.2.0",
275
275
  "react-dom": "^18.2.0",
276
276
  "react-test-renderer": "^18.2.0",
277
- "rollup": "^4.4.1",
277
+ "rollup": "^4.5.1",
278
278
  "rollup-plugin-esbuild": "^6.1.0",
279
279
  "rollup-plugin-gzip": "^3.1.0",
280
280
  "rollup-plugin-preserve-shebang": "^1.0.1",
@@ -284,20 +284,20 @@
284
284
  "tinydocs": "^0.1.33",
285
285
  "tmp": "^0.2.1",
286
286
  "ts-unused-exports": "^10.0.1",
287
- "typescript": "5.2.2",
288
- "yjs": "^13.6.8"
287
+ "typescript": "5.3.2",
288
+ "yjs": "^13.6.10"
289
289
  },
290
290
  "peerDependencies": {
291
- "@sqlite.org/sqlite-wasm": "^3.44.0-build1",
291
+ "@sqlite.org/sqlite-wasm": "^3.44.1-build2",
292
292
  "@vlcn.io/crsqlite-wasm": "^0.15.2",
293
293
  "automerge-repo": "^0.1.0",
294
- "partykit": "^0.0.37",
295
- "partysocket": "^0.0.15",
294
+ "partykit": "^0.0.39",
295
+ "partysocket": "^0.0.16",
296
296
  "prettier": "^3.0.3",
297
297
  "react": "^18.2.0",
298
298
  "react-dom": "^18.2.0",
299
299
  "sqlite3": "^5.1.6",
300
- "yjs": "^13.6.7"
300
+ "yjs": "^13.6.10"
301
301
  },
302
302
  "peerDependenciesMeta": {
303
303
  "@sqlite.org/sqlite-wasm": {
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- <section id="hero"><h2 id="the-reactive-data-store-for-local-first-apps">The <em>reactive</em> data store for <span>local-first apps</span>.</h2><p id="copy">Build blisteringly fast web apps that work both online and offline. Manage your state locally, synchronize it to the cloud when you need to, or even make it collaborative. But, most importantly... have fun building stuff again!</p></section><p><a href="https://tinybase.org/guides/releases/#v4-5"><em>NEW!</em> v4.5 release</a> <span id="one-with">&quot;The One With Expo SQLite Next&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><ul><li>Manage <a href="#start-with-a-simple-key-value-store">key-value data</a>, <a href="#level-up-to-use-tabular-data">tabular data</a> - or both - with optional <a href="#apply-schemas-to-tables-values">schematization</a> to model your app&#x27;s data structures.</li><li><a href="#register-granular-listeners">Flexibly reactive</a> to reconciled updates, so you only spend rendering cycles on things that change.</li><li><a href="#build-complex-queries-with-tinyql">Powerful query engine</a> to select, join, filter, group, sort and paginate data - reactively - and without SQL.</li><li>Built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, <a href="#model-table-relationships">tabular relationships</a> - and even an <a href="#set-checkpoints-for-an-undo-stack">undo stack</a> for your app state.</li><li>Create <a href="#type-definitions-orm-like-apis">type definitions &amp; ORM-like APIs</a>, from schema or inference. <a href="#an-inspector-for-your-data">Inspect your data</a> (<em>new!</em>) directly in the browser.</li><li>Easily <a href="#persist-to-storage-sqlite-crdts">sync your data</a> to browser <a href="https://tinybase.org/api/persister-browser">storage</a>, <a href="https://tinybase.org/api/persister-indexed-db/">IndexedDB</a>, <a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence/">SQLite</a>, <a href="https://tinybase.org/guides/schemas-and-persistence/synchronizing-data/">CRDTs</a>, and (<em>new!</em>) <a href="https://tinybase.org/api/persister-partykit-client/">PartyKit</a>.</li><li>Optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and (<em>new!</em>) <a href="#pre-built-reactive-components">pre-built components</a> that let you easily build fully reactive user interfaces.</li><li>Tiny by name, tiny by nature: <a href="#did-we-say-tiny">5.0kB - 9.4kB</a>, no dependencies. <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</li></ul><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">Tinybase works great on its own, but also plays well with friends!</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img width="48" src="https://tinybase.org/react.svg"> React</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img width="48" src="https://tinybase.org/partykit.svg"> PartyKit</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/expo.svg">Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/sqlite.svg"> SQLite</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img width="48" src="https://tinybase.org/indexeddb.svg"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img width="48" src="https://tinybase.org/yjs.svg"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img width="48" src="https://tinybase.org/crsqlite.png"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img width="48" src="https://tinybase.org/automerge.svg"> Automerge</a></div></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;label=Twitter&amp;labelColor=%23333&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=jest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/4.5.0" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/store/functions/creation/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
1
+ <section id="hero"><h2 id="the-reactive-data-store-for-local-first-apps">The <em>reactive</em> data store for <span>local-first apps</span>.</h2><p id="copy">Build blisteringly fast web apps that work both online and offline. Manage your state locally, synchronize it to the cloud when you need to, or even make it collaborative. But, most importantly... have fun building stuff again!</p></section><p><a href="https://tinybase.org/guides/releases/#v4-5"><em>NEW!</em> v4.5 release</a> <span id="one-with">&quot;The One With Expo SQLite Next&quot;</span></p><p><a class="start" href="https://tinybase.org/guides/the-basics/getting-started/">Get started</a></p><p><a href="https://tinybase.org/demos/">Try the demos</a></p><p><a href="https://tinybase.org/api/store/interfaces/store/store/">Read the docs</a></p><hr><ul><li>Manage <a href="#start-with-a-simple-key-value-store">key-value data</a>, <a href="#level-up-to-use-tabular-data">tabular data</a> - or both - with optional <a href="#apply-schemas-to-tables-values">schematization</a> to model your app&#x27;s data structures.</li><li><a href="#register-granular-listeners">Flexibly reactive</a> to reconciled updates, so you only spend rendering cycles on things that change.</li><li><a href="#build-complex-queries-with-tinyql">Powerful query engine</a> to select, join, filter, group, sort and paginate data - reactively - and without SQL.</li><li>Built-in <a href="#create-indexes-for-fast-lookups">indexing</a>, <a href="#define-metrics-and-aggregations">metric aggregation</a>, <a href="#model-table-relationships">tabular relationships</a> - and even an <a href="#set-checkpoints-for-an-undo-stack">undo stack</a> for your app state.</li><li>Create <a href="#type-definitions-orm-like-apis">type definitions &amp; ORM-like APIs</a>, from schema or inference. <a href="#an-inspector-for-your-data">Inspect your data</a> (<em>new!</em>) directly in the browser.</li><li>Easily <a href="#persist-to-storage-sqlite-crdts">sync your data</a> to browser <a href="https://tinybase.org/api/persister-browser">storage</a>, <a href="https://tinybase.org/api/persister-indexed-db/">IndexedDB</a>, <a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence/">SQLite</a>, <a href="https://tinybase.org/guides/schemas-and-persistence/synchronizing-data/">CRDTs</a>, and (<em>new!</em>) <a href="https://tinybase.org/api/persister-partykit-client/">PartyKit</a>.</li><li>Optional <a href="#call-hooks-to-bind-to-data">bindings to React</a> and (<em>new!</em>) <a href="#pre-built-reactive-components">pre-built components</a> that let you easily build fully reactive user interfaces.</li><li>Tiny by name, tiny by nature: <a href="#did-we-say-tiny">5.0kB - 9.4kB</a>, no dependencies. <a href="#well-tested-and-documented">100% tested</a>, <a href="https://tinybase.org/guides/the-basics/getting-started/">fully documented</a>, and of course, <a href="https://github.com/tinyplex/tinybase">open source</a>!</li></ul><hr><section id="friends"><h2 id="tinybase-works-great-on-its-own-but-also-plays-well-with-friends">Tinybase works great on its own, but also plays well with friends!</h2><div><a href="https://tinybase.org/guides/building-uis/getting-started-with-ui-react"><img width="48" src="https://tinybase.org/react.svg"> React</a></div><div><a href="https://tinybase.org/api/persister-partykit-client"><img width="48" src="https://tinybase.org/partykit.svg"> PartyKit</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/expo.svg">Expo SQLite</a></div><div><a href="https://tinybase.org/guides/schemas-and-persistence/database-persistence"><img width="48" src="https://tinybase.org/sqlite.svg"> SQLite</a></div><div><a href="https://tinybase.org/api/persister-indexed-db/functions/creation/createindexeddbpersister"><img width="48" src="https://tinybase.org/indexeddb.svg"> IndexedDB</a></div><div><a href="https://tinybase.org/api/persister-yjs/functions/creation/createyjspersister"><img width="48" src="https://tinybase.org/yjs.svg"> YJS</a></div><div><a href="https://tinybase.org/api/persister-cr-sqlite-wasm"><img width="48" src="https://tinybase.org/crsqlite.png"> CR-SQLite</a></div><div><a href="https://tinybase.org/api/persister-automerge"><img width="48" src="https://tinybase.org/automerge.svg"> Automerge</a></div></section><hr><section id="follow"><a href="https://github.com/tinyplex/tinybase" target="_blank"><img src="https://img.shields.io/github/stars/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=GitHub&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&amp;logo=discord&amp;logoColor=%23fff&amp;label=Discord&amp;labelColor=%233131e8&amp;color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&amp;logo=x&amp;logoColor=%23fff&amp;label=Twitter&amp;labelColor=%23333&amp;color=%23333"></a><br><a href="https://github.com/tinyplex/tinybase/discussions" target="_blank"><img src="https://img.shields.io/github/discussions/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Ideas&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="https://github.com/tinyplex/tinybase/issues" target="_blank"><img src="https://img.shields.io/github/issues/tinyplex/tinybase?style=for-the-badge&amp;logo=GitHub&amp;logoColor=%23fff&amp;label=Issues&amp;labelColor=%23d81b60&amp;color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&amp;logo=jest&amp;logoColor=%23fff&amp;color=%23333&amp;labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/4.5.2" target="_blank"><img src="https://img.shields.io/npm/v/tinybase?style=for-the-badge&amp;logo=npm&amp;logoColor=%23fff&amp;labelColor=%23bd0005&amp;color=%23333"></a></section><hr><section><h2 id="start-with-a-simple-key-value-store">Start with a simple key-value store.</h2><p>Creating a <a href="https://tinybase.org/api/store/interfaces/store/store/"><code>Store</code></a> requires just a simple call to the <a href="https://tinybase.org/api/store/functions/creation/createstore/"><code>createStore</code></a> function. Once you have one, you can easily set <a href="https://tinybase.org/api/store/type-aliases/store/values/"><code>Values</code></a> in it by unique <a href="https://tinybase.org/api/common/type-aliases/identity/id/"><code>Id</code></a>. And of course you can easily get them back out again.</p><p>Read more about using keyed value data in <a href="https://tinybase.org/guides/the-basics/">The Basics</a> guide.</p></section>
2
2
 
3
3
  ```js
4
4
  const store = createStore()