Skip to content

Releases: tinyplex/tinybase

v8.0.0-beta.1

21 Feb 10:30

Choose a tag to compare

v8.0.0-beta.1 Pre-release
Pre-release

Introducing Middleware

This release introduces a powerful new system for intercepting and transforming data as it flows into your TinyBase Store. Middleware callbacks can be registered to fire before data is written to the Store, allowing you to modify, validate, or even reject changes before they take effect.

import {createMiddleware, createStore} from 'tinybase';
const store = createStore();

const middleware = createMiddleware(store);
middleware.addWillSetCellCallback((tableId, rowId, cellId, cell) => {
  if (tableId === 'pets' && cellId === 'age' && cell < 0) {
    // Reject negative ages by returning undefined
    return undefined;
  }
  // Otherwise, allow the change to proceed unmodified
  return cell;
});

Read more in our new comprehensive Using Middleware guide, which includes examples of using Middleware for data validation, transformation, and more.

Middleware complements listeners but is distinct in that it runs before changes are applied to the Store, whereas listeners run after. Middleware can modify the data that listeners see, and can prevent changes from being applied at all by returning undefined. In conjunction with schemas, Middleware provides a powerful way to enforce data integrity and implement complex data transformations - and it should work in synchronization environments too.

Many, many thanks to Brandon Mason for designing and implementing this concept. Despite the major version number, we trust there are no breaking changes in this release. But please let us know if you find any!

v7.3.5

21 Feb 09:24

Choose a tag to compare

This release updates dependencies.

v7.3.4

15 Feb 01:42

Choose a tag to compare

This release updates dependencies and includes #285, that fixes a number of related mutation+sync issues.

v7.3.3

11 Feb 22:56

Choose a tag to compare

This release updates dependencies and includes #284

v7.3.2

20 Jan 08:17

Choose a tag to compare

This release updates dependencies and includes #282.

v7.3.1

30 Dec 22:20

Choose a tag to compare

This release updates dependencies.

v7.3.0

15 Dec 17:02

Choose a tag to compare

Introducing State Hooks

This release introduces a new family of convenience hooks that follow React's useState pattern, making it even easier to read and write TinyBase data in your React components.

Each state hook returns a tuple containing both the current value and a setter function, eliminating the need to use separate getter and setter hooks.

State hooks combine the functionality of getter hooks (like the useRow hook) and setter callback hooks (like the useSetRowCallback hook) into a single, convenient API that feels just like React's useState:

import {createStore} from 'tinybase';
import {useCellState} from 'tinybase/ui-react';

const store = createStore().setRow('pets', 'fido', {
  species: 'dog',
  color: 'brown',
});

const PetEditor = () => {
  const [color, setColor] = useCellState('pets', 'fido', 'color', store);

  return (
    <div>
      <div>Color: {color}</div>
      <button onClick={() => setColor('black')}>Change Color</button>
    </div>
  );
};

Available State Hooks

This release includes eight new state hooks covering the most common data access patterns:

These hopefully mean less boilerplate, are particularly useful when building forms, editors, or any interactive UI that needs bidirectional data binding.

Demo Updates

We've updated a few of the demos to showcase these new state hooks:

Check out these demos to see the state hooks in action.

v7.2.0

12 Dec 20:53

Choose a tag to compare

Introducing Parameterized Queries!

This release introduces parameterized queries to TinyQL - finally!

These allow you to define queries using named 'params' that you can then easily update to change the query's results - without redefining the whole query each time.

Let's take a look with a simple example:

import {createStore, createQueries} from 'tinybase';

const store = createStore().setTable('pets', {
  fido: {age: 2, species: 'dog'},
  felix: {age: 1, species: 'cat'},
  cujo: {age: 3, species: 'dog'},
});

const queries = createQueries(store).setQueryDefinition(
  'petsBySpecies',
  'pets',
  ({select, where, param}) => {
    select('age');
    where('species', param('species'));
  },
  {species: 'dog'}, // Initial param value
);

console.log(queries.getResultTable('petsBySpecies'));
// -> {fido: {age: 2}, cujo: {age: 3}}

// Update the 'species' param to 'cat' to change the results:
queries.setParamValue('petsBySpecies', 'species', 'cat');
console.log(queries.getResultTable('petsBySpecies'));
// -> {felix: {age: 1}}

You can of course have multiple params in a query definition, and use them in any part of the query definition that you would like. Listeners also work as expected - if you are listening to a query's results, and you change a param that affects those results, your listener will be called accordingly.

This is TinyBase so you should not be too surprised... but params themselves are reactive! You can get and listen to their values with the getParamValue method and addParamValueListener method, for example.

For React users, we also shipped a bunch of new hooks that cover params in exactly the way you would expect, including the useSetParamValueCallback hook and the useSetParamValuesCallback hook, which let you easily update param values from, say, an event handler in your application.

We know this has been a long-awaited feature, so we hope you enjoy it! See the TinyQL guide for more details, and please let us know how it goes!

Demos

We have updated the Movie Database demo to use parameterized queries, and as a result is more efficient and easier to (we think) understand. See the yearGenreMovies, directedMovies, and appearedMovies queries to see params in action.

We have also updated the Car Analysis demo to use just one single parameterized query for the whole app!

Full API additions

This release includes the following new Queries interface methods:

It also includes the following new React hooks:

Check out the API docs for each. They should seem very familiar.

Please check out this new release and let us know what you think!

v7.1.0

11 Dec 07:30

Choose a tag to compare

This release introduces Schematizers, a new system for converting schemas from popular validation libraries into TinyBase's schema format.

Schematizers provide a bridge between external schema validation libraries (like Zod, TypeBox, and Valibot) and TinyBase's TablesSchema and ValuesSchema formats. Instead of manually writing TinyBase schemas, you can now convert existing schemas at runtime:

import {createStore} from 'tinybase';
import {createZodSchematizer} from 'tinybase/schematizers/schematizer-zod';
import {z} from 'zod';

const schematizer = createZodSchematizer();

const zodSchema = {
  pets: z.object({
    species: z.string(),
    age: z.number(),
    sold: z.boolean().default(false),
  }),
};

const schematizedStore = createStore().setTablesSchema(
  schematizer.toTablesSchema(zodSchema),
);

schematizedStore.setRow('pets', 'fido', {species: 'dog', age: 3});
console.log(schematizedStore.getRow('pets', 'fido'));
// -> {species: 'dog', age: 3, sold: false}

Schematizers perform best-effort conversions, extracting basic type information (string, number, boolean), defaults, and nullable settings from your schemas.

This release includes support for:

For more information, see the Using Schematizers guide.

v7.0.1

05 Dec 18:50

Choose a tag to compare

This makes a small change to the generic typing of the persister StatusListener type so that all specialized Persisters are correctly understood to be subtypes of Persister, fixing #273