Skip to content

Releases: tinyplex/tinybase

v7.0.0

Choose a tag to compare

@jamesgpearce jamesgpearce released this 04 Dec 04:00

This important (and slightly breaking!) release adds support for null as a valid Cell and Value type, alongside string, number, and boolean.

Null Type Support

You can now set Cells and Values to null:

import {createStore} from 'tinybase';

const store = createStore();
store.setCell('pets', 'fido', 'species', 'dog');
store.setCell('pets', 'fido', 'color', null);

console.log(store.getCell('pets', 'fido', 'color'));
// -> null

console.log(store.hasCell('pets', 'fido', 'color'));
// -> true

To allow null values in your schema, use the new allowNull property:

store.setTablesSchema({
  pets: {
    species: {type: 'string'},
    color: {type: 'string', allowNull: true},
  },
});

store.setCell('pets', 'fido', 'color', null);
// Valid because allowNull is true

store.setCell('pets', 'fido', 'species', null);
// Invalid - species does not allow null

store.delSchema();

Important Distinction: null vs undefined

It's crucial to understand the difference between null and undefined in TinyBase:

  • null is an explicit value. A Cell set to null exists in the Store.
  • undefined means the Cell does not exist in the Store.

This means that the hasCell method will return true for a Cell with a null value:

store.setCell('pets', 'fido', 'color', null);
console.log(store.hasCell('pets', 'fido', 'color'));
// -> true

store.delCell('pets', 'fido', 'color');
console.log(store.hasCell('pets', 'fido', 'color'));
// -> false

store.delTables();

Breaking Change: Database Persistence

Important: This release includes a breaking change for applications using database persisters (the Sqlite3Persister, PostgresPersister, or PglitePersister interfaces, for example).

SQL NULL values are now loaded as TinyBase null values. Previously, SQL NULL would result in Cells being absent from the Store. Now, SQL NULL maps directly to TinyBase null, which means:

  • Tables loaded from SQL databases will be dense rather than sparse
  • Every Row will have every Cell Id present in the table schema
  • Cells that were SQL NULL will have the value null

Example of the roundtrip transformation via a SQLite database:

import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
import {createSqliteWasmPersister} from 'tinybase/persisters/persister-sqlite-wasm';

const sqlite3 = await sqlite3InitModule();
let db = new sqlite3.oo1.DB(':memory:', 'c');

store.setTable('pets', {
  fido: {species: 'dog'},
  felix: {species: 'cat', color: 'black'},
});

const tabularPersister = createSqliteWasmPersister(store, sqlite3, db, {
  mode: 'tabular',
  tables: {save: {pets: 'pets'}, load: {pets: 'pets'}},
});

await tabularPersister.save();
// After saving the the SQL database:
// SQL table: fido (species: 'dog', color: NULL)
//           felix (species: 'cat', color: 'black')

await tabularPersister.load();
// After loading again, the Store now has a dense table with an explicit null:

console.log(store.getRow('pets', 'fido'));
// -> {species: 'dog', color: null}

This is the correct semantic mapping since SQL databases have fixed schemas where every row must account for every column. See the Database Persistence guide for more details.

Migration Guide

If you are using database persisters, you should:

  1. Review your data access patterns: If you were checking hasCell(...) === false to detect missing data, you now need to check getCell(...) === null for null values.

  2. Update your schemas: Add allowNull: true to Cell definitions that should permit null values:

store.setTablesSchema({
  pets: {
    species: {type: 'string'},
    color: {type: 'string', allowNull: true},
    age: {type: 'number', allowNull: true},
  },
});
  1. Consider memory implications: Dense tables consume more memory than sparse tables. If you have large tables with many optional Cells, this could be significant.

v6.7.5

Choose a tag to compare

@jamesgpearce jamesgpearce released this 29 Nov 04:33

This release updates dependencies, including Automerge v2.5.0.

It also adds an agents.md file to make it easier for AI agents to understand the system.

v6.7.3

Choose a tag to compare

@jamesgpearce jamesgpearce released this 13 Nov 05:41

This release updates dependencies.

v6.7.2

Choose a tag to compare

@jamesgpearce jamesgpearce released this 25 Oct 02:11

This release updates dependencies.

v6.7.1

Choose a tag to compare

@jamesgpearce jamesgpearce released this 11 Oct 09:01

This release updates dependencies, and migrates the test suite from Jest to Vitest.

v6.7.0

Choose a tag to compare

@jamesgpearce jamesgpearce released this 04 Oct 01:43

This release includes support for the Origin Private File System (OPFS) in a browser. The createOpfsPersister function is the main entry point, and is available in the existing persister-browser module:

import {createStore} from 'tinybase';
import {createOpfsPersister} from 'tinybase/persisters/persister-browser';

const opfs = await navigator.storage.getDirectory();
const handle = await opfs.getFileHandle('tinybase.json', {create: true});

const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
const persister = createOpfsPersister(store, handle);

await persister.save();
// Store JSON will be saved to the OPFS file.

await persister.load();
// Store JSON will be loaded from the OPFS file.

await persister.destroy();

That's it! If you've used other TinyBase persisters, this API should be easy and familiar to use.

One caveat: observability in OPFS is not yet standardized in browsers. This means that the auto-load functionality of the persister may not work as expected, although a best effort is made using the experimental FileSystemObserverAPI, so please let us know how that works!

v6.6.1

Choose a tag to compare

@jamesgpearce jamesgpearce released this 23 Sep 02:35

This release updates dependencies.

v6.6.0

Choose a tag to compare

@jamesgpearce jamesgpearce released this 23 Sep 02:34

This release improves the Inspector tool, making it easier to debug, inspect, and mutate your TinyBase stores.

image

As well as a modernized UI, new in this release is the ability to create, duplicate, or delete tables, rows, values and cells directly within the Inspector. Press the 'pencil' icon to start editing items, and then hover over the new icons to see how to manipulate the data.

See the Inspecting Data guide for more information about how to use the Inspector in your application during development.

v6.5.2

Choose a tag to compare

@jamesgpearce jamesgpearce released this 13 Aug 20:04

This release updates dependencies.

v6.5.1

Choose a tag to compare

@jamesgpearce jamesgpearce released this 06 Aug 06:57

This release updates dependencies.