Skip to content

Latest commit

 

History

History
134 lines (97 loc) · 4.08 KB

File metadata and controls

134 lines (97 loc) · 4.08 KB

Todo List Demo

A two-panel todo app demonstrating tauri-plugin-libsql with local SQLite and optional Turso embedded replica sync.

What it shows

  • Left panel — local SQLite database (todos.db) with instant reads/writes
  • Right panel — Turso embedded replica (todos-turso.db) synced with a remote Turso database; demonstrates real network latency on writes
  • Drizzle ORM via createDrizzleProxy (sqlite-proxy pattern)
  • Browser-safe migrations with migrate() bundled at build time via import.meta.glob
  • Sonner toast notifications per-panel (bottom-left for local, bottom-right for Turso)
  • Optional AES-256 encryption via environment variable (local DB only)

Running

Prerequisites

Install dependencies

bun install

Start dev server

bun run tauri dev

With encryption enabled (local DB)

LIBSQL_ENCRYPTION_KEY=my-secret-key bun run tauri dev

The key is padded/truncated to 32 bytes automatically.

Connecting to Turso

The right panel shows a connect form on first launch. Enter your Turso credentials:

  1. Remote URLlibsql://mydb-org.turso.io
  2. Auth Token — your Turso auth token
# Get your credentials
turso db show --url <db-name>
turso db tokens create <db-name>

Credentials are saved in localStorage and restored on next launch. Click the × button in the Turso panel header to disconnect.

Reset DB

Each panel has a Reset DB button at the bottom. It drops the todos table and the __drizzle_migrations tracking table, then re-runs all migrations from scratch. Useful when:

  • You manually deleted tables in the Turso console
  • The migration tracking table has stale records
  • You want a clean slate without deleting the DB file

Database location

Both database files are created in the current working directory when you run the command. Running from examples/todo-list/ puts them there.

  • todos.db — local SQLite
  • todos-turso.db — embedded replica (Turso sync)

The two databases must be separate files. Opening a plain SQLite file as an embedded replica (or vice versa) causes a "metadata file missing" error.

Architecture

App.svelte
  │
  ├── <TodoList dbFile="todos.db" position="bottom-left" />
  │     └── Database.load() → migrate() → Drizzle queries
  │
  └── <TodoList dbFile="todos-turso.db" syncUrl="..." position="bottom-right" />
        └── Database.load({ syncUrl, authToken })  ← initial sync from Turso
              migrate()
              Drizzle queries
              db.sync()  ← manual pull of remote changes

Startup sequence (inside TodoList)

// 1. Open/create the database file (initial Turso sync if syncUrl set)
dbInstance = await Database.load(options);

// 2. Run pending migrations
await migrate(dbPath, migrations);

// 3. Now safe to query
await loadTodos();

Migration files

drizzle/
  0000_init.sql    ← generated by drizzle-kit, bundled by Vite at build time

Schema changes

# 1. Edit src/lib/schema.ts
# 2. Generate a new migration
bun run db:generate
# 3. Restart the app — migration runs automatically on next launch

Project structure

examples/todo-list/
├── drizzle/                  # Generated SQL migration files
├── src/
│   ├── App.svelte            # Two-panel layout, Turso connect/disconnect form
│   └── lib/
│       ├── TodoList.svelte   # Self-contained panel: DB lifecycle, CRUD, sync
│       ├── schema.ts         # Drizzle table definitions
│       ├── db.ts             # createDb() factory for Drizzle instance
│       └── components/       # UI primitives (Button, Input, Card, etc.)
├── src-tauri/
│   ├── Cargo.toml            # Plugin with replication feature enabled
│   └── src/lib.rs            # Plugin registration, encryption from env
├── drizzle.config.ts         # drizzle-kit config
└── package.json              # Scripts: db:generate, tauri dev/build