---
description: 
globs: 
alwaysApply: true
---
# wa-sqlite Usage Guide

## Table of Contents
- [1. Overview](#1-overview)
- [2. Installation](#2-installation)
- [3. Basic Setup](#3-basic-setup)
  - [3.1 Import and Initialize](#31-import-and-initialize)
  - [3.2 Basic Database Operations](#32-basic-database-operations)
- [4. Virtual File Systems (VFS)](#4-virtual-file-systems-vfs)
  - [4.1 Available VFS Options](#41-available-vfs-options)
  - [4.2 Using a VFS](#42-using-a-vfs)
- [5. Best Practices](#5-best-practices)
  - [5.1 Error Handling](#51-error-handling)
  - [5.2 Transaction Management](#52-transaction-management)
  - [5.3 Prepared Statements](#53-prepared-statements)
- [6. Performance Considerations](#6-performance-considerations)
- [7. Common Issues and Solutions](#7-common-issues-and-solutions)
- [8. TypeScript Support](#8-typescript-support)

## 1. Overview
wa-sqlite is a WebAssembly build of SQLite that enables SQLite database operations in web browsers and JavaScript environments. It provides both synchronous and asynchronous builds, with support for custom virtual file systems (VFS) for persistent storage.

## 2. Installation
```bash
npm install wa-sqlite
# or
yarn add wa-sqlite
```

## 3. Basic Setup

### 3.1 Import and Initialize
```javascript
// Choose one of these imports based on your needs:
// - wa-sqlite.mjs: Synchronous build
// - wa-sqlite-async.mjs: Asynchronous build (required for async VFS)
// - wa-sqlite-jspi.mjs: JSPI-based async build (experimental, Chromium only)
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite.mjs';
import * as SQLite from 'wa-sqlite';

async function initDatabase() {
  // Initialize SQLite module
  const module = await SQLiteESMFactory();
  const sqlite3 = SQLite.Factory(module);
  
  // Open database (returns a Promise)
  const db = await sqlite3.open_v2('myDatabase');
  return { sqlite3, db };
}
```

### 3.2 Basic Database Operations
```javascript
async function basicOperations() {
  const { sqlite3, db } = await initDatabase();
  
  try {
    // Create a table
    await sqlite3.exec(db, `
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        email TEXT UNIQUE
      )
    `);
    
    // Insert data
    await sqlite3.exec(db, `
      INSERT INTO users (name, email) 
      VALUES ('John Doe', 'john@example.com')
    `);
    
    // Query data
    const results = [];
    await sqlite3.exec(db, 'SELECT * FROM users', (row, columns) => {
      results.push({ row, columns });
    });
    
    return results;
  } finally {
    // Always close the database when done
    await sqlite3.close(db);
  }
}
```

## 4. Virtual File Systems (VFS)

### 4.1 Available VFS Options
wa-sqlite provides several VFS implementations for persistent storage:

1. **IDBBatchAtomicVFS** (Recommended for general use)
   - Uses IndexedDB with batch atomic writes
   - Works in all contexts (Window, Worker, Service Worker)
   - Supports WAL mode
   - Best performance with `PRAGMA synchronous=normal`

2. **IDBMirrorVFS**
   - Keeps files in memory, persists to IndexedDB
   - Works in all contexts
   - Good for smaller databases

3. **OPFS-based VFS** (Origin Private File System)
   - Various implementations available:
     - AccessHandlePoolVFS
     - OPFSAdaptiveVFS
     - OPFSCoopSyncVFS
     - OPFSPermutedVFS
   - Better performance but limited to Worker contexts

### 4.2 Using a VFS
```javascript
import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js';
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite-async.mjs';
import * as SQLite from 'wa-sqlite';

async function initDatabaseWithVFS() {
  const module = await SQLiteESMFactory();
  const sqlite3 = SQLite.Factory(module);
  
  // Register VFS
  const vfs = await IDBBatchAtomicVFS.create('myApp', module);
  sqlite3.vfs_register(vfs, true);
  
  // Open database with VFS
  const db = await sqlite3.open_v2('myDatabase');
  
  // Configure for better performance
  await sqlite3.exec(db, 'PRAGMA synchronous = normal');
  await sqlite3.exec(db, 'PRAGMA journal_mode = WAL');
  
  return { sqlite3, db };
}
```

## 5. Best Practices

### 5.1 Error Handling
```javascript
async function safeDatabaseOperation() {
  const { sqlite3, db } = await initDatabase();
  
  try {
    await sqlite3.exec(db, 'SELECT * FROM non_existent_table');
  } catch (error) {
    if (error.code === SQLite.SQLITE_ERROR) {
      console.error('SQL error:', error.message);
    } else {
      console.error('Database error:', error);
    }
  } finally {
    await sqlite3.close(db);
  }
}
```

### 5.2 Transaction Management
```javascript
async function transactionExample() {
  const { sqlite3, db } = await initDatabase();
  
  try {
    await sqlite3.exec(db, 'BEGIN TRANSACTION');
    
    // Perform multiple operations
    await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Alice']);
    await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Bob']);
    
    await sqlite3.exec(db, 'COMMIT');
  } catch (error) {
    await sqlite3.exec(db, 'ROLLBACK');
    throw error;
  } finally {
    await sqlite3.close(db);
  }
}
```

### 5.3 Prepared Statements
```javascript
async function preparedStatementExample() {
  const { sqlite3, db } = await initDatabase();
  
  try {
    // Prepare statement
    const stmt = await sqlite3.prepare(db, 'SELECT * FROM users WHERE id = ?');
    
    // Execute with different parameters
    await sqlite3.bind(stmt, 1, 1);
    while (await sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
      const row = sqlite3.row(stmt);
      console.log(row);
    }
    
    // Reset and reuse
    await sqlite3.reset(stmt);
    await sqlite3.bind(stmt, 1, 2);
    // ... execute again
    
    await sqlite3.finalize(stmt);
  } finally {
    await sqlite3.close(db);
  }
}
```

## 6. Performance Considerations

1. **VFS Selection**
   - Use IDBBatchAtomicVFS for general-purpose applications
   - Consider OPFS-based VFS for better performance in Worker contexts
   - Use MemoryVFS for temporary databases

2. **Configuration**
   - Set appropriate page size (default is usually fine)
   - Use WAL mode for better concurrency
   - Consider `PRAGMA synchronous=normal` for better performance
   - Adjust cache size based on your needs

3. **Concurrency**
   - Use transactions for multiple operations
   - Be aware of VFS-specific concurrency limitations
   - Consider using Web Workers for heavy database operations

## 7. Common Issues and Solutions

1. **Database Locking**
   - Use appropriate transaction isolation levels
   - Implement retry logic for busy errors
   - Consider using WAL mode

2. **Storage Limitations**
   - Be aware of browser storage quotas
   - Implement cleanup strategies
   - Monitor database size

3. **Cross-Context Access**
   - Use appropriate VFS for your context
   - Consider message passing for cross-context communication
   - Be aware of storage access limitations

## 8. TypeScript Support
wa-sqlite includes TypeScript definitions. The main types are:

```typescript
type SQLiteCompatibleType = number | string | Uint8Array | Array<number> | bigint | null;

interface SQLiteAPI {
  open_v2(filename: string, flags?: number, zVfs?: string): Promise<number>;
  exec(db: number, sql: string, callback?: (row: any[], columns: string[]) => void): Promise<number>;
  close(db: number): Promise<number>;
  // ... other methods
}
```

## Additional Resources

- [Official GitHub Repository](https://github.com/rhashimoto/wa-sqlite)
- [Online Demo](https://rhashimoto.github.io/wa-sqlite/demo/)
- [API Reference](https://rhashimoto.github.io/wa-sqlite/docs/)
- [FAQ](https://github.com/rhashimoto/wa-sqlite/issues?q=is%3Aissue+label%3Afaq+)
- [Discussion Forums](https://github.com/rhashimoto/wa-sqlite/discussions) 