Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build/common.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const TEST_MODULES = [
'persisters/persister-sqlite-wasm',
'persisters/persister-cr-sqlite-wasm',
'persisters/persister-expo-sqlite',
'persisters/persister-expo-sqlite-next',
'persisters/persister-remote',
'persisters/persister-yjs',
'persisters/persister-automerge',
Expand Down Expand Up @@ -51,6 +52,7 @@ const ALL_MODULES = [
'persisters/persister-sqlite-wasm',
'persisters/persister-cr-sqlite-wasm',
'persisters/persister-expo-sqlite',
'persisters/persister-expo-sqlite-next',
'persisters/persister-remote',
'persisters/persister-yjs',
'persisters/persister-automerge',
Expand Down
15,064 changes: 10,135 additions & 4,929 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
"eslint-plugin-jsdoc": "^46.9.0",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"expo-sqlite": "^11.6.0",
"expo-sqlite": "^12.1.0",
"fake-indexeddb": "^5.0.1",
"gulp": "^4.0.2",
"gulp-gzip": "^1.4.2",
Expand Down Expand Up @@ -331,4 +331,4 @@
"optional": true
}
}
}
}
1 change: 1 addition & 0 deletions site/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ const addApi = (docs: Docs): Docs =>
.addApiFile('lib/types/persisters/persister-sqlite-wasm.d.ts')
.addApiFile('lib/types/persisters/persister-cr-sqlite-wasm.d.ts')
.addApiFile('lib/types/persisters/persister-expo-sqlite.d.ts')
.addApiFile('lib/types/persisters/persister-expo-sqlite-next.d.ts')
.addApiFile('lib/types/persisters/persister-partykit-client.d.ts')
.addApiFile('lib/types/persisters/persister-partykit-server.d.ts')
.addApiFile('lib/types/tools.d.ts')
Expand Down
27 changes: 14 additions & 13 deletions site/guides/03_schemas_and_persistence/4_persisting_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@ which returns a new Persister object that can load and save a Store. Between
them, these allow you to store your TinyBase data locally, remotely, to SQLite
databases, and across synchronization boundaries with CRDT frameworks.

| Module | Function | Storage |
| ------------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------ |
| persister-browser | createSessionPersister | Browser session storage |
| persister-browser | createLocalPersister | Browser local storage |
| persister-indexed-db | createIndexedDbPersister | Browser IndexedDB |
| persister-remote | createRemotePersister | Remote server |
| persister-file | createFilePersister | Local file (where possible) |
| persister-sqlite3 | createSqlite3Persister | SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3) |
| persister-sqlite-wasm | createSqliteWasmPersister | SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm) |
| persister-cr-sqlite-wasm | createCrSqliteWasmPersister | SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite) |
| persister-expo-sqlite | createExpoSqlitePersister | SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |
| persister-yjs | createYjsPersister | Yjs CRDTs, via [yjs](https://github.com/yjs/yjs) |
| persister-automerge | createSqliteWasmPersister | Automerge CRDTs, via [automerge-repo](https://github.com/automerge/automerge-repo) |
| Module | Function | Storage |
| -------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
| persister-browser | createSessionPersister | Browser session storage |
| persister-browser | createLocalPersister | Browser local storage |
| persister-indexed-db | createIndexedDbPersister | Browser IndexedDB |
| persister-remote | createRemotePersister | Remote server |
| persister-file | createFilePersister | Local file (where possible) |
| persister-sqlite3 | createSqlite3Persister | SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3) |
| persister-sqlite-wasm | createSqliteWasmPersister | SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm) |
| persister-cr-sqlite-wasm | createCrSqliteWasmPersister | SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite) |
| persister-expo-sqlite | createExpoSqlitePersister | SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |
| persister-expo-sqlite-next | createExpoSqliteNextPersister | SQLite in React Native, via [expo-sqlite/next](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |
| persister-yjs | createYjsPersister | Yjs CRDTs, via [yjs](https://github.com/yjs/yjs) |
| persister-automerge | createSqliteWasmPersister | Automerge CRDTs, via [automerge-repo](https://github.com/automerge/automerge-repo) |

See the Database Persistence guide for details on how to work with SQLite
databases, and the Synchronizing Data guide for more complex synchronization
Expand Down
17 changes: 9 additions & 8 deletions site/guides/03_schemas_and_persistence/6_database_persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
Since v4.0, there are various options for persisting Store data to and from
SQLite databases, via a range of third-party modules.

There are currently four SQLite-based persistence options:

| Module | Function | Storage |
| ------------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------ |
| persister-sqlite3 | createSqlite3Persister | SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3) |
| persister-sqlite-wasm | createSqliteWasmPersister | SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm) |
| persister-cr-sqlite-wasm | createCrSqliteWasmPersister | SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite) |
| persister-expo-sqlite | createExpoSqlitePersister | SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |
There are currently five SQLite-based persistence options:

| Module | Function | Storage |
| -------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------ |
| persister-sqlite3 | createSqlite3Persister | SQLite in Node, via [sqlite3](https://github.com/TryGhost/node-sqlite3) |
| persister-sqlite-wasm | createSqliteWasmPersister | SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm) |
| persister-cr-sqlite-wasm | createCrSqliteWasmPersister | SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite) |
| persister-expo-sqlite | createExpoSqlitePersister | SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |
| persister-expo-sqlite-next | createExpoNextSqlitePersister | SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite) |

(Take a look at the
[vite-tinybase-ts-react-crsqlite](https://github.com/tinyplex/vite-tinybase-ts-react-crsqlite)
Expand Down
31 changes: 31 additions & 0 deletions src/persisters/persister-expo-sqlite-next.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Database, addDatabaseChangeListener} from 'expo-sqlite/next';
import {
ExpoSqliteNextPersister,
createExpoSqliteNextPersister as createExpoSqliteNextPersisterDecl,
} from '../types/persisters/persister-expo-sqlite-next';
import {UpdateListener, createSqlitePersister} from './sqlite/create';
import {DatabasePersisterConfig} from '../types/persisters';
import {IdObj} from '../common/obj';
import {Store} from '../types/store';

type Subscription = {remove: () => void};

export const createExpoSqliteNextPersister = ((
store: Store,
db: Database,
configOrStoreTableName?: DatabasePersisterConfig | string,
onSqlCommand?: (sql: string, args?: any[]) => void,
onIgnoredError?: (error: any) => void,
): ExpoSqliteNextPersister =>
createSqlitePersister(
store,
configOrStoreTableName,
async (sql: string, args: any[] = []): Promise<IdObj<any>[]> =>
await db.allAsync(sql, args),
(listener: UpdateListener): Subscription =>
addDatabaseChangeListener(({tableName}) => listener(tableName)),
(subscription: Subscription) => subscription.remove(),
onSqlCommand,
onIgnoredError,
db,
) as ExpoSqliteNextPersister) as typeof createExpoSqliteNextPersisterDecl;
1 change: 1 addition & 0 deletions src/types/docs/persisters.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* |persister-sqlite-wasm|createSqliteWasmPersister|SQLite in a browser, via [sqlite-wasm](https://github.com/tomayac/sqlite-wasm)|
* |persister-cr-sqlite-wasm|createCrSqliteWasmPersister|SQLite CRDTs, via [cr-sqlite-wasm](https://github.com/vlcn-io/cr-sqlite)|
* |persister-expo-sqlite|createExpoSqlitePersister|SQLite in React Native, via [expo-sqlite](https://github.com/expo/expo/tree/main/packages/expo-sqlite)|
* |persister-expo-sqlite-next|createExpoSqliteNextPersister|SQLite in React Native, via [expo-sqlite/next](https://github.com/expo/expo/tree/main/packages/expo-sqlite/next)|
* |persister-yjs|createYjsPersister|Yjs CRDTs, via [yjs](https://github.com/yjs/yjs)|
* |persister-automerge|createSqliteWasmPersister|Automerge CRDTs, via [automerge-repo](https://github.com/automerge/automerge-repo)|
*
Expand Down
149 changes: 149 additions & 0 deletions src/types/docs/persisters/persister-expo-sqlite-next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* The persister-expo-sqlite-next module of the TinyBase project lets you save
* and load Store data to and from a local Expo-SQLite database (in an
* appropriate React Native environment).
*
* Note that this Persister is currently experimental as Expo themselves iterate
* on the underlying database library API.
* @see Persisting Data guide
* @packageDocumentation
* @module persister-expo-sqlite-next
* @since v4.4.1
*/
/// persister-expo-sqlite-next
/**
* The ExpoSqliteNextPersister interface is a minor extension to the Persister
* interface.
*
* It simply provides an extra getDb method for accessing a reference to the
* database instance the Store is being persisted to.
* @since v4.4.1
*/
/// ExpoSqliteNextPersister
{
/**
* The getDb method returns a reference to the database instance the Store is
* being persisted to.
* @returns A reference to the database instance.
* @example
* This example creates a Persister object against a newly-created Store and
* then gets the database instance back out again.
*
* ```js yolo
* const db = SQLite.openDatabaseSync('my.db');
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const persister = createExpoSqliteNextPersister(store, db, 'my_tinybase');
*
* console.log(persister.getDb() == db);
* // -> true
*
* persister.destroy();
* ```
* @category Getter
* @since v4.4.1
*/
/// ExpoSqliteNextPersister.getDb
}
/**
* The createExpoSqliteNextPersister function creates a Persister object that
* can persist the Store to a local Expo-SQLite database (in an appropriate
* React Native environment).
*
* Note that this Persister is currently experimental as Expo themselves iterate
* on the underlying database library API.
*
* As well as providing a reference to the Store to persist, you must provide a
* `db` parameter which identifies the database instance.
*
* A database Persister uses one of two modes: either a JSON serialization of
* the whole Store stored in a single row of a table (the default), or a tabular
* mapping of Table Ids to database table names and vice-versa).
*
* The third argument is a DatabasePersisterConfig object that configures which
* of those modes to use, and settings for each. If the third argument is simply
* a string, it is used as the `storeTableName` property of the JSON
* serialization.
*
* See the documentation for the DpcJson and DpcTabular types for more
* information on how both of those modes can be configured.
* @param store The Store to persist.
* @param db The database instance that was returned from
* `SQLite.openDatabase(...)`.
* @param configOrStoreTableName A DatabasePersisterConfig to configure the
* persistence mode (or a string to set the `storeTableName` property of the
* JSON serialization).
* @param onSqlCommand An optional handler called every time the Persister
* executes a SQL command or query. This is suitable for logging persistence
* behavior in a development environment, since v4.0.4.
* @param onIgnoredError An optional handler for the errors that the Persister
* would otherwise ignore when trying to save or load data. This is suitable for
* debugging persistence issues in a development environment, since v4.0.4.
* @returns A reference to the new ExpoSqliteNextPersister object.
* @example
* This example creates a ExpoSqliteNextPersister object and persists the Store
* to a local SQLite database as a JSON serialization into the `my_tinybase`
* table. It makes a change to the database directly and then reloads it back
* into the Store.
*
* ```js yolo
* const db = SQLite.openDatabaseSync('my.db');
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const persister = createExpoSqliteNextPersister(store, db, 'my_tinybase');
*
* await persister.save();
* // Store will be saved to the database.
*
* console.log(
* await new Promise((resolve) =>
* db.allAsync('SELECT * FROM my_tinybase;').then(resolve),
* ),
* );
* // -> [{_id: '_', store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
*
* await new Promise((resolve) =>
* db.allAsync(
* 'UPDATE my_tinybase SET store = ' +
* `'[{"pets":{"felix":{"species":"cat"}}},{}]' WHERE _id = '_';`,
* ),
* );
* await persister.load();
* console.log(store.getTables());
* // -> {pets: {felix: {species: 'cat'}}}
*
* persister.destroy();
* ```
* @example
* This example creates a ExpoSqliteNextPersister object and persists the Store
* to a local SQLite database with tabular mapping.
*
* ```js yolo
* const db = SQLite.openDatabaseSync('my.db');
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
* const persister = createExpoSqliteNextPersister(store, db, {
* mode: 'tabular',
* tables: {load: {pets: 'pets'}, save: {pets: 'pets'}},
* });
*
* await persister.save();
* console.log(
* await new Promise((resolve) =>
* db.allAsync('SELECT * FROM pets;').then(resolve),
* ),
* );
* // -> [{_id: 'fido', species: 'dog'}]
*
* await new Promise((resolve) =>
* db.allAsync(
* `INSERT INTO pets (_id, species) VALUES ('felix', 'cat')`
* ).then(resolve),
* );
* await persister.load();
* console.log(store.getTables());
* // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
*
* persister.destroy();
* ```
* @category Creation
* @since v4.0.3
*/
/// createExpoSqliteNextPersister
20 changes: 20 additions & 0 deletions src/types/persisters/persister-expo-sqlite-next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// persister-expo-sqlite-next

import {DatabasePersisterConfig, Persister} from '../persisters';
import {Database} from 'expo-sqlite/next';
import {Store} from '../store';

/// ExpoSqliteNextPersister
export interface ExpoSqliteNextPersister extends Persister {
/// ExpoSqliteNextPersister.getDb
getDb: () => Database;
}

/// createExpoSqliteNextPersister
export function createExpoSqliteNextPersister(
store: Store,
db: Database,
configOrStoreTableName?: DatabasePersisterConfig | string,
onSqlCommand?: (sql: string, args?: any[]) => void,
onIgnoredError?: (error: any) => void,
): ExpoSqliteNextPersister;
21 changes: 21 additions & 0 deletions src/types/with-schemas/persisters/persister-expo-sqlite-next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// persister-expo-sqlite-next

import {DatabasePersisterConfig, Persister} from '../persisters';
import {OptionalSchemas, Store} from '../store';
import {Database} from 'expo-sqlite/next';

/// ExpoSqliteNextPersister
export interface ExpoSqliteNextPersister<Schemas extends OptionalSchemas>
extends Persister<Schemas> {
/// ExpoSqliteNextPersister.getDb
getDb: () => Database;
}

/// createExpoSqliteNextPersister
export function createExpoSqliteNextPersister<Schemas extends OptionalSchemas>(
store: Store<Schemas>,
db: Database,
configOrStoreTableName?: DatabasePersisterConfig<Schemas> | string,
onSqlCommand?: (sql: string, args?: any[]) => void,
onIgnoredError?: (error: any) => void,
): ExpoSqliteNextPersister<Schemas>;