Skip to content

Commit 0431b93

Browse files
committed
[bun] BunSqlite persister boilerplate
1 parent b191af3 commit 0431b93

6 files changed

Lines changed: 248 additions & 0 deletions

File tree

gulpfile.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const TEST_MODULES = [
3434
'persisters/persister-remote',
3535
'persisters/persister-sqlite-wasm',
3636
'persisters/persister-sqlite3',
37+
'persisters/persister-sqlite-bun',
3738
'persisters/persister-yjs',
3839
'synchronizers',
3940
'synchronizers/synchronizer-local',

site/build.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ const addApi = (docs: Docs): Docs =>
217217
.addApiFile('dist/@types/persisters/persister-remote/index.d.ts')
218218
.addApiFile('dist/@types/persisters/persister-sqlite-wasm/index.d.ts')
219219
.addApiFile('dist/@types/persisters/persister-sqlite3/index.d.ts')
220+
.addApiFile('dist/@types/persisters/persister-sqlite-bun/index.d.ts')
220221
.addApiFile('dist/@types/persisters/persister-yjs/index.d.ts')
221222
.addApiFile('dist/@types/synchronizers/index.d.ts')
222223
.addApiFile('dist/@types/synchronizers/synchronizer-local/index.d.ts')
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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+
/// persister-sqlite-bun
11+
/**
12+
* The SqliteBunPersister interface represents a Persister that lets you save
13+
* and load Store data to and from a local Bun SQLite database.
14+
*
15+
* You should use the createSqliteBunPersister function to create a
16+
* SqliteBunPersister object.
17+
*
18+
* It is a minor extension to the Persister interface and simply provides an
19+
* extra getDb method for accessing a reference to the database instance the
20+
* Store is being persisted to.
21+
* @category Persister
22+
* @since v6.1.0
23+
*/
24+
/// SqliteBunPersister
25+
{
26+
/**
27+
* The getDb method returns a reference to the database instance the Store is
28+
* being persisted to.
29+
* @returns A reference to the database instance.
30+
* @example
31+
* This example creates a Persister object against a newly-created Store and
32+
* then gets the database instance back out again.
33+
*
34+
* ```js bun
35+
* import {Database} from 'bun:sqlite';
36+
* import {createStore} from 'tinybase';
37+
* import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
38+
*
39+
* const db = new Database(':memory:');
40+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
41+
* const persister = createSqliteBunPersister(store, db, 'my_tinybase');
42+
*
43+
* console.log(persister.getDb() == db);
44+
* // -> true
45+
*
46+
* persister.destroy();
47+
* ```
48+
* @category Getter
49+
* @since v6.1.0
50+
*/
51+
/// SqliteBunPersister.getDb
52+
}
53+
/**
54+
* The createSqliteBunPersister function creates a SqliteBunPersister object
55+
* that can persist the Store to a local Bun SQLite database.
56+
*
57+
* A SqliteBunPersister supports regular Store objects, and can also be used to
58+
* persist the metadata of a MergeableStore when using the JSON serialization
59+
* mode, as described below.
60+
*
61+
* As well as providing a reference to the Store to persist, you must provide a
62+
* `db` parameter which identifies the database instance.
63+
*
64+
* A database Persister uses one of two modes: either a JSON serialization of
65+
* the whole Store stored in a single row of a table (the default), or a tabular
66+
* mapping of Table Ids to database table names and vice-versa).
67+
*
68+
* The third argument is a DatabasePersisterConfig object that configures which
69+
* of those modes to use, and settings for each. If the third argument is simply
70+
* a string, it is used as the `storeTableName` property of the JSON
71+
* serialization.
72+
*
73+
* See the documentation for the DpcJson and DpcTabular types for more
74+
* information on how both of those modes can be configured.
75+
* @param store The Store or MergeableStore to persist.
76+
* @param db The database instance that was returned from `new Database(...)`.
77+
* @param configOrStoreTableName A DatabasePersisterConfig to configure the
78+
* persistence mode (or a string to set the `storeTableName` property of the
79+
* JSON serialization).
80+
* @param onSqlCommand An optional handler called every time the Persister
81+
* executes a SQL command or query. This is suitable for logging persistence
82+
* behavior in a development environment.
83+
* @param onIgnoredError An optional handler for the errors that the Persister
84+
* would otherwise ignore when trying to save or load data. This is suitable for
85+
* debugging persistence issues in a development environment.
86+
* @returns A reference to the new SqliteBunPersister object.
87+
* @example
88+
* This example creates a SqliteBunPersister object and persists the Store to a
89+
* local SQLite database as a JSON serialization into the `my_tinybase` table.
90+
* It makes a change to the database directly and then reloads it back into the
91+
* Store.
92+
*
93+
* ```js bun
94+
* import {Database} from 'bun:sqlite';
95+
* import {createStore} from 'tinybase';
96+
* import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
97+
*
98+
* const db = new Database(':memory:');
99+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
100+
* const persister = createSqliteBunPersister(store, db, 'my_tinybase');
101+
*
102+
* await persister.save();
103+
* // Store will be saved to the database.
104+
*
105+
* console.log(
106+
* await new Promise((resolve) =>
107+
* db.all('SELECT * FROM my_tinybase;', (_, rows) => resolve(rows)),
108+
* ),
109+
* );
110+
* // -> [{_id: '_', store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
111+
*
112+
* await new Promise((resolve) =>
113+
* db.all(
114+
* 'UPDATE my_tinybase SET store = ' +
115+
* `'[{"pets":{"felix":{"species":"cat"}}},{}]' WHERE _id = '_';`,
116+
* resolve,
117+
* ),
118+
* );
119+
* await persister.load();
120+
* console.log(store.getTables());
121+
* // -> {pets: {felix: {species: 'cat'}}}
122+
*
123+
* persister.destroy();
124+
* ```
125+
* @example
126+
* This example creates a SqliteBunPersister object and persists the Store to a
127+
* local SQLite database with tabular mapping.
128+
*
129+
* ```js bun
130+
* import {Database} from 'bun:sqlite';
131+
* import {createStore} from 'tinybase';
132+
* import {createSqliteBunPersister} from 'tinybase/persisters/persister-sqlite-bun';
133+
*
134+
* const db = new Database(':memory:');
135+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
136+
* const persister = createSqliteBunPersister(store, db, {
137+
* mode: 'tabular',
138+
* tables: {load: {pets: 'pets'}, save: {pets: 'pets'}},
139+
* });
140+
*
141+
* await persister.save();
142+
* console.log(
143+
* await new Promise((resolve) =>
144+
* db.all('SELECT * FROM pets;', (_, rows) => resolve(rows)),
145+
* ),
146+
* );
147+
* // -> [{_id: 'fido', species: 'dog'}]
148+
*
149+
* await new Promise((resolve) =>
150+
* db.all(
151+
* `INSERT INTO pets (_id, species) VALUES ('felix', 'cat')`,
152+
* resolve,
153+
* ),
154+
* );
155+
* await persister.load();
156+
* console.log(store.getTables());
157+
* // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
158+
*
159+
* persister.destroy();
160+
* ```
161+
* @category Creation
162+
* @since v6.1.0
163+
*/
164+
/// createSqliteBunPersister
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// persister-sqlite-bun
2+
import type {Database} from 'bun:sqlite';
3+
import type {MergeableStore} from '../../mergeable-store/index.js';
4+
import type {Store} from '../../store/index.js';
5+
import type {DatabasePersisterConfig, Persister, Persists} from '../index.js';
6+
7+
/// SqliteBunPersister
8+
export interface SqliteBunPersister
9+
extends Persister<Persists.StoreOrMergeableStore> {
10+
/// SqliteBunPersister.getDb
11+
getDb(): Database;
12+
}
13+
14+
/// createSqliteBunPersister
15+
export function createSqliteBunPersister(
16+
store: Store | MergeableStore,
17+
db: Database,
18+
configOrStoreTableName?: DatabasePersisterConfig | string,
19+
onSqlCommand?: (sql: string, params?: any[]) => void,
20+
onIgnoredError?: (error: any) => void,
21+
): SqliteBunPersister;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// persister-sqlite-bun
2+
import type {Database} from 'bun:sqlite';
3+
import type {MergeableStore} from '../../../mergeable-store/with-schemas/index.js';
4+
import type {
5+
OptionalSchemas,
6+
Store,
7+
} from '../../../store/with-schemas/index.js';
8+
import type {
9+
DatabasePersisterConfig,
10+
Persister,
11+
Persists,
12+
} from '../../with-schemas/index.js';
13+
14+
/// SqliteBunPersister
15+
export interface SqliteBunPersister<Schemas extends OptionalSchemas>
16+
extends Persister<Schemas, Persists.StoreOrMergeableStore> {
17+
/// SqliteBunPersister.getDb
18+
getDb(): Database;
19+
}
20+
21+
/// createSqliteBunPersister
22+
export function createSqliteBunPersister<Schemas extends OptionalSchemas>(
23+
store: Store<Schemas> | MergeableStore<Schemas>,
24+
db: Database,
25+
configOrStoreTableName?: DatabasePersisterConfig<Schemas> | string,
26+
onSqlCommand?: (sql: string, params?: any[]) => void,
27+
onIgnoredError?: (error: any) => void,
28+
): SqliteBunPersister<Schemas>;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {Database} from 'bun:sqlite';
2+
import type {MergeableStore} from '../../@types/mergeable-store/index.js';
3+
import type {DatabasePersisterConfig} from '../../@types/persisters/index.js';
4+
import type {
5+
SqliteBunPersister,
6+
createSqliteBunPersister as createSqliteBunPersisterDecl,
7+
} from '../../@types/persisters/persister-sqlite-bun/index.d.ts';
8+
import type {Store} from '../../@types/store/index.js';
9+
import {IdObj} from '../../common/obj.ts';
10+
import {createCustomSqlitePersister} from '../common/database/sqlite.ts';
11+
12+
type UnsubscribeFunction = () => 0;
13+
14+
export const createSqliteBunPersister = ((
15+
store: Store | MergeableStore,
16+
db: Database,
17+
configOrStoreTableName?: DatabasePersisterConfig | string,
18+
onSqlCommand?: (sql: string, params?: any[]) => void,
19+
onIgnoredError?: (error: any) => void,
20+
): SqliteBunPersister =>
21+
createCustomSqlitePersister(
22+
store,
23+
configOrStoreTableName,
24+
async (sql: string, params: any[] = []): Promise<IdObj<any>[]> =>
25+
db.query<IdObj<any>, any[]>(sql).all(...params),
26+
(): UnsubscribeFunction => () => 0,
27+
(unsubscribeFunction: UnsubscribeFunction): any => unsubscribeFunction(),
28+
onSqlCommand,
29+
onIgnoredError,
30+
() => 0,
31+
3, // StoreOrMergeableStore,
32+
db,
33+
) as SqliteBunPersister) as typeof createSqliteBunPersisterDecl;

0 commit comments

Comments
 (0)