How to Use the SQLite Handler for .db Files in the Browser: A Complete Guide

The SQLite handler (sqlite3Handler) enables browser-based conversion of SQLite .db files to CSV by loading the official SQLite WebAssembly module, deserializing the database into memory, and exporting each table as a separate CSV file without any server-side processing.

The p2r3/convert repository provides a client-side file conversion framework that runs entirely in the browser. By implementing the FormatHandler interface, the SQLite handler for .db files allows developers to parse SQLite databases and extract tabular data as CSV using WebAssembly, eliminating the need for backend infrastructure.

How the SQLite Handler Works

Architecture Overview

The handler follows the generic FormatHandler contract defined in src/FormatHandler.ts. It acts as a bridge between the browser's file API and the SQLite WebAssembly runtime, converting binary .db files into structured CSV exports entirely within the client's memory space.

Registration and Format Declaration

In src/handlers/index.ts, the handler is instantiated and registered with the global handler list at lines 55-56:

import sqlite3Handler from "./sqlite.ts";
// ...
handlers.push(new sqlite3Handler());

This registration enables the application to recognize files with the .db extension and MIME type application/vnd.sqlite3.

The handler declares its capabilities in src/handlers/sqlite.ts through the supportedFormats array (lines 12-26), specifying SQLite3 as input and CSV as the output format:

supportedFormats = [
  {
    id: "sqlite3",
    name: "SQLite3 Database",
    extension: "db",
    mimeType: "application/vnd.sqlite3",
  },
  {
    id: "csv",
    name: "CSV",
    extension: "csv",
    mimeType: "text/csv",
    lossy: true,
    description: "Table data only; indexes and triggers are not preserved",
  },
];

WASM Initialization and Database Loading

When conversion begins, the handler lazily loads the official SQLite WebAssembly module from @sqlite.org/sqlite-wasm. In src/handlers/sqlite.ts at line 50, the initialization occurs:

const sqlite3 = await sqlite3InitModule();

The handler then deserializes the uploaded .db file into the WASM memory heap. At lines 54-68, the process allocates memory using sqlite3.wasm.allocFromTypedArray and attaches the buffer to an in-memory database instance via sqlite3.capi.sqlite3_deserialize:

const p = sqlite3.wasm.allocFromTypedArray(bytes);
const db = new sqlite3.oo1.DB(":memory:", "ct");
sqlite3.capi.sqlite3_deserialize(
  db.pointer,
  "main",
  p,
  bytes.length,
  bytes.length,
  sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE
);

Step-by-Step Implementation Guide

Registering the Handler

To enable SQLite support in your Convert instance, ensure the handler is imported and registered. The standard entry point in src/handlers/index.ts automatically pushes sqlite3Handler to the global handlers array:

import "./src/handlers/index.ts"; // Side-effect: registers all handlers including SQLite

Converting a .db File to CSV

Use the central convertFiles method from src/main.ts to process user-uploaded files. This example demonstrates reading a file from an HTML input element and converting it to multiple CSV files (one per table):

import convert from "./src/main.ts";

// HTML file input element
const fileInput = document.querySelector<HTMLInputElement>("#db-file");

fileInput?.addEventListener("change", async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;

  // Read file into Uint8Array
  const bytes = new Uint8Array(await file.arrayBuffer());
  const input = { name: file.name, bytes };

  // Perform conversion
  const csvFiles = await convert.convertFiles(
    [input],
    "sqlite3", // Input format ID from supportedFormats
    "csv"      // Output format ID
  );

  // Download each table as a separate CSV
  csvFiles.forEach(({ name, bytes }) => {
    const blob = new Blob([bytes], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `${name}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  });
});

Direct Handler Invocation

For advanced use cases, instantiate the handler directly to bypass the generic conversion facade:

import sqlite3Handler from "./src/handlers/sqlite.ts";

const handler = new sqlite3Handler();
await handler.init(); // Loads the WASM module

const csvFiles = await handler.doConvert(
  [{ name: "data.db", bytes: fileBytes }],
  { internal: "sqlite3", id: "sqlite3", name: "SQLite3" },
  { internal: "csv", id: "csv", name: "CSV" }
);

Key Source Files and Methods

Understanding the codebase structure helps when extending or debugging the SQLite handler:

  • src/handlers/sqlite.ts – Core implementation containing the sqlite3Handler class, doConvert method, and getTables helper.
  • src/handlers/index.ts – Registration point where the handler is instantiated and pushed to the global handlers array (lines 55-56).
  • src/FormatHandler.ts – Defines the FormatHandler interface and FileData contract used across all handlers.
  • src/main.ts – Exposes the convertFiles orchestration method that routes files to appropriate handlers based on format IDs.
  • package.json – Declares the @sqlite.org/sqlite-wasm dependency required for in-browser SQLite parsing.

Summary

  • The SQLite handler (sqlite3Handler) enables fully client-side conversion of .db files to CSV using WebAssembly.
  • The handler registers itself in src/handlers/index.ts and declares support for SQLite3 input and CSV output in src/handlers/sqlite.ts.
  • It utilizes the official @sqlite.org/sqlite-wasm package to deserialize database files into memory and execute SQL queries.
  • The getTables() method enumerates tables using sqlite_master, while doConvert() exports each table as a separate CSV file.
  • Developers can invoke the handler through the central convertFiles() API or instantiate sqlite3Handler directly for fine-grained control.

Frequently Asked Questions

What dependencies are required to use the SQLite handler in the browser?

The handler requires the @sqlite.org/sqlite-wasm package, which provides the official SQLite WebAssembly build. This dependency is declared in package.json and is loaded lazily when the handler's init() method is called, ensuring the WASM runtime is only fetched when needed.

Can the SQLite handler export database objects other than tables?

No, the current implementation only exports table data. According to the supportedFormats definition in src/handlers/sqlite.ts, the conversion is lossy and specifically excludes indexes, triggers, views, and other database objects. Only the data rows from tables found in sqlite_master are converted to CSV format.

Is the SQLite handler compatible with all SQLite .db file versions?

The handler relies on the official @sqlite.org/sqlite-wasm package, which supports standard SQLite 3 database formats. However, compatibility depends on the specific WASM build version specified in the project's dependencies. Databases using very recent SQLite features or non-standard extensions may require updating the WASM dependency in package.json.

How does the handler handle large .db files in the browser?

The handler loads the entire database file into WebAssembly memory using sqlite3.wasm.allocFromTypedArray and sqlite3.capi.sqlite3_deserialize. This means the entire .db file must fit within the browser's available memory and the WASM heap limits. For extremely large databases, this may cause performance issues or out-of-memory errors, as the current implementation does not support streaming or chunked processing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →