tinybase 6.1.0-beta.3 → 6.1.0-beta.4

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.
@@ -17,6 +17,7 @@
17
17
  * |IndexedDbPersister|Browser IndexedDB|Yes|No
18
18
  * |RemotePersister|Remote server|Yes|No
19
19
  * |Sqlite3Persister|SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3)|Yes|Yes*
20
+ * |SqliteBunPersister| SQLite in Bun, via [bun:sqlite](https://bun.sh/docs/api/sqlite)|Yes|Yes*
20
21
  * |SqliteWasmPersister|SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm)|Yes|Yes*
21
22
  * |ExpoSqlitePersister|SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite)|Yes|Yes*
22
23
  * |PostgresPersister|PostgreSQL, via [postgres](https://github.com/porsager/postgres)|Yes|Yes*
@@ -0,0 +1,159 @@
1
+ /**
2
+ * The persister-sqlite-bun module of the TinyBase project lets you save and
3
+ * load Store data to and from a local Bun SQLite database (in an appropriate
4
+ * environment).
5
+ * @see Database Persistence guide
6
+ * @packageDocumentation
7
+ * @module persister-sqlite-bun
8
+ * @since v6.1.0
9
+ */
10
+ import type {Database} from 'bun:sqlite';
11
+ import type {MergeableStore} from '../../mergeable-store/index.d.ts';
12
+ import type {Store} from '../../store/index.d.ts';
13
+ import type {DatabasePersisterConfig, Persister, Persists} from '../index.d.ts';
14
+
15
+ /**
16
+ * The SqliteBunPersister interface represents a Persister that lets you save
17
+ * and load Store data to and from a local Bun SQLite database.
18
+ *
19
+ * You should use the createSqliteBunPersister function to create a
20
+ * SqliteBunPersister object.
21
+ *
22
+ * It is a minor extension to the Persister interface and simply provides an
23
+ * extra getDb method for accessing a reference to the database instance the
24
+ * Store is being persisted to.
25
+ * @category Persister
26
+ * @since v6.1.0
27
+ */
28
+ export interface SqliteBunPersister
29
+ extends Persister<Persists.StoreOrMergeableStore> {
30
+ /**
31
+ * The getDb method returns a reference to the database instance the Store is
32
+ * being persisted to.
33
+ * @returns A reference to the database instance.
34
+ * @example
35
+ * This example creates a Persister object against a newly-created Store and
36
+ * then gets the database instance back out again.
37
+ *
38
+ * ```js bun
39
+ * import {Database} from 'bun:sqlite';
40
+ * import {createStore} from 'tinybase';
41
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
42
+ *
43
+ * const db = new Database(':memory:');
44
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
45
+ * const persister = createSqliteBunPersister(store, db, 'my_tinybase');
46
+ *
47
+ * console.log(persister.getDb() == db);
48
+ * // -> true
49
+ *
50
+ * persister.destroy();
51
+ * ```
52
+ * @category Getter
53
+ * @since v6.1.0
54
+ */
55
+ getDb(): Database;
56
+ }
57
+
58
+ /**
59
+ * The createSqliteBunPersister function creates a SqliteBunPersister object
60
+ * that can persist the Store to a local Bun SQLite database.
61
+ *
62
+ * A SqliteBunPersister supports regular Store objects, and can also be used to
63
+ * persist the metadata of a MergeableStore when using the JSON serialization
64
+ * mode, as described below.
65
+ *
66
+ * As well as providing a reference to the Store to persist, you must provide a
67
+ * `db` parameter which identifies the database instance.
68
+ *
69
+ * A database Persister uses one of two modes: either a JSON serialization of
70
+ * the whole Store stored in a single row of a table (the default), or a tabular
71
+ * mapping of Table Ids to database table names and vice-versa).
72
+ *
73
+ * The third argument is a DatabasePersisterConfig object that configures which
74
+ * of those modes to use, and settings for each. If the third argument is simply
75
+ * a string, it is used as the `storeTableName` property of the JSON
76
+ * serialization.
77
+ *
78
+ * See the documentation for the DpcJson and DpcTabular types for more
79
+ * information on how both of those modes can be configured.
80
+ * @param store The Store or MergeableStore to persist.
81
+ * @param db The database instance that was returned from `new Database(...)`.
82
+ * @param configOrStoreTableName A DatabasePersisterConfig to configure the
83
+ * persistence mode (or a string to set the `storeTableName` property of the
84
+ * JSON serialization).
85
+ * @param onSqlCommand An optional handler called every time the Persister
86
+ * executes a SQL command or query. This is suitable for logging persistence
87
+ * behavior in a development environment.
88
+ * @param onIgnoredError An optional handler for the errors that the Persister
89
+ * would otherwise ignore when trying to save or load data. This is suitable for
90
+ * debugging persistence issues in a development environment.
91
+ * @returns A reference to the new SqliteBunPersister object.
92
+ * @example
93
+ * This example creates a SqliteBunPersister object and persists the Store to a
94
+ * local SQLite database as a JSON serialization into the `my_tinybase` table.
95
+ * It makes a change to the database directly and then reloads it back into the
96
+ * Store.
97
+ *
98
+ * ```js bun
99
+ * import {Database} from 'bun:sqlite';
100
+ * import {createStore} from 'tinybase';
101
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
102
+ *
103
+ * const db = new Database(':memory:');
104
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
105
+ * const persister = createSqliteBunPersister(store, db, 'my_tinybase');
106
+ *
107
+ * await persister.save();
108
+ * // Store will be saved to the database.
109
+ *
110
+ * console.log(db.query('SELECT * FROM my_tinybase;').all());
111
+ * // -> [{_id: '_', store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
112
+ *
113
+ * db.query(
114
+ * 'UPDATE my_tinybase SET store = ' +
115
+ * `'[{"pets":{"felix":{"species":"cat"}}},{}]' WHERE _id = '_';`,
116
+ * ).run();
117
+ * await persister.load();
118
+ * console.log(store.getTables());
119
+ * // -> {pets: {felix: {species: 'cat'}}}
120
+ *
121
+ * persister.destroy();
122
+ * ```
123
+ * @example
124
+ * This example creates a SqliteBunPersister object and persists the Store to a
125
+ * local SQLite database with tabular mapping.
126
+ *
127
+ * ```js bun
128
+ * import {Database} from 'bun:sqlite';
129
+ * import {createStore} from 'tinybase';
130
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
131
+ *
132
+ * const db = new Database(':memory:');
133
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
134
+ * const persister = createSqliteBunPersister(store, db, {
135
+ * mode: 'tabular',
136
+ * tables: {load: {pets: 'pets'}, save: {pets: 'pets'}},
137
+ * });
138
+ *
139
+ * await persister.save();
140
+ * console.log(db.query('SELECT * FROM pets;').all());
141
+ * // -> [{_id: 'fido', species: 'dog'}]
142
+ *
143
+ * db.query(`INSERT INTO pets (_id, species) VALUES ('felix', 'cat')`).run();
144
+ * await persister.load();
145
+ * console.log(store.getTables());
146
+ * // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
147
+ *
148
+ * persister.destroy();
149
+ * ```
150
+ * @category Creation
151
+ * @since v6.1.0
152
+ */
153
+ export function createSqliteBunPersister(
154
+ store: Store | MergeableStore,
155
+ db: Database,
156
+ configOrStoreTableName?: DatabasePersisterConfig | string,
157
+ onSqlCommand?: (sql: string, params?: any[]) => void,
158
+ onIgnoredError?: (error: any) => void,
159
+ ): SqliteBunPersister;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * The persister-sqlite-bun module of the TinyBase project lets you save and
3
+ * load Store data to and from a local Bun SQLite database (in an appropriate
4
+ * environment).
5
+ * @see Database Persistence guide
6
+ * @packageDocumentation
7
+ * @module persister-sqlite-bun
8
+ * @since v6.1.0
9
+ */
10
+ import type {Database} from 'bun:sqlite';
11
+ import type {MergeableStore} from '../../../mergeable-store/with-schemas/index.d.ts';
12
+ import type {
13
+ OptionalSchemas,
14
+ Store,
15
+ } from '../../../store/with-schemas/index.d.ts';
16
+ import type {
17
+ DatabasePersisterConfig,
18
+ Persister,
19
+ Persists,
20
+ } from '../../with-schemas/index.d.ts';
21
+
22
+ /**
23
+ * The SqliteBunPersister interface represents a Persister that lets you save
24
+ * and load Store data to and from a local Bun SQLite database.
25
+ *
26
+ * You should use the createSqliteBunPersister function to create a
27
+ * SqliteBunPersister object.
28
+ *
29
+ * It is a minor extension to the Persister interface and simply provides an
30
+ * extra getDb method for accessing a reference to the database instance the
31
+ * Store is being persisted to.
32
+ * @category Persister
33
+ * @since v6.1.0
34
+ */
35
+ export interface SqliteBunPersister<Schemas extends OptionalSchemas>
36
+ extends Persister<Schemas, Persists.StoreOrMergeableStore> {
37
+ /**
38
+ * The getDb method returns a reference to the database instance the Store is
39
+ * being persisted to.
40
+ * @returns A reference to the database instance.
41
+ * @example
42
+ * This example creates a Persister object against a newly-created Store and
43
+ * then gets the database instance back out again.
44
+ *
45
+ * ```js bun
46
+ * import {Database} from 'bun:sqlite';
47
+ * import {createStore} from 'tinybase';
48
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
49
+ *
50
+ * const db = new Database(':memory:');
51
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
52
+ * const persister = createSqliteBunPersister(store, db, 'my_tinybase');
53
+ *
54
+ * console.log(persister.getDb() == db);
55
+ * // -> true
56
+ *
57
+ * persister.destroy();
58
+ * ```
59
+ * @category Getter
60
+ * @since v6.1.0
61
+ */
62
+ getDb(): Database;
63
+ }
64
+
65
+ /**
66
+ * The createSqliteBunPersister function creates a SqliteBunPersister object
67
+ * that can persist the Store to a local Bun SQLite database.
68
+ *
69
+ * This has schema-based typing. The following is a simplified representation:
70
+ *
71
+ * ```ts override
72
+ * createSqliteBunPersister(
73
+ * store: Store | MergeableStore,
74
+ * db: Database,
75
+ * configOrStoreTableName?: DatabasePersisterConfig | string,
76
+ * onSqlCommand?: (sql: string, params?: any[]) => void,
77
+ * onIgnoredError?: (error: any) => void,
78
+ * ): SqliteBunPersister;
79
+ * ```
80
+ *
81
+ * A SqliteBunPersister supports regular Store objects, and can also be used to
82
+ * persist the metadata of a MergeableStore when using the JSON serialization
83
+ * mode, as described below.
84
+ *
85
+ * As well as providing a reference to the Store to persist, you must provide a
86
+ * `db` parameter which identifies the database instance.
87
+ *
88
+ * A database Persister uses one of two modes: either a JSON serialization of
89
+ * the whole Store stored in a single row of a table (the default), or a tabular
90
+ * mapping of Table Ids to database table names and vice-versa).
91
+ *
92
+ * The third argument is a DatabasePersisterConfig object that configures which
93
+ * of those modes to use, and settings for each. If the third argument is simply
94
+ * a string, it is used as the `storeTableName` property of the JSON
95
+ * serialization.
96
+ *
97
+ * See the documentation for the DpcJson and DpcTabular types for more
98
+ * information on how both of those modes can be configured.
99
+ * @param store The Store or MergeableStore to persist.
100
+ * @param db The database instance that was returned from `new Database(...)`.
101
+ * @param configOrStoreTableName A DatabasePersisterConfig to configure the
102
+ * persistence mode (or a string to set the `storeTableName` property of the
103
+ * JSON serialization).
104
+ * @param onSqlCommand An optional handler called every time the Persister
105
+ * executes a SQL command or query. This is suitable for logging persistence
106
+ * behavior in a development environment.
107
+ * @param onIgnoredError An optional handler for the errors that the Persister
108
+ * would otherwise ignore when trying to save or load data. This is suitable for
109
+ * debugging persistence issues in a development environment.
110
+ * @returns A reference to the new SqliteBunPersister object.
111
+ * @example
112
+ * This example creates a SqliteBunPersister object and persists the Store to a
113
+ * local SQLite database as a JSON serialization into the `my_tinybase` table.
114
+ * It makes a change to the database directly and then reloads it back into the
115
+ * Store.
116
+ *
117
+ * ```js bun
118
+ * import {Database} from 'bun:sqlite';
119
+ * import {createStore} from 'tinybase';
120
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
121
+ *
122
+ * const db = new Database(':memory:');
123
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
124
+ * const persister = createSqliteBunPersister(store, db, 'my_tinybase');
125
+ *
126
+ * await persister.save();
127
+ * // Store will be saved to the database.
128
+ *
129
+ * console.log(db.query('SELECT * FROM my_tinybase;').all());
130
+ * // -> [{_id: '_', store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
131
+ *
132
+ * db.query(
133
+ * 'UPDATE my_tinybase SET store = ' +
134
+ * `'[{"pets":{"felix":{"species":"cat"}}},{}]' WHERE _id = '_';`,
135
+ * ).run();
136
+ * await persister.load();
137
+ * console.log(store.getTables());
138
+ * // -> {pets: {felix: {species: 'cat'}}}
139
+ *
140
+ * persister.destroy();
141
+ * ```
142
+ * @example
143
+ * This example creates a SqliteBunPersister object and persists the Store to a
144
+ * local SQLite database with tabular mapping.
145
+ *
146
+ * ```js bun
147
+ * import {Database} from 'bun:sqlite';
148
+ * import {createStore} from 'tinybase';
149
+ * import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
150
+ *
151
+ * const db = new Database(':memory:');
152
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
153
+ * const persister = createSqliteBunPersister(store, db, {
154
+ * mode: 'tabular',
155
+ * tables: {load: {pets: 'pets'}, save: {pets: 'pets'}},
156
+ * });
157
+ *
158
+ * await persister.save();
159
+ * console.log(db.query('SELECT * FROM pets;').all());
160
+ * // -> [{_id: 'fido', species: 'dog'}]
161
+ *
162
+ * db.query(`INSERT INTO pets (_id, species) VALUES ('felix', 'cat')`).run();
163
+ * await persister.load();
164
+ * console.log(store.getTables());
165
+ * // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
166
+ *
167
+ * persister.destroy();
168
+ * ```
169
+ * @category Creation
170
+ * @since v6.1.0
171
+ */
172
+ export function createSqliteBunPersister<Schemas extends OptionalSchemas>(
173
+ store: Store<Schemas> | MergeableStore<Schemas>,
174
+ db: Database,
175
+ configOrStoreTableName?: DatabasePersisterConfig<Schemas> | string,
176
+ onSqlCommand?: (sql: string, params?: any[]) => void,
177
+ onIgnoredError?: (error: any) => void,
178
+ ): SqliteBunPersister<Schemas>;
@@ -17,6 +17,7 @@
17
17
  * |IndexedDbPersister|Browser IndexedDB|Yes|No
18
18
  * |RemotePersister|Remote server|Yes|No
19
19
  * |Sqlite3Persister|SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3)|Yes|Yes*
20
+ * |SqliteBunPersister| SQLite in Bun, via [bun:sqlite](https://bun.sh/docs/api/sqlite)|Yes|Yes*
20
21
  * |SqliteWasmPersister|SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm)|Yes|Yes*
21
22
  * |ExpoSqlitePersister|SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite)|Yes|Yes*
22
23
  * |PostgresPersister|PostgreSQL, via [postgres](https://github.com/porsager/postgres)|Yes|Yes*
@@ -0,0 +1 @@
1
+ const a=a=>typeof a,t="tinybase",e="",n=",",s=a(e),i=Promise,o=clearInterval,r=a=>null==a,c=(a,t,e)=>r(a)?e?.():t(a),l=t=>a(t)==s,y=a=>Array.isArray(a),u=(a,t,e)=>a.slice(t,e),w=a=>a.length,d=async a=>i.all(a),v=a=>{throw Error(a)},p=(a,t)=>a.forEach(t),E=(a,t="")=>a.join(t),g=(a,t)=>a.map(t),A=a=>0==w(a),h=(a,t)=>a.filter(t),m=(a,...t)=>a.push(...t),N=a=>a.shift(),$=(a,t)=>a?.has(t)??!1,f=a=>r(a)||0==(a=>a?.size??0)(a),S=a=>[...a?.values()??[]],C=(a,t)=>a?.forEach(t),O=(a,t)=>a?.delete(t),T="_",I="_id",L="SELECT",b="WHERE",D="TABLE",R="ALTER "+D,M="DELETE FROM",_=L+"*FROM",P="pragma_",F="data_version",U="schema_version",j="pragma_table_",B=a=>`"${a.replace(/"/g,'""')}"`,J=(a,t=[1])=>E(g(a,(()=>"$"+t[0]++)),n),Y=Object,k=a=>Y.getPrototypeOf(a),x=Y.entries,z=Y.keys,G=Y.freeze,H=(a=[])=>Y.fromEntries(a),q=(...a)=>Y.assign({},...a),K=(a,t)=>(delete a[t],a),Q=(a,t)=>g(x(a),(([a,e])=>t(e,a))),V=(a,t)=>H(Q(a,((a,e)=>[e,t(a,e)]))),W=a=>Y.values(a),X=a=>w(z(a)),Z=a=>(a=>!r(a)&&c(k(a),(a=>a==Y.prototype||r(k(a))),(()=>!0)))(a)&&0==X(a),aa=a=>new Map(a),ta=(a,t)=>a?.get(t),ea=(a,t)=>g([...a?.entries()??[]],(([a,e])=>t(e,a))),na=(a,t,e)=>r(e)?(O(a,t),a):a?.set(t,e),sa=(a,t,e,n)=>($(a,t)?n?.(ta(a,t)):na(a,t,e()),ta(a,t)),ia=(a,t,e,n,s=0)=>c((e?sa:ta)(a,t[s],s>w(t)-2?e:aa),(i=>{if(s>w(t)-2)return n?.(i)&&na(a,t[s]),i;const o=ia(i,t,e,n,s+1);return f(i)&&na(a,t[s]),o})),oa=a=>new Set(y(a)||r(a)?a:[a]),ra=(a,t)=>a?.add(t),ca="ColumnName",la="store",ya="json",ua=la+"TableName",wa=la+"Id"+ca,da=la+ca,va="autoLoadIntervalSeconds",pa="rowId"+ca,Ea="tableId",ga="tableName",Aa="deleteEmptyColumns",ha="deleteEmptyTable",ma={mode:ya,[va]:1},Na={load:0,save:0,[ga]:t+"_values"},$a=(a,t,e,n,s)=>{const i=aa();return V(a,((a,o)=>{const c=u(W(q(t,l(a)?{[e]:a}:a)),0,X(t));r(c[0])||n(o,c[0])||(s(o,c[0]),na(i,o,c))})),i},fa=JSON.stringify,Sa=JSON.parse,Ca=/^\d+$/,Oa=aa(),Ta=aa(),Ia=(a,t,n,s,i,o,l,u={},d=0,E=[])=>{let g,A,h,$=0,S=0,T=0;sa(Oa,E,(()=>0)),sa(Ta,E,(()=>[]));const I=aa(),[L,b,D,R,M]=((a=1,t,e)=>1!=a&&t.isMergeable()?[1,t.getMergeableContent,()=>t.getTransactionMergeableChanges(!e),([[a],[t]])=>!Z(a)||!Z(t),t.setDefaultContent]:2!=a?[0,t.getContent,t.getTransactionChanges,([a,t])=>!Z(a)||!Z(t),t.setContent]:v("Store type not supported by this Persister"))(l,a,d),[_,P,F]=(()=>{let a;const[t,n]=(()=>{const a=[];let t=0;return[n=>(n?N(a):null)??e+t++,t=>{Ca.test(t)&&w(a)<1e3&&m(a,t)}]})(),s=aa();return[(n,i,o,r=[],c=()=>[])=>{a??=z;const l=t(1);return na(s,l,[n,i,o,r,c]),ra(ia(i,o??[e],oa),l),l},(t,n,...i)=>p(((a,t=[e])=>{const n=[],s=(a,e)=>e==w(t)?m(n,a):null===t[e]?C(a,(a=>s(a,e+1))):p([t[e],null],(t=>s(ta(a,t),e+1)));return s(a,0),n})(t,n),(t=>C(t,(t=>ta(s,t)[0](a,...n??[],...i))))),a=>c(ta(s,a),(([,t,i])=>(ia(t,i??[e],void 0,(t=>(O(t,a),f(t)?1:0))),na(s,a),n(a),i))),t=>c(ta(s,t),(([t,,e=[],n,s])=>{const i=(...o)=>{const c=w(o);c==w(e)?t(a,...o,...s(o)):r(e[c])?p(n[c]?.(...o)??[],(a=>i(...o,a))):i(...o,e[c])};i()}))]})(),U=a=>{a!=$&&($=a,P(I,void 0,$))},j=t=>{(L&&y(t?.[0])?1===t?.[2]?a.applyMergeableChanges:a.setMergeableContent:1===t?.[2]?a.applyChanges:a.setContent)(t)},B=async a=>(2!=$&&(U(1),S++,await x((async()=>{try{const e=await t();y(e)?j(e):a?M(a):v("Content is not an array: "+e)}catch(t){o?.(t),a&&M(a)}U(0)}))),z),J=()=>(A&&(i(A),A=void 0),z),Y=async a=>(1!=$&&(U(2),T++,await x((async()=>{try{await n(b,a)}catch(a){o?.(a)}U(0)}))),z),k=()=>(h&&(a.delListener(h),h=void 0),z),x=async(...a)=>(m(ta(Ta,E),...a),await(async()=>{if(!ta(Oa,E)){for(na(Oa,E,1);!r(g=N(ta(Ta,E)));)try{await g()}catch(a){o?.(a)}na(Oa,E,0)}})(),z),z={load:B,startAutoLoad:async a=>{J(),await B(a);try{A=await s((async(a,t)=>{t||a?2!=$&&(U(1),S++,j(t??a),U(0)):await B()}))}catch(a){o?.(a)}return z},stopAutoLoad:J,isAutoLoading:()=>!r(A),save:Y,startAutoSave:async()=>(k(),await Y(),h=a.addDidFinishTransactionListener((()=>{const a=D();R(a)&&Y(a)})),z),stopAutoSave:k,isAutoSaving:()=>!r(h),getStatus:()=>$,addStatusListener:a=>_(a,I),delListener:t=>(F(t),a),schedule:x,getStore:()=>a,destroy:()=>(ta(Ta,E).splice(0,void 0),J().stopAutoSave()),getStats:()=>({loads:S,saves:T}),...u};return G(z)},La=(a,t,e,s,i,o=ba,c,l)=>{const y=aa();return[async()=>{y.clear(),g(await e(a,t),(({tn:a,cn:t})=>ra(sa(y,a,oa),t)))},async(t,e)=>((a,t)=>$(ta(y,a),t))(t,e)?H(h(g(await a(_+B(t)),(a=>[a[e],l?V(K(a,e),l):K(a,e)])),(([a,t])=>!r(a)&&!Z(t)))):{},async(t,e,s,l,u,w=!1)=>{const v=oa();V(s??{},(a=>g(z(a??{}),(a=>ra(v,a)))));const p=S(v);if(!w&&u&&A(p)&&$(y,t))return await a("DROP "+D+B(t)),void na(y,t);const N=ta(y,t),f=oa(S(N));if(A(p)||($(y,t)?await d(g([e,...p],(async(n,s)=>{O(f,n)||(await a(R+B(t)+"ADD"+B(n)+i),0==s&&await a("CREATE UNIQUE INDEX pk ON "+B(t)+`(${B(e)})`),ra(N,n))}))):(await a("CREATE "+D+B(t)+`(${B(e)}${i} PRIMARY KEY${E(g(p,(a=>n+B(a)+i)))});`),na(y,t,oa([e,...p])))),await d([...!w&&l?g(S(f),(async n=>{n!=e&&(await a(R+B(t)+"DROP"+B(n)),O(N,n))})):[]]),w)r(s)?await a(M+B(t)+b+" true"):await d(Q(s,(async(n,s)=>{r(n)?await a(M+B(t)+b+B(e)+"=$1",[s]):A(p)||await o(a,t,e,z(n),{[s]:c?g(W(n),c):W(n)},N)})));else if(A(p))$(y,t)&&await a(M+B(t)+b+" true");else{const n=h(S(ta(y,t)),(a=>a!=e)),i={},r=[];V(s??{},((a,t)=>{i[t]=g(n,(t=>c?c(a?.[t]):a?.[t])),m(r,t)})),await o(a,t,e,n,i),await a(M+B(t)+b+B(e)+`NOT IN(${J(r)})`,r)}},async t=>{let e;await a("BEGIN");try{e=await t()}catch(a){s?.(a)}return await a("END"),e}]},ba=async(a,t,e,s,i)=>{const o=[1];await a("INSERT INTO"+B(t)+"("+((...a)=>E(g(a,B),n))(e,...s)+")VALUES"+E(Q(i,(a=>"($"+o[0]+++","+J(a,o)+")")),n)+"ON CONFLICT("+B(e)+")DO UPDATE SET"+E(g(s,(a=>B(a)+"=excluded."+B(a))),n),Q(i,((a,t)=>[t,...g(a,(a=>a??null))])).flat())},Da=(a,t,e,n,s,i,o,[r,c,l],y,u,w,d,v,p)=>{const[E,g,A,h]=La(t,y,u,s,v,p),m=Ia(a,(async()=>await h((async()=>{return await E(),a=(await g(r,c))[T]?.[l]??"null",Sa(a,((a,t)=>""===t?void 0:t));var a}))),(async a=>await h((async()=>{var t;await E(),await A(r,c,{[T]:{[l]:(t=a()??null,fa(t,((a,t)=>void 0===t?"":t)))}},!0,!0)}))),e,n,s,o,{[d]:()=>w,destroy:()=>(m.stopAutoLoad().stopAutoSave(),i(),m)},0,w);return m},Ra=(a,t,e,n,s,i,o,[c,l,[y,u,w]],v,p,E,g,A,m,N,$)=>{const[f,S,C,O]=La(t,v,p,s,A,m,N,$),L=async(a,t)=>await d(ea(l,(async([e,n,s,i],o)=>{t&&!(o in a)||await C(e,n,a[o],s,i,t)}))),b=async(a,t)=>u?await C(w,I,{[T]:a},!0,!0,t):null,D=Ia(a,(async()=>await O((async()=>{await f();const a=await(async()=>H(h(await d(ea(c,(async([a,t],e)=>[a,await S(e,t)]))),(a=>!Z(a[1])))))(),t=await(async()=>y?(await S(w,I))[T]:{})();return Z(a)&&r(t)?void 0:[a,t]}))),(async(a,t)=>await O((async()=>{if(await f(),r(t)){const[t,e]=a();await L(t),await b(e)}else await L(t[0],!0),await b(t[1],!0)}))),e,n,s,o,{[g]:()=>E,destroy:()=>(D.stopAutoLoad().stopAutoSave(),i(),D)},0,E);return D},Ma=(a,n,s,i,r,c,y,w,d,v,p="getDb",E)=>{let g,A,h;const m=((a,t)=>t?async(e,n)=>(t(e,n),await a(e,n)):a)(s,c),[N,f,C,O]=(a=>{const e=(a=>q(ma,l(a)?{[ua]:a}:a??{}))(a),n=e[va];if(e.mode==ya){const a=e[ua]??t;return[1,n,[a,e[wa]??I,e[da]??la],oa(a)]}const{tables:{load:s={},save:i={}}={},values:o={}}=e,r=u(W(q(Na,o)),0,X(Na)),c=r[2],y=oa(c),w=oa(c);return[0,n,[$a(s,{[Ea]:null,[pa]:I},Ea,(a=>$(w,a)),(a=>ra(y,a))),$a(i,{[ga]:null,[pa]:I,[Aa]:0,[ha]:0},ga,((a,t)=>$(w,t)),((a,t)=>ra(y,t))),r],y]})(n);return(N?Da:Ra)(a,m,(a=>{let t;const e=()=>t=setInterval((async()=>{try{const[{d:t,s:e,c:n}]=await m(`${L} ${F} d,${U} s,TOTAL_CHANGES() c FROM ${P}${F} JOIN ${P}${U}`);t==g&&e==A&&n==h||(null!=g&&a(),g=t,A=e,h=n)}catch{}}),1e3*f),n=()=>{g=A=h=null,o(t)},s=i((t=>{O.has(t)&&(n(),a(),e())}));return e(),()=>{n(),r(s)}}),(a=>a()),y,w,d,C,S(O),(async(a,t)=>await a(`${L} t.name tn,c.name cn FROM ${j}list()t,${j}info(t.name)c ${b} t.schema='main'AND t.type IN('table','view')AND t.name IN(${J(t)})ORDER BY t.name,c.name`,t)),v,p,e,E,(a=>!0===a?1:!1===a?0:a),void 0)},_a=(a,t,e,n,s)=>Ma(a,e,(async(a,e=[])=>t.query(a).all(...e)),(()=>()=>0),(a=>a()),n,s,(()=>0),3,t);export{_a as createSqliteBunPersister};
@@ -0,0 +1 @@
1
+ const a=a=>typeof a,t="tinybase",e="",n=",",s=a(e),i=Promise,o=clearInterval,r=a=>null==a,c=(a,t,e)=>r(a)?e?.():t(a),l=t=>a(t)==s,y=a=>Array.isArray(a),u=(a,t,e)=>a.slice(t,e),w=a=>a.length,d=async a=>i.all(a),v=a=>{throw Error(a)},p=(a,t)=>a.forEach(t),E=(a,t="")=>a.join(t),g=(a,t)=>a.map(t),A=a=>0==w(a),h=(a,t)=>a.filter(t),m=(a,...t)=>a.push(...t),N=a=>a.shift(),$=(a,t)=>a?.has(t)??!1,f=a=>r(a)||0==(a=>a?.size??0)(a),S=a=>[...a?.values()??[]],C=(a,t)=>a?.forEach(t),O=(a,t)=>a?.delete(t),T="_",I="_id",L="SELECT",b="WHERE",D="TABLE",R="ALTER "+D,M="DELETE FROM",_=L+"*FROM",P="pragma_",F="data_version",U="schema_version",j="pragma_table_",B=a=>`"${a.replace(/"/g,'""')}"`,J=(a,t=[1])=>E(g(a,(()=>"$"+t[0]++)),n),Y=Object,k=a=>Y.getPrototypeOf(a),x=Y.entries,z=Y.keys,G=Y.freeze,H=(a=[])=>Y.fromEntries(a),q=(...a)=>Y.assign({},...a),K=(a,t)=>(delete a[t],a),Q=(a,t)=>g(x(a),(([a,e])=>t(e,a))),V=(a,t)=>H(Q(a,((a,e)=>[e,t(a,e)]))),W=a=>Y.values(a),X=a=>w(z(a)),Z=a=>(a=>!r(a)&&c(k(a),(a=>a==Y.prototype||r(k(a))),(()=>!0)))(a)&&0==X(a),aa=a=>new Map(a),ta=(a,t)=>a?.get(t),ea=(a,t)=>g([...a?.entries()??[]],(([a,e])=>t(e,a))),na=(a,t,e)=>r(e)?(O(a,t),a):a?.set(t,e),sa=(a,t,e,n)=>($(a,t)?n?.(ta(a,t)):na(a,t,e()),ta(a,t)),ia=(a,t,e,n,s=0)=>c((e?sa:ta)(a,t[s],s>w(t)-2?e:aa),(i=>{if(s>w(t)-2)return n?.(i)&&na(a,t[s]),i;const o=ia(i,t,e,n,s+1);return f(i)&&na(a,t[s]),o})),oa=a=>new Set(y(a)||r(a)?a:[a]),ra=(a,t)=>a?.add(t),ca="ColumnName",la="store",ya="json",ua=la+"TableName",wa=la+"Id"+ca,da=la+ca,va="autoLoadIntervalSeconds",pa="rowId"+ca,Ea="tableId",ga="tableName",Aa="deleteEmptyColumns",ha="deleteEmptyTable",ma={mode:ya,[va]:1},Na={load:0,save:0,[ga]:t+"_values"},$a=(a,t,e,n,s)=>{const i=aa();return V(a,((a,o)=>{const c=u(W(q(t,l(a)?{[e]:a}:a)),0,X(t));r(c[0])||n(o,c[0])||(s(o,c[0]),na(i,o,c))})),i},fa=JSON.stringify,Sa=JSON.parse,Ca=/^\d+$/,Oa=aa(),Ta=aa(),Ia=(a,t,n,s,i,o,l,u={},d=0,E=[])=>{let g,A,h,$=0,S=0,T=0;sa(Oa,E,(()=>0)),sa(Ta,E,(()=>[]));const I=aa(),[L,b,D,R,M]=((a=1,t,e)=>1!=a&&t.isMergeable()?[1,t.getMergeableContent,()=>t.getTransactionMergeableChanges(!e),([[a],[t]])=>!Z(a)||!Z(t),t.setDefaultContent]:2!=a?[0,t.getContent,t.getTransactionChanges,([a,t])=>!Z(a)||!Z(t),t.setContent]:v("Store type not supported by this Persister"))(l,a,d),[_,P,F]=(()=>{let a;const[t,n]=(()=>{const a=[];let t=0;return[n=>(n?N(a):null)??e+t++,t=>{Ca.test(t)&&w(a)<1e3&&m(a,t)}]})(),s=aa();return[(n,i,o,r=[],c=()=>[])=>{a??=z;const l=t(1);return na(s,l,[n,i,o,r,c]),ra(ia(i,o??[e],oa),l),l},(t,n,...i)=>p(((a,t=[e])=>{const n=[],s=(a,e)=>e==w(t)?m(n,a):null===t[e]?C(a,(a=>s(a,e+1))):p([t[e],null],(t=>s(ta(a,t),e+1)));return s(a,0),n})(t,n),(t=>C(t,(t=>ta(s,t)[0](a,...n??[],...i))))),a=>c(ta(s,a),(([,t,i])=>(ia(t,i??[e],void 0,(t=>(O(t,a),f(t)?1:0))),na(s,a),n(a),i))),t=>c(ta(s,t),(([t,,e=[],n,s])=>{const i=(...o)=>{const c=w(o);c==w(e)?t(a,...o,...s(o)):r(e[c])?p(n[c]?.(...o)??[],(a=>i(...o,a))):i(...o,e[c])};i()}))]})(),U=a=>{a!=$&&($=a,P(I,void 0,$))},j=t=>{(L&&y(t?.[0])?1===t?.[2]?a.applyMergeableChanges:a.setMergeableContent:1===t?.[2]?a.applyChanges:a.setContent)(t)},B=async a=>(2!=$&&(U(1),S++,await x((async()=>{try{const e=await t();y(e)?j(e):a?M(a):v("Content is not an array: "+e)}catch(t){o?.(t),a&&M(a)}U(0)}))),z),J=()=>(A&&(i(A),A=void 0),z),Y=async a=>(1!=$&&(U(2),T++,await x((async()=>{try{await n(b,a)}catch(a){o?.(a)}U(0)}))),z),k=()=>(h&&(a.delListener(h),h=void 0),z),x=async(...a)=>(m(ta(Ta,E),...a),await(async()=>{if(!ta(Oa,E)){for(na(Oa,E,1);!r(g=N(ta(Ta,E)));)try{await g()}catch(a){o?.(a)}na(Oa,E,0)}})(),z),z={load:B,startAutoLoad:async a=>{J(),await B(a);try{A=await s((async(a,t)=>{t||a?2!=$&&(U(1),S++,j(t??a),U(0)):await B()}))}catch(a){o?.(a)}return z},stopAutoLoad:J,isAutoLoading:()=>!r(A),save:Y,startAutoSave:async()=>(k(),await Y(),h=a.addDidFinishTransactionListener((()=>{const a=D();R(a)&&Y(a)})),z),stopAutoSave:k,isAutoSaving:()=>!r(h),getStatus:()=>$,addStatusListener:a=>_(a,I),delListener:t=>(F(t),a),schedule:x,getStore:()=>a,destroy:()=>(ta(Ta,E).splice(0,void 0),J().stopAutoSave()),getStats:()=>({loads:S,saves:T}),...u};return G(z)},La=(a,t,e,s,i,o=ba,c,l)=>{const y=aa();return[async()=>{y.clear(),g(await e(a,t),(({tn:a,cn:t})=>ra(sa(y,a,oa),t)))},async(t,e)=>((a,t)=>$(ta(y,a),t))(t,e)?H(h(g(await a(_+B(t)),(a=>[a[e],l?V(K(a,e),l):K(a,e)])),(([a,t])=>!r(a)&&!Z(t)))):{},async(t,e,s,l,u,w=!1)=>{const v=oa();V(s??{},(a=>g(z(a??{}),(a=>ra(v,a)))));const p=S(v);if(!w&&u&&A(p)&&$(y,t))return await a("DROP "+D+B(t)),void na(y,t);const N=ta(y,t),f=oa(S(N));if(A(p)||($(y,t)?await d(g([e,...p],(async(n,s)=>{O(f,n)||(await a(R+B(t)+"ADD"+B(n)+i),0==s&&await a("CREATE UNIQUE INDEX pk ON "+B(t)+`(${B(e)})`),ra(N,n))}))):(await a("CREATE "+D+B(t)+`(${B(e)}${i} PRIMARY KEY${E(g(p,(a=>n+B(a)+i)))});`),na(y,t,oa([e,...p])))),await d([...!w&&l?g(S(f),(async n=>{n!=e&&(await a(R+B(t)+"DROP"+B(n)),O(N,n))})):[]]),w)r(s)?await a(M+B(t)+b+" true"):await d(Q(s,(async(n,s)=>{r(n)?await a(M+B(t)+b+B(e)+"=$1",[s]):A(p)||await o(a,t,e,z(n),{[s]:c?g(W(n),c):W(n)},N)})));else if(A(p))$(y,t)&&await a(M+B(t)+b+" true");else{const n=h(S(ta(y,t)),(a=>a!=e)),i={},r=[];V(s??{},((a,t)=>{i[t]=g(n,(t=>c?c(a?.[t]):a?.[t])),m(r,t)})),await o(a,t,e,n,i),await a(M+B(t)+b+B(e)+`NOT IN(${J(r)})`,r)}},async t=>{let e;await a("BEGIN");try{e=await t()}catch(a){s?.(a)}return await a("END"),e}]},ba=async(a,t,e,s,i)=>{const o=[1];await a("INSERT INTO"+B(t)+"("+((...a)=>E(g(a,B),n))(e,...s)+")VALUES"+E(Q(i,(a=>"($"+o[0]+++","+J(a,o)+")")),n)+"ON CONFLICT("+B(e)+")DO UPDATE SET"+E(g(s,(a=>B(a)+"=excluded."+B(a))),n),Q(i,((a,t)=>[t,...g(a,(a=>a??null))])).flat())},Da=(a,t,e,n,s,i,o,[r,c,l],y,u,w,d,v,p)=>{const[E,g,A,h]=La(t,y,u,s,v,p),m=Ia(a,(async()=>await h((async()=>{return await E(),a=(await g(r,c))[T]?.[l]??"null",Sa(a,((a,t)=>""===t?void 0:t));var a}))),(async a=>await h((async()=>{var t;await E(),await A(r,c,{[T]:{[l]:(t=a()??null,fa(t,((a,t)=>void 0===t?"":t)))}},!0,!0)}))),e,n,s,o,{[d]:()=>w,destroy:()=>(m.stopAutoLoad().stopAutoSave(),i(),m)},0,w);return m},Ra=(a,t,e,n,s,i,o,[c,l,[y,u,w]],v,p,E,g,A,m,N,$)=>{const[f,S,C,O]=La(t,v,p,s,A,m,N,$),L=async(a,t)=>await d(ea(l,(async([e,n,s,i],o)=>{t&&!(o in a)||await C(e,n,a[o],s,i,t)}))),b=async(a,t)=>u?await C(w,I,{[T]:a},!0,!0,t):null,D=Ia(a,(async()=>await O((async()=>{await f();const a=await(async()=>H(h(await d(ea(c,(async([a,t],e)=>[a,await S(e,t)]))),(a=>!Z(a[1])))))(),t=await(async()=>y?(await S(w,I))[T]:{})();return Z(a)&&r(t)?void 0:[a,t]}))),(async(a,t)=>await O((async()=>{if(await f(),r(t)){const[t,e]=a();await L(t),await b(e)}else await L(t[0],!0),await b(t[1],!0)}))),e,n,s,o,{[g]:()=>E,destroy:()=>(D.stopAutoLoad().stopAutoSave(),i(),D)},0,E);return D},Ma=(a,n,s,i,r,c,y,w,d,v,p="getDb",E)=>{let g,A,h;const m=((a,t)=>t?async(e,n)=>(t(e,n),await a(e,n)):a)(s,c),[N,f,C,O]=(a=>{const e=(a=>q(ma,l(a)?{[ua]:a}:a??{}))(a),n=e[va];if(e.mode==ya){const a=e[ua]??t;return[1,n,[a,e[wa]??I,e[da]??la],oa(a)]}const{tables:{load:s={},save:i={}}={},values:o={}}=e,r=u(W(q(Na,o)),0,X(Na)),c=r[2],y=oa(c),w=oa(c);return[0,n,[$a(s,{[Ea]:null,[pa]:I},Ea,(a=>$(w,a)),(a=>ra(y,a))),$a(i,{[ga]:null,[pa]:I,[Aa]:0,[ha]:0},ga,((a,t)=>$(w,t)),((a,t)=>ra(y,t))),r],y]})(n);return(N?Da:Ra)(a,m,(a=>{let t;const e=()=>t=setInterval((async()=>{try{const[{d:t,s:e,c:n}]=await m(`${L} ${F} d,${U} s,TOTAL_CHANGES() c FROM ${P}${F} JOIN ${P}${U}`);t==g&&e==A&&n==h||(null!=g&&a(),g=t,A=e,h=n)}catch{}}),1e3*f),n=()=>{g=A=h=null,o(t)},s=i((t=>{O.has(t)&&(n(),a(),e())}));return e(),()=>{n(),r(s)}}),(a=>a()),y,w,d,C,S(O),(async(a,t)=>await a(`${L} t.name tn,c.name cn FROM ${j}list()t,${j}info(t.name)c ${b} t.schema='main'AND t.type IN('table','view')AND t.name IN(${J(t)})ORDER BY t.name,c.name`,t)),v,p,e,E,(a=>!0===a?1:!1===a?0:a),void 0)},_a=(a,t,e,n,s)=>Ma(a,e,(async(a,e=[])=>t.query(a).all(...e)),(()=>()=>0),(a=>a()),n,s,(()=>0),3,t);export{_a as createSqliteBunPersister};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinybase",
3
- "version": "6.1.0-beta.3",
3
+ "version": "6.1.0-beta.4",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinybase",
6
6
  "license": "MIT",
@@ -22,17 +22,17 @@
22
22
  "sideEffects": false,
23
23
  "peerDependencies": {
24
24
  "@automerge/automerge-repo": "^1.2.1",
25
- "@cloudflare/workers-types": "^4.20250507.0",
25
+ "@cloudflare/workers-types": "^4.20250508.0",
26
26
  "@electric-sql/pglite": "^0.2.17",
27
27
  "@libsql/client": "^0.15.4",
28
- "@powersync/common": "^1.29.0",
28
+ "@powersync/common": "^1.30.0",
29
29
  "@sqlite.org/sqlite-wasm": "^3.49.1-build4",
30
30
  "@vlcn.io/crsqlite-wasm": "^0.16.0",
31
31
  "electric-sql": "^0.12.1",
32
32
  "expo": "^53.0.7",
33
33
  "expo-sqlite": "^15.2.9",
34
34
  "partykit": "^0.0.114",
35
- "partysocket": "^1.1.3",
35
+ "partysocket": "^1.1.4",
36
36
  "postgres": "^3.4.5",
37
37
  "react": "^19.0.0",
38
38
  "react-dom": "^19.0.0",
@@ -232,6 +232,12 @@
232
232
  "persisters/persister-sqlite3/with-schemas": [
233
233
  "./@types/persisters/persister-sqlite3/with-schemas/index.d.ts"
234
234
  ],
235
+ "persisters/persister-sqlite-bun": [
236
+ "./@types/persisters/persister-sqlite-bun/index.d.ts"
237
+ ],
238
+ "persisters/persister-sqlite-bun/with-schemas": [
239
+ "./@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts"
240
+ ],
235
241
  "persisters/persister-yjs": [
236
242
  "./@types/persisters/persister-yjs/index.d.ts"
237
243
  ],
@@ -460,6 +466,12 @@
460
466
  "min/persisters/persister-sqlite3/with-schemas": [
461
467
  "./@types/persisters/persister-sqlite3/with-schemas/index.d.ts"
462
468
  ],
469
+ "min/persisters/persister-sqlite-bun": [
470
+ "./@types/persisters/persister-sqlite-bun/index.d.ts"
471
+ ],
472
+ "min/persisters/persister-sqlite-bun/with-schemas": [
473
+ "./@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts"
474
+ ],
463
475
  "min/persisters/persister-yjs": [
464
476
  "./@types/persisters/persister-yjs/index.d.ts"
465
477
  ],
@@ -823,6 +835,18 @@
823
835
  "default": "./persisters/persister-sqlite3/with-schemas/index.js"
824
836
  }
825
837
  },
838
+ "./persisters/persister-sqlite-bun": {
839
+ "default": {
840
+ "types": "./@types/persisters/persister-sqlite-bun/index.d.ts",
841
+ "default": "./persisters/persister-sqlite-bun/index.js"
842
+ }
843
+ },
844
+ "./persisters/persister-sqlite-bun/with-schemas": {
845
+ "default": {
846
+ "types": "./@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts",
847
+ "default": "./persisters/persister-sqlite-bun/with-schemas/index.js"
848
+ }
849
+ },
826
850
  "./persisters/persister-yjs": {
827
851
  "default": {
828
852
  "types": "./@types/persisters/persister-yjs/index.d.ts",
@@ -1279,6 +1303,18 @@
1279
1303
  "default": "./min/persisters/persister-sqlite3/with-schemas/index.js"
1280
1304
  }
1281
1305
  },
1306
+ "./min/persisters/persister-sqlite-bun": {
1307
+ "default": {
1308
+ "types": "./@types/persisters/persister-sqlite-bun/index.d.ts",
1309
+ "default": "./min/persisters/persister-sqlite-bun/index.js"
1310
+ }
1311
+ },
1312
+ "./min/persisters/persister-sqlite-bun/with-schemas": {
1313
+ "default": {
1314
+ "types": "./@types/persisters/persister-sqlite-bun/with-schemas/index.d.ts",
1315
+ "default": "./min/persisters/persister-sqlite-bun/with-schemas/index.js"
1316
+ }
1317
+ },
1282
1318
  "./min/persisters/persister-yjs": {
1283
1319
  "default": {
1284
1320
  "types": "./@types/persisters/persister-yjs/index.d.ts",