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.
- package/lib/cjs/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/debug/persisters/persister-partykit-server.js +17 -6
- package/lib/es6/persisters/persister-partykit-server.js +1 -1
- package/lib/es6/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/persisters/persister-partykit-server.js +1 -1
- package/lib/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/types/persisters/persister-partykit-server.d.ts +24 -0
- package/lib/types/with-schemas/persisters/persister-partykit-server.d.ts +34 -0
- package/lib/umd/persisters/persister-partykit-server.js +1 -1
- package/lib/umd/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-partykit-server.js +1 -1
- package/lib/umd-es6/persisters/persister-partykit-server.js.gz +0 -0
- package/package.json +21 -21
- package/readme.md +1 -1
|
@@ -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),
|
|
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;
|
|
Binary file
|
|
@@ -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)),
|
|
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;
|
|
Binary file
|
|
@@ -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
|
-
|
|
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 {
|
|
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,
|
|
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};
|
|
Binary file
|
|
@@ -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),
|
|
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};
|
|
Binary file
|
|
@@ -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),
|
|
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={});
|
|
Binary file
|
|
@@ -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),
|
|
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={});
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinybase",
|
|
3
|
-
"version": "4.5.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
233
|
+
"@types/node": "^20.9.4",
|
|
234
234
|
"@types/puppeteer": "^5.4.7",
|
|
235
|
-
"@types/react": "^18.2.
|
|
236
|
-
"@types/react-dom": "^18.2.
|
|
237
|
-
"@types/react-test-renderer": "^18.0.
|
|
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.
|
|
240
|
-
"@typescript-eslint/parser": "^6.
|
|
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.
|
|
253
|
-
"eslint": "^8.
|
|
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.
|
|
271
|
-
"partysocket": "^0.0.
|
|
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.
|
|
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.
|
|
288
|
-
"yjs": "^13.6.
|
|
287
|
+
"typescript": "5.3.2",
|
|
288
|
+
"yjs": "^13.6.10"
|
|
289
289
|
},
|
|
290
290
|
"peerDependencies": {
|
|
291
|
-
"@sqlite.org/sqlite-wasm": "^3.44.
|
|
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.
|
|
295
|
-
"partysocket": "^0.0.
|
|
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.
|
|
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">"The One With Expo SQLite Next"</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'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 & 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&logo=GitHub&logoColor=%23fff&label=GitHub&labelColor=%23d81b60&color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&logo=discord&logoColor=%23fff&label=Discord&labelColor=%233131e8&color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&logo=x&logoColor=%23fff&label=Twitter&labelColor=%23333&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&logo=GitHub&logoColor=%23fff&label=Ideas&labelColor=%23d81b60&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&logo=GitHub&logoColor=%23fff&label=Issues&labelColor=%23d81b60&color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&logo=jest&logoColor=%23fff&color=%23333&labelColor=%2387c305"> </a><a href="https://www.npmjs.com/package/tinybase/v/4.5.
|
|
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">"The One With Expo SQLite Next"</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'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 & 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&logo=GitHub&logoColor=%23fff&label=GitHub&labelColor=%23d81b60&color=%23333"> </a><a href="https://discord.com/invite/mGz3mevwP8" target="_blank"><img src="https://img.shields.io/discord/1027918215323590676?style=for-the-badge&logo=discord&logoColor=%23fff&label=Discord&labelColor=%233131e8&color=%23333"> </a><a href="https://twitter.com/tinybasejs" target="_blank"><img src="https://img.shields.io/twitter/follow/tinybasejs?style=for-the-badge&logo=x&logoColor=%23fff&label=Twitter&labelColor=%23333&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&logo=GitHub&logoColor=%23fff&label=Ideas&labelColor=%23d81b60&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&logo=GitHub&logoColor=%23fff&label=Issues&labelColor=%23d81b60&color=%23333"> </a><a href="#well-tested-and-documented"><img src="https://img.shields.io/badge/Tests-100%25-green?style=for-the-badge&logo=jest&logoColor=%23fff&color=%23333&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&logo=npm&logoColor=%23fff&labelColor=%23bd0005&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()
|