Tuple Database

2.2.4 · active · verified Wed Apr 22

Tuple Database is a local-first, embedded database designed for modern JavaScript and TypeScript applications, particularly those embracing the local-first software paradigm. It functions as a reactive, indexable graph database, often described as an 'embedded FoundationDb.' The library, currently at version 2.2.4, provides transactional read/write operations with a schemaless approach, where schemas are enforced by the application's type definitions rather than the database itself. It supports both synchronous and asynchronous storage backends, including SQLite or LevelDb, making it versatile for various environments. Key differentiators include its focus on freeing developers from the complexities of multi-tenant systems by empowering users with local data ownership, offering all reactive queries, and enabling direct manipulation of indexes for graph and relational queries. While the release cadence isn't explicitly stated, active development is indicated by its `2.x.x` versioning and comprehensive feature set, positioning it as a robust solution for frontend state management and embedded data persistence.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates defining a schema, initializing an in-memory database, performing transactional writes, and executing reactive scans. It also briefly mentions the React hook for state management.

import { TupleDatabaseClient, TupleDatabase, InMemoryTupleStorage, transactionalReadWrite } from "tuple-database";

// 1. Define your schema using TypeScript types.
type User = {
  id: string;
  first_name: string;
  last_name: string;
  age: number;
};

type UserIndex = {
  key: ["user", { id: string }],
  value: User;
};

type AgeIndex = {
  key: ["userByAge", { age: number }, { id: string }],
  value: null;
};

type Schema = UserIndex | AgeIndex;

// 2. Construct your database with an in-memory storage.
const db = new TupleDatabaseClient<Schema>(new TupleDatabase(new InMemoryTupleStorage()));

// 3. Define a transactional write query.
const insertUser = transactionalReadWrite<Schema>()((tx, user: User) => {
  const { id, first_name, last_name, age } = user;
  tx.set(["user", { id }], user);
  tx.set(["userByAge", { age }, { id }], null);
});

// 4. Insert some data.
insertUser(db, { id: "1", first_name: "Chet", last_name: "Corcos", age: 31 });
insertUser(db, { id: "2", first_name: "Tanishq", last_name: "Kancharla", age: 22 });
console.log("Users inserted.");

// 5. Define a read query to get users by age.
function getUsersByAge(dbClient: TupleDatabaseClient<Schema>, minAge: number) {
  return dbClient.scan({ prefix: ["userByAge", { age: minAge }], gte: ["userByAge", { age: minAge }] });
}

// 6. Execute a read query and log results.
const usersOver30 = getUsersByAge(db, 30);
console.log("Users with age >= 30:", usersOver30.map(entry => entry.key[2].id));

// For React integration:
// import { useTupleDatabase } from 'tuple-database/useTupleDatabase';
// function App({db}: {db: TupleDatabaseClient<Schema>}) {
//   const oldestUser = useTupleDatabase(db, () => {
//     const [oldestEntry] = db.scan({prefix: ["userByAge"], reverse: true, limit: 1});
//     return oldestEntry ? db.get(["user", {id: oldestEntry.key[2].id}]) : null;
//   }, []);
//   return <div>The oldest user is age: {oldestUser?.age}</div>;
// }

view raw JSON →