TinyBase Documentation

repository·main·Indexed 26 days ago

https://github.com/tinyplex/tinybase

A reactive in-memory data store for local-first JavaScript and TypeScript apps. TinyBase provides key-value and tabular data management with native CRDT support via MergeableStore for synchronization and persistence across various backends including IndexedDB, SQLite, and PostgreSQL. It features a query engine (TinyQL), indexing, metric aggregation, and specialized UI bindings for React, Solid, and Svelte.

Tokens
152.9K
Snippets
375
Records
704
Agent score
86%

What's inside TinyBase

  1. Overview of TinyBase features

    main

    TinyBase is a reactive in-memory data store designed for local-first JavaScript and TypeScript applications. Key features include:

    • Reactivity: Listen to granular changes to specific parts of your data to optimize UI rendering. Supports React bindings, pre-built components, and charts.
    • Database-like capabilities: Supports key-value and tabular data, indexing, metric aggregation, table relationships, and a query engine (TinyQL) for selecting, joining, filtering, and grouping data without SQL.
    • Synchronization & Persistence: Native CRDT support for deterministic data merging across clients/servers. Supports persisting to file, browser storage (OPFS, IndexedDB), and various databases like SQLite, PostgreSQL, PGlite, and more.
    • Local-first optimized: Extremely lightweight (7.2kB - 15.6kB) with no dependencies, designed to work offline and run anywhere JavaScript does.
  2. Overview of TinyBase Solid UI modules

    main

    TinyBase provides specialized modules for building reactive user interfaces with SolidJS. The ecosystem is organized into several layers:

    1. ui-solid: Contains the core primitives for reactivity.
    2. ui-solid view components: Higher-level components built on top of the primitives.
    3. ui-solid-dom: Browser-focused modules for DOM manipulation and integration.
    4. Provider context patterns: Patterns for managing TinyBase stores within the SolidJS component tree.
  3. Overview of TinyBase Core Concepts

    main

    TinyBase is a reactive, in-memory data store designed for local-first applications.

    Data Structures

    • Tables: Tabular data organized as Table → Row → Cell (relational model).
    • Values: Simple key-value pairs for application state.

    Reactivity

    TinyBase uses a fine-grained reactive system. You can listen to changes at multiple granularities:

    • Entire store changes
    • Table/value additions or removals
    • Row changes within a table
    • Individual cell or value changes

    Synchronization

    TinyBase uses CRDTs (Conflict-free Replicated Data Types) via MergeableStore and Hybrid Logical Clocks for deterministic synchronization across clients and servers.

  4. Understand TinyBase module patterns

    main

    Most TinyBase modules follow a consistent structural pattern consisting of two parts:

    1. A creation function: A single function used to instantiate the module (e.g., createStore for the store module).
    2. A major interface: A primary TypeScript interface that the returned object conforms to (e.g., the Store interface).

    Core logic is located in .ts files, while TypeScript definitions are maintained in .d.ts files within @types folders. The package also provides a single entry point via tinybase.ts and tinybase.d.ts which wraps all modules into one convenient package.

  5. Use Schematizers to convert external schemas to TinyBase

    main

    Schematizers allow you to convert schemas from popular validation libraries into TinyBase's TablesSchema and ValuesSchema formats at runtime. This avoids manual schema rewriting by leveraging your existing definitions from libraries like Zod, TypeBox, or Valibot.

    Supported libraries and their creation functions:

    LibraryCreation function
    ZodcreateZodSchematizer
    TypeBoxcreateTypeBoxSchematizer
    ValibotcreateValibotSchematizer
    ArkTypecreateArkTypeSchematizer
    YupcreateYupSchematizer
    Effect SchemacreateEffectSchematizer

    You can also use createCustomSchematizer to implement support for any other schema system.

  6. Deciding when to use TinyBase

    main

    TinyBase is a reactive in-memory data store designed for local-first JavaScript and TypeScript applications.

    Use TinyBase when your app needs:

    • Fast, reactive data in the browser, worker, Node, Bun, or React Native.
    • Structured data (tabular, relationships, indexes, metrics, or queries) without requiring SQL for every interaction.
    • Local-first/Offline experience with data persistence between sessions.
    • Deterministic synchronization between clients or servers.
    • Fine-grained bindings for React, Solid, or Svelte.
    • A small, dependency-free layer to sit in front of existing storage or sync infrastructure.

    Avoid TinyBase if:

    • The authoritative dataset is too large to fit in the JavaScript environment's memory.
    • The primary requirement is arbitrary server-side SQL over large datasets.
    • You need a managed backend (auth, billing, etc.) as a single hosted product.
    • You only need simple component-local variables without structured data or persistence.
  7. Understand TinyBase package sizes and modularity

    main
    TinyBase is designed to be modular, allowing you to add only the functionality you need to keep your bundle size small. You can use the minimal store module alone or include UI components for various frameworks. All modules have zero dependencies.
  8. Understand TinyBase Persistence and Persisters

    main

    TinyBase Stores are in-memory data structures. To preserve data between sessions, reloads, or across different environments, you use a Persister. Persisters allow you to save and load Store data to and from various storage types like browser storage, files, databases, or CRDT frameworks.

    Persister Categories

    Basic Persisters

    Best for smaller datasets and basic browser/server environments. They typically use JSON serialization.

    • SessionPersister: Browser session storage
    • LocalPersister: Browser local storage
    • OpfsPersister: Browser origin private file system (OPFS)
    • FilePersister: Local file
    • IndexedDbPersister: Browser IndexedDB
    • RemotePersister: Remote server
    • ReactNativeMmkvPersister: MMKV in React Native

    Database Persisters

    Ideal for larger datasets, often on a server, or in a browser with a SQLite instance. They can save data in JSON or tabular formats.

    • Sqlite3Persister: SQLite in Node (via sqlite3)
    • SqliteBunPersister: SQLite in Bun (via bun:sqlite)
    • SqliteWasmPersister: SQLite in a browser (via sqlite-wasm)
    • ExpoSqlitePersister: SQLite in React Native (via expo-sqlite)
    • ReactNativeSqlitePersister: SQLite in React Native (via react-native-sqlite-storage)
    • CrSqliteWasmPersister: SQLite CRDTs (via cr-sqlite-wasm)
    • ElectricSqlPersister: Electric SQL
    • LibSqlPersister: LibSQL for Turso
    • PowerSyncPersister: PowerSync
    • PostgresPersister: PostgreSQL
    • PglitePersister: PostgreSQL via PGlite

    Durable Object Persisters

    Designed for Cloudflare Durable Objects.

    • DurableObjectStoragePersister: Cloudflare Durable Object key-value storage
    • DurableObjectSqlStoragePersister: Cloudflare Durable Object SQLite storage

    Third-Party CRDT & Socket Persisters

    For complex synchronization with CRDT frameworks or PartyKit.

    • YjsPersister: Yjs CRDTs
    • AutomergePersister: Automerge CRDTs
    • PartyKitPersister: PartyKit via persister-partykit-server
  9. Understand MergeableStore for synchronization

    main
    To enable synchronization in TinyBase, you must use a MergeableStore instead of a regular Store. A MergeableStore is a subtype of Store, meaning all existing Store methods remain unchanged. However, it automatically records additional metadata during data changes, which allows the system to reconcile potential conflicts during synchronization processes.
  10. Understand TinyBase testing architecture

    main

    TinyBase uses Jest as its primary testing coordinator. The testing suite is organized into three main categories located in the test directory:

    1. Unit Tests (test/unit): These test individual modules. They are run against debug builds and require the compileForTest task to be executed first. Notably, these tests also validate all code snippets found in the official API documentation and guides to ensure example code remains functional.
    2. Performance Tests (test/perf): These benchmark large numbers of operations to verify time complexity. Instead of strict pass/fail thresholds (which vary by hardware), these tests output an ASCII chart. Developers should look for a relatively flat chart to ensure no high-complexity algorithm bugs have been introduced.
    3. End-to-End Tests (test/e2e): These use Puppeteer to run transactions through the TinyBase website demos, helping to catch regressions in complex application scenarios.