Database Configuration

Configure SQLite database and migrations

Type Definition

interface DatabaseConfig {
  /**
   * Database file name (default: 'app.db')
   */
  name?: string;

  /**
   * App migrations (executed after core migrations)
   */
  migrations?: Migration[];
}

interface Migration {
  /**
   * Version number (must be incrementing)
   */
  version: number;

  /**
   * Migration name
   */
  name: string;

  /**
   * Upgrade SQL
   */
  up: string;

  /**
   * Downgrade SQL (optional)
   */
  down?: string;
}

Default Values

OptionDefault
name'app.db'
migrations[]

Basic Configuration

database: {
  name: 'myapp.db',
  migrations: [],
},

Built-in Tables

The core automatically creates the following tables:

settings table

Stores app settings (key-value pairs):

CREATE TABLE settings (
  key TEXT PRIMARY KEY,
  value TEXT,
  updated_at INTEGER
);

app_state table

Stores UI state:

CREATE TABLE app_state (
  key TEXT PRIMARY KEY,
  value TEXT,
  updated_at INTEGER
);

_migrations table

Records applied migrations:

CREATE TABLE _migrations (
  version INTEGER PRIMARY KEY,
  name TEXT,
  applied_at INTEGER
);

Adding Custom Migrations

Create custom tables or modify data structures:

database: {
  migrations: [
    {
      version: 1,
      name: 'create_users_table',
      up: `
        CREATE TABLE users (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          name TEXT NOT NULL,
          email TEXT UNIQUE,
          created_at INTEGER DEFAULT (strftime('%s', 'now'))
        );
      `,
      down: 'DROP TABLE users;',
    },
    {
      version: 2,
      name: 'add_avatar_to_users',
      up: 'ALTER TABLE users ADD COLUMN avatar TEXT;',
      down: 'ALTER TABLE users DROP COLUMN avatar;',
    },
  ],
},

Migration Rules

Migration version numbers must be incrementing - no gaps or duplicates allowed.

  • Version numbers start from 1 and increment
  • Unapplied migrations run automatically on app startup
  • Once executed, migrations should not be modified (add new ones instead)
  • down is optional, used for rollback

Using the Database

Querying Data

import { query, execute, transaction } from '@linch-tech/desktop-core';

// Query
const users = await query<User[]>('SELECT * FROM users WHERE id = ?', [1]);

// Execute (insert, update, delete)
await execute('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com']);

// Transaction
await transaction(async () => {
  await execute('INSERT INTO users (name) VALUES (?)', ['Alice']);
  await execute('INSERT INTO users (name) VALUES (?)', ['Bob']);
});

Using Built-in Settings

import { getSetting, setSetting, deleteSetting } from '@linch-tech/desktop-core';

// Read setting
const theme = await getSetting<string>('theme');

// Save setting
await setSetting('theme', 'dark');

// Delete setting
await deleteSetting('theme');

Using Hooks

import { useSetting, useAppState } from '@linch-tech/desktop-core';

function SettingsPage() {
  // Read/write settings
  const [theme, setTheme] = useSetting<string>('theme', 'light');

  // Read/write UI state
  const [sidebarOpen, setSidebarOpen] = useAppState('sidebarOpen', true);

  return (
    <div>
      <select value={theme} onChange={(e) => setTheme(e.target.value)}>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
    </div>
  );
}

Database File Location

Database files are stored in the app data directory:

PlatformPath
Windows%APPDATA%\{identifier}\{name}
macOS~/Library/Application Support/{identifier}/{name}
Linux~/.local/share/{identifier}/{name}

Where {identifier} is from tauri.conf.json and {name} is the database name.

Complete Example

export const config = {
  database: {
    name: 'myapp.db',
    migrations: [
      {
        version: 1,
        name: 'create_projects_table',
        up: `
          CREATE TABLE projects (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            description TEXT,
            status TEXT DEFAULT 'active',
            created_at INTEGER DEFAULT (strftime('%s', 'now')),
            updated_at INTEGER DEFAULT (strftime('%s', 'now'))
          );
          CREATE INDEX idx_projects_status ON projects(status);
        `,
        down: 'DROP TABLE projects;',
      },
      {
        version: 2,
        name: 'create_tasks_table',
        up: `
          CREATE TABLE tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            project_id INTEGER NOT NULL,
            title TEXT NOT NULL,
            completed INTEGER DEFAULT 0,
            created_at INTEGER DEFAULT (strftime('%s', 'now')),
            FOREIGN KEY (project_id) REFERENCES projects(id)
          );
          CREATE INDEX idx_tasks_project ON tasks(project_id);
        `,
        down: 'DROP TABLE tasks;',
      },
    ],
  },
};

Notes

Database functionality requires features.database to be true (enabled by default).

SQLite doesn't support some ALTER TABLE operations (like dropping columns, changing column types). For these changes, you need to create a new table and migrate the data.