{"id":33247478,"url":"https://github.com/npiesco/absurder-sql","last_synced_at":"2026-01-03T01:22:04.464Z","repository":{"id":318993212,"uuid":"1038831519","full_name":"npiesco/absurder-sql","owner":"npiesco","description":"absurder-sql which absurdly utilizes a custom SQLite VFS backend to treat IndexedDB like a disc and store data blocks.","archived":false,"fork":false,"pushed_at":"2025-11-10T01:18:43.000Z","size":14523,"stargazers_count":98,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-10T03:16:06.458Z","etag":null,"topics":["absurdity","grafana","indexeddb","npm","npm-module","npm-package","prometheus","rust","sqlite","sqlite3","wasm","wasm-bindgen"],"latest_commit_sha":null,"homepage":"https://iscopesolutions.net/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/npiesco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-15T22:43:30.000Z","updated_at":"2025-11-08T20:53:59.000Z","dependencies_parsed_at":"2025-10-17T16:32:59.206Z","dependency_job_id":"5492f754-0a11-4982-90b1-1bff97ba0e1c","html_url":"https://github.com/npiesco/absurder-sql","commit_stats":null,"previous_names":["npiesco/absurder-sql"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/npiesco/absurder-sql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npiesco%2Fabsurder-sql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npiesco%2Fabsurder-sql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npiesco%2Fabsurder-sql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npiesco%2Fabsurder-sql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/npiesco","download_url":"https://codeload.github.com/npiesco/absurder-sql/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/npiesco%2Fabsurder-sql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284775706,"owners_count":27061386,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-16T02:00:05.974Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["absurdity","grafana","indexeddb","npm","npm-module","npm-package","prometheus","rust","sqlite","sqlite3","wasm","wasm-bindgen"],"created_at":"2025-11-16T21:01:23.466Z","updated_at":"2026-01-03T01:22:04.457Z","avatar_url":"https://github.com/npiesco.png","language":"C","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"absurder-sql.png\" alt=\"AbsurderSQL Logo\" width=\"200\"/\u003e\n  \u003ch1\u003eAbsurderSQL\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eRust + WASM + SQLite + IndexedDB\u003c/strong\u003e\u003c/p\u003e\n  \n  [![npm](https://img.shields.io/npm/v/@npiesco/absurder-sql)](https://www.npmjs.com/package/@npiesco/absurder-sql)\n  [![npm downloads](https://img.shields.io/npm/dm/@npiesco/absurder-sql)](https://www.npmjs.com/package/@npiesco/absurder-sql)\n  [![crates.io](https://img.shields.io/crates/v/absurder-sql)](https://crates.io/crates/absurder-sql)\n  [![crates.io downloads](https://img.shields.io/crates/d/absurder-sql)](https://crates.io/crates/absurder-sql)\n\u003c/div\u003e\n\n**Tech Stack:**  \n[![Rust](https://img.shields.io/badge/rust-1.85%2B-orange)](Cargo.toml)\n[![WASM](https://img.shields.io/badge/wasm-supported-blue)](https://webassembly.org/)\n[![SQLite](https://img.shields.io/badge/sqlite-embedded-blue)](https://www.sqlite.org/)\n[![IndexedDB](https://img.shields.io/badge/indexeddb-browser-green)](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)\n\n**Capabilities:**\n[![Dual Mode](https://img.shields.io/badge/mode-Browser%20%2B%20Native-purple)](docs/DUAL_MODE.md)\n[![Mobile](https://img.shields.io/badge/mobile-iOS%20%2B%20Android-61dafb)](absurder-sql-mobile/)\n[![Export/Import](https://img.shields.io/badge/export%2Fimport-full%20portability-success)](docs/EXPORT_IMPORT.md)\n[![Telemetry](https://img.shields.io/badge/telemetry-optional-lightgrey)](#telemetry-optional)\n[![Prometheus](https://img.shields.io/badge/prometheus-metrics-orange)](monitoring/prometheus/)\n[![Grafana](https://img.shields.io/badge/grafana-dashboards-orange)](monitoring/grafana/)\n[![DevTools](https://img.shields.io/badge/devtools-chrome%2Ffirefox-blue)](browser-extension/)\n\n\u003e *SQLite + IndexedDB + Custom VFS that's absurdly absurder than absurd-sql*\n\n## This is an absurd*er* project.\n\nIt implements a custom SQLite Virtual File System (VFS) backend that treats **IndexedDB like a disk** and stores data in blocks there. Your database lives permanently in browser storage with **intelligent block-level I/O**—reading and writing 4KB chunks with LRU caching—avoiding the performance nightmare of serializing entire database files on every operation.\n\n**It basically stores a whole database into another database using a custom VFS. Which is absurd*er*.**\n\nBut AbsurderSQL takes it further: it's **absurdly better**. Unlike absurd-sql, your data isn't locked in IndexedDB forever—you can **[export and import](docs/EXPORT_IMPORT.md)** standard SQLite files. Need to query from both browser and CLI? Use **[dual-mode persistence](docs/DUAL_MODE.md)**—same database structure, IndexedDB in the browser and real files on the server. Multiple tabs? **[Multi-tab coordination](docs/MULTI_TAB_GUIDE.md)** with automatic leader election prevents conflicts. Want production observability? Optional **[Prometheus + Grafana monitoring](monitoring/)** with **[DevTools extension](browser-extension/)** for debugging WASM telemetry.\n\n**Read the [blog post](https://iscopesolutions.net/) that explains the absurdity in detail.**\n\n---\n\n### Why AbsurderSQL?\n\nA high-performance **tri-mode** Rust library that brings full SQLite functionality to **browsers, native applications, and mobile devices**:\n\n- **Browser (WASM)**: SQLite → IndexedDB with multi-tab coordination, Web Worker support, and full export/import\n- **Native/CLI**: SQLite → Real filesystem with traditional `.db` files\n- **Mobile (React Native)**: SQLite → Device filesystem via UniFFI with SQLCipher encryption for iOS and Android\n\n**Unique Advantages:** \n\nExport/import databases as standard SQLite files (absurd-sql has no export/import—data is permanently locked in IndexedDB). Build web apps that store data in IndexedDB, then query the same database structure from CLI/server using standard SQLite tools. Multi-tab coordination with automatic leader election prevents conflicts. Perfect for offline-first applications with backup/restore, data migration, and optional server synchronization.\n\n**Production Observability (Optional):** When enabled with `--features telemetry`, includes complete monitoring stack: Prometheus metrics, OpenTelemetry tracing, pre-built Grafana dashboards, production-ready alert rules with runbooks, and a Chrome/Firefox DevTools extension for debugging WASM telemetry. All telemetry features are opt-in—default builds include zero monitoring overhead.\n\nEnabling production-ready SQL operations with crash consistency, multi-tab coordination, complete data portability, optional observability, and the flexibility to run anywhere from web apps to server applications.\n\n## Tri-Mode Architecture\n\nAbsurderSQL runs in **three modes** - Browser (WASM), Native (Rust CLI/Server), and Mobile (React Native):\n```mermaid\ngraph TB\n    subgraph \"Browser Environment (WASM)\"\n        JS[\"JavaScript/TypeScript\u003cbr/\u003eWeb Application\"]\n        WASM[\"WASM Bridge\u003cbr/\u003e(wasm-bindgen)\"]\n    end\n    \n    subgraph \"Native Environment (Rust)\"\n        CLI[\"CLI/Server\u003cbr/\u003eApplication\"]\n        NATIVE_DB[\"Native Database API\u003cbr/\u003e(database.rs)\"]\n    end\n\n    subgraph \"Mobile Environment (React Native)\"\n        RN[\"React Native App\u003cbr/\u003e(TypeScript)\"]\n        UNIFFI[\"UniFFI Bridge\u003cbr/\u003e(Swift/Kotlin)\"]\n    end\n    \n    subgraph \"AbsurderSQL Core (Rust)\"\n        DB[\"Database API\u003cbr/\u003e(lib.rs)\"]\n        SQLITE[\"SQLite Engine\u003cbr/\u003e(sqlite-wasm-rs / rusqlite)\"]\n        VFS[\"Custom VFS Layer\u003cbr/\u003e(indexeddb_vfs.rs)\"]\n        \n        subgraph \"Storage Layer\"\n            BS[\"BlockStorage\u003cbr/\u003e(block_storage.rs)\"]\n            SYNC[\"Sync Operations\u003cbr/\u003e(sync_operations.rs)\"]\n            META[\"Metadata Manager\u003cbr/\u003e(metadata.rs)\"]\n            CACHE[\"LRU Cache\u003cbr/\u003e(128 blocks)\"]\n            ALLOC[\"Allocation\u003cbr/\u003e(allocation.rs)\"]\n            EXPORT[\"Export\u003cbr/\u003e(export.rs)\"]\n            IMPORT[\"Import\u003cbr/\u003e(import.rs)\"]\n        end\n        \n        subgraph \"Multi-Tab Coordination (Browser Only)\"\n            LEADER[\"Leader Election\u003cbr/\u003e(leader_election.rs)\"]\n            BCAST[\"BroadcastChannel\u003cbr/\u003e(broadcast_notifications.rs)\"]\n            QUEUE[\"Write Queue\u003cbr/\u003e(write_queue.rs)\"]\n        end\n        \n        subgraph \"Monitoring \u0026 Recovery\"\n            OBS[\"Observability\u003cbr/\u003e(observability.rs)\"]\n            RECOVERY[\"Recovery\u003cbr/\u003e(recovery.rs)\"]\n        end\n    end\n    \n    subgraph \"Browser Persistence\"\n        INDEXEDDB[\"IndexedDB\u003cbr/\u003e(Browser Storage)\"]\n        LOCALSTORAGE[\"localStorage\u003cbr/\u003e(Coordination)\"]\n    end\n    \n    subgraph \"Native Persistence\"\n        FILESYSTEM[\"Filesystem\u003cbr/\u003e(Traditional .db files)\"]\n        BLOCKS[\"./absurdersql_storage/\u003cbr/\u003edatabase.sqlite + blocks/\"]\n    end\n\n    subgraph \"Mobile Persistence\"\n        DEVICE_FS[\"Device Filesystem\u003cbr/\u003e(iOS/Android Storage)\"]\n        SQLCIPHER[\"SQLCipher\u003cbr/\u003e(AES-256 Encryption)\"]\n    end\n    \n    subgraph \"Telemetry Stack (optional --features telemetry)\"\n        PROM[\"Prometheus\u003cbr/\u003e(Metrics)\"]\n        OTEL[\"OpenTelemetry\u003cbr/\u003e(Traces)\"]\n        GRAFANA[\"Grafana Dashboards\"]\n        ALERTS[\"Alert Rules\"]\n        DEVTOOLS[\"DevTools Extension\u003cbr/\u003e(Chrome/Firefox)\"]\n    end\n    \n    JS --\u003e|execute/query| WASM\n    WASM --\u003e|calls| DB\n    CLI --\u003e|execute/query| NATIVE_DB\n    NATIVE_DB --\u003e|SQL| SQLITE\n    RN --\u003e|execute/query| UNIFFI\n    UNIFFI --\u003e|calls| DB\n    DB --\u003e|SQL| SQLITE\n    DB --\u003e|exportToFile| EXPORT\n    DB --\u003e|importFromFile| IMPORT\n    SQLITE --\u003e|VFS calls| VFS\n    VFS --\u003e|block I/O| BS\n    BS --\u003e|read/write| CACHE\n    BS --\u003e|allocate| ALLOC\n    BS --\u003e|persist| SYNC\n    SYNC --\u003e|metadata| META\n    EXPORT --\u003e|read blocks| BS\n    IMPORT --\u003e|write blocks| BS\n    BS --\u003e|\"WASM mode\"| INDEXEDDB\n    BS --\u003e|\"Native mode\"| FILESYSTEM\n    NATIVE_DB --\u003e|\"fs_persist\"| BLOCKS\n    UNIFFI --\u003e|\"Mobile mode\"| DEVICE_FS\n    DEVICE_FS --\u003e|\"encryption\"| SQLCIPHER\n    BS --\u003e|metrics| OBS\n    LEADER --\u003e|atomic ops| LOCALSTORAGE\n    LEADER --\u003e|notify| BCAST\n    QUEUE --\u003e|forward| BCAST\n    OBS --\u003e|\"--features telemetry\"| PROM\n    OBS --\u003e|\"--features telemetry\"| OTEL\n    PROM --\u003e|scrape| GRAFANA\n    PROM --\u003e|evaluate| ALERTS\n    OTEL --\u003e|spans| DEVTOOLS\n    \n    style SQLITE fill:#a855f7,stroke:#333,color:#fff\n    style VFS fill:#3b82f6,stroke:#333,color:#fff\n    style BS fill:#fbbf24,stroke:#333,color:#000\n    style EXPORT fill:#ec4899,stroke:#333,color:#fff\n    style IMPORT fill:#8b5cf6,stroke:#333,color:#fff\n    style INDEXEDDB fill:#22c55e,stroke:#333,color:#000\n    style QUEUE fill:#ef4444,stroke:#333,color:#fff\n    style OBS fill:#92400e,stroke:#333,color:#fff\n    style PROM fill:#1c1c1c,stroke:#333,color:#fff\n    style GRAFANA fill:#f97316,stroke:#333,color:#fff\n    \n    %% Default styling for uncolored blocks (light gray)\n    style JS fill:#d1d5db,stroke:#333,color:#000\n    style WASM fill:#d1d5db,stroke:#333,color:#000\n    style CLI fill:#d1d5db,stroke:#333,color:#000\n    style NATIVE_DB fill:#d1d5db,stroke:#333,color:#000\n    style DB fill:#d1d5db,stroke:#333,color:#000\n    style SYNC fill:#d1d5db,stroke:#333,color:#000\n    style META fill:#d1d5db,stroke:#333,color:#000\n    style CACHE fill:#d1d5db,stroke:#333,color:#000\n    style ALLOC fill:#d1d5db,stroke:#333,color:#000\n    style LEADER fill:#d1d5db,stroke:#333,color:#000\n    style BCAST fill:#d1d5db,stroke:#333,color:#000\n    style RECOVERY fill:#d1d5db,stroke:#333,color:#000\n    style LOCALSTORAGE fill:#d1d5db,stroke:#333,color:#000\n    style FILESYSTEM fill:#d1d5db,stroke:#333,color:#000\n    style BLOCKS fill:#d1d5db,stroke:#333,color:#000\n    style RN fill:#61dafb,stroke:#333,color:#000\n    style UNIFFI fill:#10b981,stroke:#333,color:#fff\n    style DEVICE_FS fill:#d1d5db,stroke:#333,color:#000\n    style SQLCIPHER fill:#f59e0b,stroke:#333,color:#000\n    style OTEL fill:#d1d5db,stroke:#333,color:#000\n    style ALERTS fill:#d1d5db,stroke:#333,color:#000\n    style DEVTOOLS fill:#d1d5db,stroke:#333,color:#000\n```\n\n**Legend:**\n🟪 SQLite Engine • 🟦 VFS Layer • 🟨 BlockStorage • 🟩 Persistence • 🟥 Multi-Tab\n🟫 Observability • ⬛ Prometheus • 🟧 Grafana • 🩵 React Native • 🟢 UniFFI\n\n## Project Structure\n\n```\nabsurder-sql/\n├── src/\n│   ├── lib.rs              # WASM entry point, Database API exports\n│   ├── database.rs         # Native Database implementation\n│   ├── types.rs            # Core types (QueryResult, ColumnValue, etc.)\n│   ├── utils.rs            # Utility functions\n│   │\n│   ├── bin/                # Binary executables\n│   │   └── cli_query.rs    # CLI query tool for filesystem databases\n│   │\n│   ├── storage/            # Storage layer implementation\n│   │   ├── mod.rs\n│   │   ├── block_storage.rs           # Core block storage with LRU cache\n│   │   ├── sync_operations.rs        # Cross-platform sync logic\n│   │   ├── io_operations.rs          # Read/write operations\n│   │   ├── allocation.rs             # Block allocation/deallocation\n│   │   ├── metadata.rs               # Block metadata management\n│   │   ├── export.rs                 # Database export to SQLite files\n│   │   ├── import.rs                 # Database import from SQLite files\n│   │   ├── retry_logic.rs            # Retry logic for transient failures\n│   │   ├── fs_persist.rs             # Native filesystem persistence\n│   │   ├── wasm_indexeddb.rs         # WASM IndexedDB integration\n│   │   ├── wasm_vfs_sync.rs          # WASM VFS sync coordination\n│   │   ├── recovery.rs               # Crash recovery logic\n│   │   ├── auto_sync.rs              # Native auto-sync\n│   │   ├── wasm_auto_sync.rs         # WASM auto-sync\n│   │   ├── leader_election.rs        # Multi-tab leader election\n│   │   ├── broadcast_notifications.rs # BroadcastChannel messaging\n│   │   ├── write_queue.rs            # Write queuing for non-leaders\n│   │   ├── optimistic_updates.rs     # Optimistic UI updates\n│   │   ├── coordination_metrics.rs   # Performance metrics tracking\n│   │   ├── observability.rs          # Metrics and monitoring\n│   │   └── constructors.rs           # BlockStorage constructors\n│   │\n│   └── vfs/                # SQLite VFS implementation\n│       ├── mod.rs\n│       └── indexeddb_vfs.rs     # Custom VFS for IndexedDB\n│\n├── tests/                  # Comprehensive test suite\n│   ├── integration_tests.rs          # End-to-end tests\n│   ├── native_database_persistence_tests.rs  # Native filesystem tests\n│   ├── wasm_integration_tests.rs     # WASM-specific tests (inc. export/import)\n│   ├── export_import_examples_test.rs # Export/import validation tests\n│   ├── export_import_lock_tests.rs   # Export/import locking tests\n│   ├── vfs_durability_tests.rs       # VFS durability tests\n│   ├── lru_cache_tests.rs            # Cache tests\n│   ├── e2e/                          # Playwright E2E tests\n│   │   ├── dual_mode_persistence.spec.js  # Browser + CLI validation\n│   │   ├── advanced-features.spec.js\n│   │   └── multi-tab-vite.spec.js\n│   └── ...                           # 65+ test files total\n│\n├── examples/               # Browser demos and documentation\n│   ├── vite-app/           # Production Vite application\n│   ├── export_import_demo.html        # Export/import 4-step wizard demo\n│   ├── export_import.js               # 9 production export/import examples\n│   ├── test_export_import_examples.html # Export/import test suite\n│   ├── sql_demo.html       # Interactive SQL demo page\n│   ├── web_demo.html       # Full-featured web interface\n│   ├── benchmark.html      # Performance comparison tool\n│   ├── multi-tab-demo.html # Multi-tab coordination demo\n│   ├── worker-example.html # Web Worker demo\n│   ├── worker-db.js        # Web Worker implementation\n│   ├── devtools_demo.html  # DevTools extension telemetry demo\n│   └── DEMO_GUIDE.md       # Demo usage guide\n│\n├── docs/                   # Comprehensive documentation\n│   ├── EXPORT_IMPORT.md    # Export/import guide (DATABASE PORTABILITY)\n│   ├── DUAL_MODE.md        # Tri-mode persistence guide\n│   ├── MULTI_TAB_GUIDE.md  # Multi-tab coordination\n│   ├── TRANSACTION_SUPPORT.md # Transaction handling\n│   ├── BENCHMARK.md        # Performance benchmarks\n│   ├── ENCRYPTION.md       # SQLCipher encryption guide\n│   ├── CODING_STANDARDS.md # Development best practices\n│   ├── REMAINING_UNWRAPS.md # Unwrap safety analysis\n│   └── mobile/             # Mobile-specific documentation\n│       ├── INSTRUCTIONS.md     # Mobile build instructions\n│       └── MOBILE_BENCHMARK.md # Mobile performance benchmarks\n│\n├── monitoring/             # Production observability (optional --features telemetry)\n│   ├── grafana/            # Pre-built Grafana dashboards\n│   │   ├── query_performance.json\n│   │   ├── storage_operations.json\n│   │   ├── system_health.json\n│   │   └── multi_tab_coordination.json\n│   ├── prometheus/         # Alert rules and recording rules\n│   │   └── alert_rules.yml # Alert rules + recording rules\n│   └── RUNBOOK.md          # Alert runbooks and remediation procedures\n│\n├── browser-extension/      # Browser DevTools extension (Chrome/Firefox)\n│   ├── manifest.json       # Manifest V3 extension configuration\n│   ├── devtools.js         # Message hub (devtools page)\n│   ├── content.js          # Content script (page bridge)\n│   ├── panel.html/css/js   # DevTools panel UI\n│   ├── icons/              # Extension icons (16, 48, 128)\n│   ├── README.md           # Extension features and architecture\n│   └── INSTALLATION.md     # Installation guide\n│\n├── absurder-sql-mobile/    # React Native bindings (iOS + Android)\n│   ├── src/\n│   │   ├── uniffi_api/     # UniFFI exported functions\n│   │   │   ├── core.rs     # 20 exported database functions\n│   │   │   └── types.rs    # QueryResult, DatabaseConfig, etc.\n│   │   ├── AbsurderDatabase.ts  # High-level TypeScript API\n│   │   └── lib.rs          # Crate entry point\n│   ├── android/            # Android-specific (Kotlin bindings, SQLCipher libs)\n│   ├── ios/                # iOS-specific (Swift bindings)\n│   ├── react-native/       # Test app for iOS/Android\n│   ├── scripts/            # Build helper scripts\n│   └── README.md           # Mobile setup guide\n│\n├── pkg/                    # WASM build output (generated)\n├── Cargo.toml             # Rust dependencies and config\n├── package.json           # Node.js dependencies\n└── README.md              # This file\n```\n\n## System Architecture\n\n### Core Architecture\nThe project follows a modular architecture with clear separation of concerns:\n\n**VFS Layer**: Implements a custom SQLite Virtual File System that translates SQLite's file operations to IndexedDB operations. This allows SQLite to work seamlessly with browser storage without modifications to the core SQLite engine.\n\n**Storage Abstraction**: Provides a unified interface for different storage backends, with IndexedDB as the primary target. The design allows for future expansion to other storage mechanisms while maintaining API compatibility.\n\n**WASM Bridge**: Handles the interface between Rust code and JavaScript, managing memory allocation, type conversions, and async operation bridging. Uses `sqlite-wasm-rs` for stable SQLite operations without the hang issues that affected previous implementations. This ensures smooth interoperability between the WASM module and browser JavaScript.\n\n**Type System**: Defines comprehensive data structures for SQL operations, query results, and configuration options, ensuring type safety across the Rust-JavaScript boundary.\n\n### Frontend Architecture\nThe web demo uses vanilla JavaScript with Bootstrap for styling, demonstrating real-time SQL query execution and result visualization. The frontend architecture emphasizes simplicity and direct WASM integration without complex frameworks.\n\n### Data Storage Design\n**Primary Storage**: IndexedDB serves as the persistent storage layer, chosen for its transaction support, large storage capacity, and widespread browser compatibility.\n\n**Memory Management**: The library implements careful memory management for WASM operations, ensuring proper cleanup of allocated memory and efficient data transfer between Rust and JavaScript contexts.\n\n**Transaction Handling**: Leverages SQLite's transaction capabilities while ensuring proper coordination with IndexedDB's transaction model for data consistency.\n\n### Configuration System\nThe architecture supports configurable database options including cache size, synchronization modes, and VFS-specific settings, allowing optimization for different use cases and performance requirements.\n\n---\n\n## Export/Import: Full Database Portability\n\n**AbsurderSQL provides complete database export and import functionality - a critical feature that absurd-sql completely lacks.**\n\n### Why This Matters\n\nWith AbsurderSQL, your data is **never locked in the browser**. You can:\n\n- **Export** databases as standard SQLite files\n- **Import** databases from SQLite files\n- **Backup** your data with one function call\n- **Migrate** databases between devices and browsers\n- **Debug** exported files with sqlite3 CLI or DB Browser\n- **Share** databases as downloadable files\n\n**absurd-sql alternative**: No export/import - data is permanently trapped in IndexedDB\n\n### Quick Example\n\n```javascript\n// From npm package\nimport init, { Database } from '@npiesco/absurder-sql';\n\n// Or from local build\n// import init, { Database } from './pkg/absurder_sql.js';\n\nawait init();\nconst db = await Database.newDatabase('myapp.db');\n\n// Create some data\nawait db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');\nawait db.execute(\"INSERT INTO users VALUES (1, 'Alice')\");\n\n// EXPORT: Get entire database as standard SQLite file\nconst exportedData = await db.exportToFile();\n\n// Download for user\nconst blob = new Blob([exportedData], { type: 'application/octet-stream' });\nconst url = URL.createObjectURL(blob);\nconst a = document.createElement('a');\na.href = url;\na.download = 'myapp.db';\na.click();\n\n// IMPORT: Load database from file\nconst file = document.getElementById('fileInput').files[0];\nconst arrayBuffer = await file.arrayBuffer();\nawait db.importFromFile(new Uint8Array(arrayBuffer));\n\n// Database is immediately usable after import (no reopen needed)\nconst result = await db.execute('SELECT * FROM users');\n```\n\n### Interactive Demos\n\n- **[Export/Import Demo](examples/export_import_demo.html)** - 4-step wizard with progress tracking\n- **[Automated Tests](examples/test_export_import_examples.html)** - 5 validation tests\n- **[Code Examples](examples/export_import.js)** - 9 production-ready examples\n\n### Full Documentation\n\nSee **[docs/EXPORT_IMPORT.md](docs/EXPORT_IMPORT.md)** for:\n- Complete API reference\n- Architecture details\n- Best practices \u0026 patterns\n- Troubleshooting guide\n- Size limits \u0026 performance\n\n---\n\n## Getting Started\n\n### Installation\n\n#### Option 1: Install from npm (Recommended)\n\n```bash\nnpm install @npiesco/absurder-sql\n```\n\nThen use in your project:\n\n```javascript\nimport init, { Database } from '@npiesco/absurder-sql';\n\n// Initialize WASM\nawait init();\n\n// Create database\nconst db = await Database.newDatabase('myapp.db');\n\n// Use SQLite\nawait db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');\nawait db.execute(\"INSERT INTO users VALUES (1, 'Alice')\");\nconst result = await db.execute('SELECT * FROM users');\n\n// Export for backup\nconst backup = await db.exportToFile();\n\n// Close when done\nawait db.close();\n```\n\n**Package includes:**\n- Pre-built WASM binary (~1.3MB, ~595KB gzipped)\n- TypeScript definitions\n- All necessary JavaScript glue code\n- **No telemetry dependencies** - minimal size, zero observability overhead\n\n\u003e **Note:** The npm package is built without the `telemetry` feature for smaller size and faster load times. If you need Prometheus/OpenTelemetry support for production monitoring, build from source with `--features telemetry`.\n\n#### Option 2: Install from crates.io (Rust Projects)\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\nabsurder-sql = \"0.1.23\"\n```\n\nOr use cargo:\n\n```bash\ncargo add absurder-sql\n```\n\n**Available on [crates.io](https://crates.io/crates/absurder-sql)** with full Rust documentation and dual-mode support (browser WASM + native CLI).\n\n#### Option 3: Build from Source\n\nFor development or custom builds:\n\n**Prerequisites:**\n- **Rust 1.85.0+** with the 2024 edition\n- **wasm-pack** for building WASM packages\n- **Node.js 18+** for running examples\n\n```bash\n# Clone the repository\ngit clone https://github.com/npiesco/absurder-sql\ncd absurder-sql\n\n# Install wasm-pack if needed\ncurl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh\n\n# Build for web\nwasm-pack build --target web --out-dir pkg\n```\n\nThis generates the `pkg/` directory containing:\n- `absurder_sql.js` - JavaScript module\n- `absurder_sql_bg.wasm` - WebAssembly binary (~1.3MB)\n- TypeScript definitions and package files\n\n### Optional Features\n\nAbsurderSQL supports optional feature flags to minimize dependencies and binary size:\n\n#### Telemetry (Optional - Build from Source Only)\n\n**The npm package does NOT include telemetry** for minimal size. To enable telemetry features (Prometheus metrics, OpenTelemetry tracing), you must build from source with the `telemetry` feature flag:\n\n```bash\n# Build with telemetry support (Prometheus + OpenTelemetry)\nwasm-pack build --target web --out-dir pkg --features telemetry\n\n# Build without telemetry (default - smaller binary, zero telemetry overhead)\nwasm-pack build --target web --out-dir pkg\n```\n\n**What telemetry provides:**\n- Prometheus metrics (queries, errors, cache hits/misses, block operations)\n- OpenTelemetry distributed tracing spans\n- Performance monitoring and observability\n\n**Dependencies (only when `telemetry` feature is enabled):**\n- `prometheus` - Metrics collection\n- `opentelemetry` - Distributed tracing\n- `opentelemetry_sdk` - Tracing SDK\n- `opentelemetry-prometheus` - Prometheus exporter\n\n**When to use:**\n- Production monitoring and observability\n- Performance debugging and profiling\n- Integration with Grafana/Prometheus stack\n- Not needed for typical applications (default build excludes it)\n\n**Exposing Metrics for Prometheus (Native Applications):**\n\nAbsurderSQL collects metrics in-memory but does NOT include an HTTP server. For Prometheus scraping, add a `/metrics` endpoint to your application's HTTP server:\n\n```rust\n// Example with axum\nuse absurder_sql::Database;\nuse prometheus::Encoder;\nuse axum::{Router, routing::get, extract::State};\n\nasync fn metrics_handler(State(db): State\u003cDatabase\u003e) -\u003e String {\n    #[cfg(feature = \"telemetry\")]\n    if let Some(metrics) = db.metrics() {\n        let encoder = prometheus::TextEncoder::new();\n        let metric_families = metrics.registry().gather();\n        return encoder.encode_to_string(\u0026metric_families).unwrap();\n    }\n    \"Telemetry not enabled\".to_string()\n}\n\n#[tokio::main]\nasync fn main() {\n    let db = Database::new(\"myapp.db\").await.unwrap();\n    let app = Router::new()\n        .route(\"/metrics\", get(metrics_handler))\n        .with_state(db);\n    \n    axum::Server::bind(\u0026\"0.0.0.0:9090\".parse().unwrap())\n        .serve(app.into_make_service())\n        .await\n        .unwrap();\n}\n```\n\nThen configure Prometheus to scrape `http://localhost:9090/metrics`.\n\n**Additional actix-web example:**\n\n```rust\nuse absurder_sql::Database;\nuse actix_web::{web, App, HttpServer, HttpResponse};\nuse prometheus::Encoder;\n\nasync fn metrics(db: web::Data\u003cDatabase\u003e) -\u003e HttpResponse {\n    #[cfg(feature = \"telemetry\")]\n    if let Some(metrics) = db.metrics() {\n        let encoder = prometheus::TextEncoder::new();\n        let metric_families = metrics.registry().gather();\n        let body = encoder.encode_to_string(\u0026metric_families).unwrap();\n        return HttpResponse::Ok()\n            .content_type(\"text/plain; version=0.0.4\")\n            .body(body);\n    }\n    HttpResponse::Ok().body(\"Telemetry not enabled\")\n}\n```\n\n### Production Observability Stack\n\nWhen `--features telemetry` is enabled, AbsurderSQL provides a complete production observability stack.\n\n**[Complete Monitoring Setup Guide](monitoring/README.md)** | **[Alert Runbook](monitoring/RUNBOOK.md)** | **[DevTools Extension](browser-extension/README.md)**\n\n#### Grafana Dashboards (4 Dashboards, 28 Panels)\n\nPre-built Grafana dashboards provide real-time visibility into database operations:\n\n1. **Query Performance Dashboard** (`monitoring/grafana/query_performance.json`)\n   - Query execution times (p50, p90, p99)\n   - Query rate and error rate\n   - Slow query detection\n   - 7 panels with drill-down capabilities\n\n2. **Storage Operations Dashboard** (`monitoring/grafana/storage_operations.json`)\n   - Block read/write rates\n   - Cache hit rates and effectiveness\n   - Storage layer latency\n   - 6 panels for storage health monitoring\n\n3. **System Health Dashboard** (`monitoring/grafana/system_health.json`)\n   - Error rates by type\n   - Transaction success rates\n   - Resource utilization\n   - 8 panels for overall system health\n\n4. **Multi-Tab Coordination Dashboard** (`monitoring/grafana/multi_tab_coordination.json`)\n   - Leader election status\n   - Write queue depth\n   - Sync operations\n   - 7 panels for multi-tab debugging\n\n**Import dashboards:** Load the JSON files directly into Grafana. All dashboards include variable templates for filtering by database instance.\n\n#### Alert Rules (18 Alerts + 26 Recording Rules)\n\nProduction-ready Prometheus alert rules with runbooks:\n\n**Critical Alerts:**\n- High error rate (\u003e5% over 5 minutes)\n- Extreme query latency (p99 \u003e 1 second)\n- Zero query throughput (potential deadlock)\n- Storage failures (\u003e3 failures per minute)\n\n**Warning Alerts:**\n- Elevated error rates, slow queries, cache inefficiency\n- Multi-tab coordination issues\n\n**Info Alerts:**\n- New leader elected, first query executed\n\n**Recording Rules:**\n- Pre-aggregated metrics for faster dashboard queries\n- Query rate calculations, error ratios, latency percentiles\n\nAll alerts include:\n- Severity labels (critical/warning/info)\n- Team routing (database-team/platform-team)\n- Detailed annotations explaining the issue\n- Links to runbooks with remediation steps\n\n**Location:** `monitoring/prometheus/alert_rules.yml`\n\n**Runbooks:** `monitoring/RUNBOOK.md` provides step-by-step debugging and remediation procedures for every alert type.\n\n#### Browser DevTools Extension\n\nChrome/Firefox extension for debugging WASM telemetry in the browser:\n\n**Features:**\n- Real-time span visualization with filtering\n- Export statistics (success/failure rates)\n- Manual flush trigger\n- Buffer inspection\n- OTLP endpoint configuration\n\n**Architecture:** Manifest V3 compliant with proper message passing (page → content script → devtools hub → panel)\n\n**Installation:**\n1. Chrome: Load unpacked from `browser-extension/`\n2. Firefox: Load temporary add-on from `browser-extension/manifest.json`\n\nSee `browser-extension/README.md` and `browser-extension/INSTALLATION.md` for complete setup instructions.\n\n**Demo Page:** `examples/devtools_demo.html` generates sample telemetry for testing the extension.\n\n#### Filesystem Persistence (Native Only)\n\nEnable native filesystem persistence for CLI/server applications:\n\n```bash\n# Build with filesystem persistence\ncargo build --features fs_persist\n\n# Run tests with filesystem persistence\ncargo test --features fs_persist\n```\n\n**Note:** All telemetry code is properly feature-gated - when the `telemetry` feature is disabled, zero telemetry code is compiled into your binary. This ensures minimal binary size and zero runtime overhead for applications that don't need observability features.\n\n### Browser Usage (WASM)\n\n```javascript\n// From npm package\nimport init, { Database } from '@npiesco/absurder-sql';\n\n// Or from local build\n// import init, { Database } from './pkg/absurder_sql.js';\n\n// Initialize WASM\nawait init();\n\n// Create database - persists to IndexedDB\nconst db = await Database.newDatabase('myapp');\n\n// Execute SQL\nawait db.execute('CREATE TABLE users (id INT, name TEXT)');\nawait db.execute(\"INSERT INTO users VALUES (1, 'Alice')\");\nconst result = await db.execute('SELECT * FROM users');\n\n// Persist to IndexedDB\nawait db.sync();\n\n// Close\nawait db.close();\n```\n\n### Web Worker Support\n\nAbsurderSQL fully supports Web Workers for off-thread database operations, keeping your main thread responsive during heavy database work:\n\n```javascript\n// worker.js\nimport init, { Database } from '@npiesco/absurder-sql';\n\nself.onmessage = async function(e) {\n  // Initialize WASM in worker\n  await init();\n  \n  const db = await Database.newDatabase('worker_db.db');\n  \n  // Workers don't have localStorage for leader election\n  // Enable non-leader writes for worker context\n  db.allowNonLeaderWrites(true);\n  \n  // Perform database operations\n  await db.execute('CREATE TABLE data (id INTEGER, value TEXT)');\n  await db.execute(\"INSERT INTO data VALUES (1, 'processed in worker')\");\n  \n  // Sync to IndexedDB\n  await db.sync();\n  \n  const result = await db.execute('SELECT * FROM data');\n  await db.close();\n  \n  // Send results back to main thread\n  self.postMessage({ success: true, rows: result.rows });\n};\n```\n\n```javascript\n// main.js\nconst worker = new Worker('/worker.js', { type: 'module' });\n\nworker.onmessage = (e) =\u003e {\n  console.log('Worker result:', e.data);\n};\n\nworker.postMessage({ type: 'processData' });\n```\n\n**Key Points:**\n- IndexedDB access works in both Window and Worker contexts\n- Workers don't have `localStorage`, so use `db.allowNonLeaderWrites(true)` for single-worker scenarios\n- All database operations run off the main thread\n- Perfect for heavy data processing, imports, or background sync\n\n**Example:** See `examples/worker-example.html` for a complete working demo\n\n### Native/CLI Usage (Filesystem)\n\n```bash\n# Build the CLI tool\ncargo build --bin cli_query --features fs_persist --release\n\n# Create table\ncargo run --bin cli_query --features fs_persist -- \\\n  \"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)\"\n\n# Insert data\ncargo run --bin cli_query --features fs_persist -- \\\n  \"INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')\"\n\n# Query data\ncargo run --bin cli_query --features fs_persist -- \\\n  \"SELECT * FROM users\"\n\n# Special commands\ncargo run --bin cli_query --features fs_persist -- \".tables\"\ncargo run --bin cli_query --features fs_persist -- \".schema\"\n```\n\n**Data Location:** `./absurdersql_storage/\u003cdb_name\u003e/database.sqlite`\n\nSee [**docs/DUAL_MODE.md**](docs/DUAL_MODE.md) for complete tri-mode guide.\n\n### Mobile Usage (React Native)\n\nAbsurderSQL Mobile provides native SQLite for iOS and Android via UniFFI-generated bindings:\n\n```typescript\nimport { AbsurderDatabase, openDatabase } from 'absurder-sql-mobile';\n\n// Simple usage with high-level API\nconst db = await openDatabase({\n  name: 'myapp.db',\n  encryption: { key: 'my-secret-key' },  // Optional SQLCipher encryption\n  cacheSize: 20000,    // 20K pages (~80MB cache)\n  journalMode: 'WAL',  // Write-ahead logging\n});\n\n// Execute queries\nawait db.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');\nawait db.execute(\"INSERT INTO users VALUES (1, 'Alice')\");\n\n// Query with parameters\nconst result = await db.executeWithParams(\n  'SELECT * FROM users WHERE id = ?',\n  [1]\n);\nconsole.log(result.rows);        // [{ id: 1, name: 'Alice' }]\nconsole.log(result.lastInsertId); // Last inserted row ID\nconsole.log(result.executionTimeMs); // Query timing\n\n// Transactions\nawait db.transaction(async () =\u003e {\n  await db.execute(\"INSERT INTO users VALUES (2, 'Bob')\");\n  await db.execute(\"INSERT INTO users VALUES (3, 'Charlie')\");\n});\n\n// Streaming for large datasets\nfor await (const row of db.executeStream('SELECT * FROM large_table')) {\n  console.log(row);\n}\n\n// Export/Import\nawait db.exportToFile('/path/to/backup.db');\nawait db.importFromFile('/path/to/restore.db');\n\nawait db.close();\n```\n\n**Features:**\n- SQLCipher AES-256 encryption (iOS uses CommonCrypto, Android uses pre-built OpenSSL)\n- Prepared statements, batch operations, streaming queries\n- Full export/import for backup/restore\n- Type-safe from Rust to TypeScript via UniFFI\n\n**Setup:** See [**absurder-sql-mobile/README.md**](absurder-sql-mobile/README.md) for build instructions.\n\n#### Mobile Development Environment Setup\n\nBuilding mobile apps requires native toolchains and Rust cross-compilation targets. Follow these steps to set up your development environment:\n\n**Prerequisites:**\n- **Rust 1.85.0+** with iOS/Android targets\n- **Xcode** (iOS) with Command Line Tools\n- **Android Studio** (Android) with NDK\n\n**1. Install Rust iOS targets:**\n```bash\nrustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios\n```\n\n**2. Build iOS bindings with UniFFI:**\n```bash\ncd absurder-sql-mobile\nnpx uniffi-bindgen-react-native build ios --and-generate\n```\n\n**3. Install CocoaPods dependencies:**\n```bash\ncd your-react-native-app/ios \u0026\u0026 pod install \u0026\u0026 cd ..\n```\n\n**4. Run on iOS Simulator:**\n```bash\nnpx react-native run-ios --simulator=\"iPhone 16\"\n```\n\n**Android Setup:**\n```bash\n# Install Rust Android targets\nrustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android\n\n# Build Android bindings\ncd absurder-sql-mobile\nnpx uniffi-bindgen-react-native build android --and-generate\n\n# Run on Android Emulator\ncd your-react-native-app \u0026\u0026 npx react-native run-android\n```\n\n\u003e **Important:** The `uniffi-bindgen-react-native build` step compiles the Rust native library for the target platform and generates the TypeScript/Swift/Kotlin bindings. This must be run before `pod install` (iOS) or Gradle build (Android).\n\n## Performance Features\n\nAbsurderSQL includes several performance optimizations for high-throughput applications:\n\n### Transaction-Deferred Sync\n\nFilesystem sync operations are automatically deferred during transactions for massive performance improvements:\n\n```javascript\n// Without transactions: ~2883ms for 1000 inserts (sync after each)\nfor (let i = 0; i \u003c 1000; i++) {\n  await db.execute(`INSERT INTO data VALUES (${i}, 'value${i}')`);\n}\n\n// With transactions: \u003c1ms for 1000 inserts (sync only on COMMIT)\nawait db.execute('BEGIN TRANSACTION');\nfor (let i = 0; i \u003c 1000; i++) {\n  await db.execute(`INSERT INTO data VALUES (${i}, 'value${i}')`);\n}\nawait db.execute('COMMIT');  // Single sync here\n```\n\n**Performance:** 2278x speedup for bulk inserts (1034ms → 0.45ms for 100 inserts)\n\n### Batch Execution\n\nExecute multiple SQL statements in one call to reduce bridge overhead (especially important for React Native):\n\n```javascript\n// Native API (browser/WASM)\nconst statements = [\n  \"INSERT INTO users VALUES (1, 'Alice')\",\n  \"INSERT INTO users VALUES (2, 'Bob')\",\n  \"INSERT INTO users VALUES (3, 'Charlie')\"\n];\n\nawait db.executeBatch(statements);\n```\n\n**Performance:** Reduces N bridge calls to 1 call. For 5000 statements:\n- Individual calls: ~170ms bridge overhead (0.034ms × 5000)\n- Batch call: ~12ms total execution time\n\n### Prepared Statements (Native Only)\n\nEliminate SQL re-parsing overhead for repeated queries:\n\n```rust\n// Native/CLI usage only (not available in WASM)\nuse absurder_sql::{SqliteIndexedDB, DatabaseConfig, ColumnValue};\n\nlet mut db = SqliteIndexedDB::new(config).await?;\n\n// Prepare once\nlet mut stmt = db.prepare(\"INSERT INTO users VALUES (?, ?, ?)\")?;\n\n// Execute many times\nfor i in 1..=1000 {\n    stmt.execute(\u0026[\n        ColumnValue::Integer(i),\n        ColumnValue::Text(format!(\"User{}\", i)),\n        ColumnValue::Integer(25 + (i % 50)),\n    ]).await?;\n}\n\n// Cleanup\nstmt.finalize()?;\n```\n\n**Supported parameter styles:**\n- Positional: `?`\n- Numbered: `?1`, `?2` (can reuse same parameter)\n- Named: `:name`, `:id`\n\n**Performance:** 1.5-2x faster for repeated queries (eliminates SQL parsing on each execution)\n\n**Note:** PreparedStatement is currently available for native/CLI applications only. Browser/WASM support will be added in a future release.\n\n## SQLite WASM Integration\n\n### Architecture Overview\nThe library provides a robust SQLite implementation for WebAssembly environments using the `sqlite-wasm-rs` crate with precompiled features. This ensures stable, production-ready SQLite functionality without the hang issues that plagued earlier custom implementations.\n\n### Key Features\n- **Full SQLite C API Support**: Complete implementation of `sqlite3_prepare_v2`, `sqlite3_step`, `sqlite3_finalize`, and parameter binding\n- **Memory Safety**: Proper Rust `Drop` trait implementation for automatic cleanup of SQLite resources\n- **Async Operations**: All database operations are async-compatible for seamless integration with browser event loops\n- **Type Safety**: Comprehensive `ColumnValue` enum supporting all SQLite data types (NULL, INTEGER, REAL, TEXT, BLOB, BIGINT, DATE)\n- **JavaScript Interop**: Complete `wasm-bindgen` exports with `WasmColumnValue` wrapper for seamless JS integration\n- **Database Encryption** (Native): Optional SQLCipher integration with AES-256 encryption for secure data at rest (`--features encryption`)\n\n## Multi-Tab Coordination\n\nAbsurderSQL includes comprehensive multi-tab coordination for browser applications, ensuring data consistency across multiple tabs without conflicts.\n\n### Core Features\n- **Automatic Leader Election**: First tab becomes leader using localStorage coordination\n- **Write Guard**: Only the leader tab can execute write operations (INSERT, UPDATE, DELETE)\n- **BroadcastChannel Sync**: Automatic change notifications to all tabs\n- **Failover Support**: Automatic re-election when leader tab closes\n- **Zero Configuration**: Works out of the box, no setup required\n\n### Advanced Features\n- **Write Queuing**: Non-leaders can queue writes that forward to leader automatically\n- **Optimistic Updates**: Track pending writes for immediate UI feedback\n- **Coordination Metrics**: Monitor performance and coordination events\n\n### Quick Example\n\n```javascript\n// From npm package\nimport init, { Database } from '@npiesco/absurder-sql';\n\n// Or from local build\n// import init, { Database } from './pkg/absurder_sql.js';\nimport { MultiTabDatabase } from './examples/multi-tab-wrapper.js';\n\nawait init();\n\n// Create multi-tab database\nconst db = new MultiTabDatabase(Database, 'myapp.db', {\n  autoSync: true  // Auto-sync after writes\n});\nawait db.init();\n\n// Check leader status\nif (await db.isLeader()) {\n  // Only leader can write\n  await db.write(\"INSERT INTO users VALUES (1, 'Alice')\");\n}\n\n// All tabs can read\nconst result = await db.query(\"SELECT * FROM users\");\n\n// Listen for changes from other tabs\ndb.onRefresh(() =\u003e {\n  console.log('Data changed in another tab!');\n  // Refresh UI\n});\n```\n\n### Advanced Features\n\n```javascript\n// Write Queuing - Queue from any tab\nawait db.queueWrite(\"INSERT INTO logs VALUES (1, 'event')\");\nawait db.queueWriteWithTimeout(\"UPDATE data SET processed = 1\", 10000);\n\n// Optimistic Updates - Track pending writes\nawait db.enableOptimisticUpdates(true);\nconst writeId = await db.trackOptimisticWrite(\"INSERT INTO users...\");\nconst pendingCount = await db.getPendingWritesCount();\n\n// Coordination Metrics - Monitor performance\nawait db.enableCoordinationMetrics(true);\nawait db.recordLeadershipChange(true);\nawait db.recordNotificationLatency(15.5);\nconst metrics = JSON.parse(await db.getCoordinationMetrics());\n\n// Helper Methods\nawait db.waitForLeadership();  // Wait to become leader\nawait db.requestLeadership();   // Request leadership\nconst info = await db.getLeaderInfo();  // Get leader info\nawait db.allowNonLeaderWrites(true);  // Override for single-tab apps\n```\n\n### Live Demos\n- **[Multi-Tab Demo](examples/multi-tab-demo.html)** - Interactive task list with multi-tab sync\n- **[Vite App](examples/vite-app/)** - Production-ready multi-tab example\n- **[Complete Guide](docs/MULTI_TAB_GUIDE.md)** - Full documentation and patterns\n\n**Open the demo in multiple browser tabs to see coordination in action!**\n\n---\n\n## Demos \u0026 Examples\n\n### Vite Integration (`vite-app/`)\nModern web app example with **multi-tab coordination**:\n- ES modules with hot reload\n- Multi-tab leader election\n- Real-time sync across tabs\n- Leader/follower UI indicators\n- Production-ready build\n\n**[Full setup guide](examples/vite-app/README.md)**\n\n```bash\ncd examples/vite-app\nnpm install\nnpm run dev\n# Open in multiple tabs!\n```\n\n### SQL Demo (`sql_demo.js` / `sql_demo.html`)\nComprehensive SQL operations demo:\n- Table creation with foreign keys\n- INSERT operations with transactions\n- Complex SELECT queries with JOINs and aggregations\n- UPDATE and DELETE operations\n- Automatic IndexedDB persistence via `sync()` calls\n\n```bash\nnode examples/sql_demo.js\n```\n\n### Interactive Web Demo (`web_demo.html`)\nFull-featured interactive SQL interface:\n- Visual query editor\n- Real-time query execution and result display\n- Console output for debugging\n- Quick action buttons for common operations\n- Automatic sync after write operations\n\n**[Detailed walkthrough](examples/DEMO_GUIDE.md)**\n\n```bash\nnpm run serve\n# Open http://localhost:8080/examples/web_demo.html\n```\n\n## Performance Benchmarks\n\nAbsurderSQL consistently outperforms absurd-sql and raw IndexedDB across all operations.\n\n**[Full benchmark results and analysis](docs/BENCHMARK.md)**\n\n### Latest Results\n\n| Implementation | Insert | Read | Update | Delete |\n|---------------|--------|------|--------|--------|\n| **AbsurderSQL** 🏆 | **3.2ms** | **1.2ms** | **400μs** | **400μs** |\n| absurd-sql | 3.8ms | 2.1ms | 800μs | 700μs |\n| Raw IndexedDB | 24.1ms | 1.4ms | 14.1ms | 6.3ms |\n\n### Run Benchmarks\n\n```bash\nnpm run serve\n# Open http://localhost:8080/examples/benchmark.html\n```\n\n---\n\n## Comparison with absurd-sql\n\nAbsurderSQL is inspired by and builds upon the excellent work of [absurd-sql](https://github.com/jlongster/absurd-sql) by James Long, which pioneered SQLite-in-IndexedDB. Here's how they compare:\n\n### Similarities\nBoth projects share core concepts:\n- IndexedDB as persistent storage backend\n- Block/page-based storage (not single-file)\n- Full SQLite functionality in browser\n- Significantly better performance than raw IndexedDB\n\n### Key Architectural Differences\n\n| Feature | **absurd-sql** | **AbsurderSQL** |\n|---------|----------------|--------------|\n| **Engine** | sql.js (Emscripten) | sqlite-wasm-rs (Rust C API) |\n| **Language** | JavaScript | Rust/WASM/UniFFI |\n| **Platform** | **Browser only** | **Browser + Native + Mobile** |\n| **Mobile Support** | **Not supported** | iOS + Android via UniFFI |\n| **Storage** | Variable SQLite pages (8KB suggested) | Fixed 4KB blocks |\n| **Worker** | Optional (fallback mode works on main thread) | Optional (works on main thread) |\n| **SharedArrayBuffer** | Optional (faster with SAB, fallback without) | Not used |\n| **CORS Headers** | Optional (only if using SAB mode) | Not required |\n\n### Database Portability \u0026 Export/Import\n\n| Feature | **absurd-sql** | **AbsurderSQL** |\n|---------|----------------|--------------|\n| **Export to File** | **Not supported** | Full SQLite file export |\n| **Import from File** | **Not supported** | Standard SQLite import |\n| **Database Backup** | Locked in IndexedDB | Download as `.db` files |\n| **Data Migration** | Manual only | Automated export/import |\n| **File Portability** | No file access | Use with sqlite3, DB Browser |\n| **Multi-Device Sync** | Not possible | Export -\u003e share -\u003e import |\n| **Disaster Recovery** | No backups | Full backup/restore |\n\n### Multi-Tab Coordination\n\n| Feature | **absurd-sql** | **AbsurderSQL** |\n|---------|----------------|--------------|\n| **Coordination** | Throws errors | Coordinated with write queuing |\n| **Leadership** | No concept | Automatic election with failover |\n| **Follower Writes** | Not supported | Supported via `queueWrite()` |\n\n### Technical Implementation Highlights\n**absurd-sql:**\n- sql.js VFS interception for file operations\n- Two modes: SAB mode (fast) or FileOpsFallback (compatible)\n- SAB mode: Worker + SharedArrayBuffer for synchronous ops\n- Fallback mode: Works anywhere, \"one writer at a time\"\n\n**AbsurderSQL:**\n- Custom Rust IndexedDB VFS implementation\n- localStorage atomic coordination primitives\n- Block-level checksums and versioning (MVCC-style)\n- LRU cache (128 blocks default)\n- Full multi-tab write coordination (no errors)\n- Works everywhere (localStorage-based, no SAB)\n\n### Which Should You Choose?\n\n**Choose AbsurderSQL if you:**\n\n**[CRITICAL] Need database export/import (DATA PORTABILITY)**\n- Export databases as standard SQLite files users can download\n- Import databases from file uploads or shared files\n- Backup/restore workflows for disaster recovery\n- Migrate data between devices, browsers, or users\n- Open exported files with sqlite3 CLI, DB Browser, or any SQLite tool\n- Share databases as files (email, cloud storage, USB drives)\n- *Why this matters:* absurd-sql has **NO export/import** - your data is permanently locked in IndexedDB\n\n**[✓] Need dual-mode persistence (Browser + Native)**\n- Build web apps with IndexedDB storage\n- Query the same data from CLI/server using traditional `.db` files\n- Offline-first apps with optional server sync\n- Debug production data locally using standard SQLite tools\n- *Why this matters:* absurd-sql is **browser-only** - no CLI/server access to your data\n\n**[✓] Want zero deployment friction**\n- Deploy to GitHub Pages, Netlify, Vercel, or any CDN instantly\n- No server configuration or CORS header setup required\n- Works in iframes and embedded contexts\n- *Why this matters:* absurd-sql's SAB mode requires special HTTP headers (COEP/COOP) for best performance, though fallback mode works without them\n\n**[✓] Want flexible architecture**\n- Can run on main thread OR in Web Worker (your choice)\n- Simpler integration - no mandatory worker setup\n- Easy to add to existing apps without refactoring\n- *Why this matters:* absurd-sql's SAB mode requires a Web Worker, though fallback mode can run on main thread with performance trade-offs\n\n**[✓] Need multi-tab applications**\n- Multiple tabs can write data without coordination errors\n- Automatic conflict resolution with leader election\n- User can have multiple tabs open without issues (e.g., documentation in one tab, app in another)\n- *Why this matters:* absurd-sql throws errors if multiple tabs try to write simultaneously\n\n**[✓] Value data integrity**\n- Built-in checksums detect corruption\n- Crash consistency guarantees (committed data survives browser crashes)\n- MVCC-style versioning prevents race conditions\n- *Why this matters:* Protects against data loss from browser crashes, bugs, or unexpected shutdowns\n\n**[✓] Want better performance**\n- 16-50% faster than absurd-sql across all operations\n- LRU caching optimizes hot data access\n- Efficient 4KB block size balances memory and I/O\n- *Why this matters:* Faster queries = better user experience, especially on mobile devices\n\n**[✓] Need production-ready tooling**\n- Comprehensive test suite (WASM + Native + E2E tests)\n- Full TypeScript definitions\n- Active development and maintenance\n- *Why this matters:* Confidence in reliability, easier debugging, better IDE support\n\n**Choose absurd-sql if you:**\n\n**[!] Already invested in sql.js**\n- Have existing sql.js code you want to keep\n- Need to support very old browsers without WASM support (pre-2017)\n- Trade-off: Miss out on Rust's memory safety and performance\n\n**[!] Prefer pure JavaScript stack**\n- Don't want to deal with Rust/WASM compilation (though wasm-pack makes this trivial)\n- Want to read/modify source code in JavaScript\n- Trade-off: Slower performance, more deployment complexity\n\n**[!] Don't need multi-tab**\n- Single-tab application only\n- Users never have multiple tabs open\n- Trade-off: Limited scalability if requirements change later\n\n**Bottom Line:**\n- **AbsurderSQL** = Modern, fast, works everywhere, multi-tab ready, export/import support\n- **absurd-sql** = Proven, JavaScript-only, two modes (SAB or fallback), single-tab focus\n\n**[Detailed technical comparison in BENCHMARK.md](docs/BENCHMARK.md#comparison-with-absurd-sql)**\n\n---\n\n## Known Issues \u0026 Troubleshooting\n\n### Transient \"readonly database\" Error in Native Tests\n\n**Issue**: When running native tests with `cargo test --features fs_persist`, you may encounter a transient failure in `test_database_operations_across_threads`:\n\n```\ntest_database_operations_across_threads ... FAILED\n\nthread 'test_database_operations_across_threads' panicked at tests/send_safety_test.rs:74:10:\nFailed to insert: DatabaseError { \n  code: \"SQLITE_ERROR\", \n  message: \"attempt to write a readonly database\", \n  sql: Some(\"INSERT INTO test (value) VALUES ('test_value')\") \n}\n```\n\n**Root Cause**: Stale database files from previous test runs can persist in multiple storage directories. When tests attempt to reuse these files, SQLite may open them in read-only mode due to file permissions or lock state inconsistencies from interrupted test runs.\n\n**Storage Directories Created by Tests:**\n- `.absurdersql_fs` - Primary test storage directory\n- `test_storage` - Additional test database storage\n- `datasync_storage` - Multi-tab sync test storage\n- `absurdersql_storage` - Native persistence test storage\n\n**Solution**: Remove all stale storage directories before running tests:\n\n```bash\n# Clean up all stale test databases\nrm -rf .absurdersql_fs test_storage datasync_storage absurdersql_storage\n\n# Run tests fresh\ncargo test --features fs_persist\n```\n\n**Prevention**: The test suite creates unique run directories (e.g., `run_\u003cpid\u003e`) to isolate test runs, but interrupted tests (Ctrl+C, IDE stop) may not clean up properly. Consider adding this cleanup to your test scripts or CI/CD pipelines:\n\n```bash\n#!/bin/bash\n# test-with-cleanup.sh\nrm -rf .absurdersql_fs test_storage datasync_storage absurdersql_storage\ncargo test --features fs_persist \"$@\"\n```\n\n**Note**: This issue does not affect production usage - only test environments where multiple test runs accumulate stale databases. Production applications using `fs_persist` with proper database lifecycle management (open → use → close) are not affected.\n\n---\n\n## Documentation\n\n### User Guides\n- **[Export/Import Guide](docs/EXPORT_IMPORT.md)** - **DATABASE PORTABILITY** - Complete export/import reference (HUGE advantage over absurd-sql)\n- **[Tri-Mode Persistence Guide](docs/DUAL_MODE.md)** - Browser + Native + Mobile filesystem support\n- **[Multi-Tab Coordination Guide](docs/MULTI_TAB_GUIDE.md)** - Complete guide for multi-tab coordination\n- **[Transaction Support](docs/TRANSACTION_SUPPORT.md)** - Transaction handling and multi-tab transactions\n- **[Encryption Guide](docs/ENCRYPTION.md)** - SQLCipher AES-256 encryption setup\n- **[Benchmark Results](docs/BENCHMARK.md)** - Performance comparisons and metrics\n- **[Demo Guide](examples/DEMO_GUIDE.md)** - How to run the interactive demos\n- **[Vite App Example](examples/vite-app/README.md)** - Production-ready multi-tab application\n\n### Mobile (React Native)\n- **[Mobile Setup Guide](absurder-sql-mobile/README.md)** - Complete iOS and Android build instructions\n- **[Mobile Build Instructions](docs/mobile/INSTRUCTIONS.md)** - Detailed mobile build process\n- **[Mobile Benchmarks](docs/mobile/MOBILE_BENCHMARK.md)** - Performance comparisons on iOS/Android\n\n### Development \u0026 Quality\n- **[Coding Standards](docs/CODING_STANDARDS.md)** - Best practices, error handling, and testing requirements\n- **[Unwrap Safety Analysis](docs/REMAINING_UNWRAPS.md)** - Comprehensive analysis of remaining unwraps\n\n### Observability \u0026 Monitoring (Optional `--features telemetry`)\n- **[Alert Runbook](monitoring/RUNBOOK.md)** - Complete debugging and remediation procedures for all alerts\n- **[DevTools Extension](browser-extension/README.md)** - Browser extension features and architecture guide\n- **[DevTools Installation](browser-extension/INSTALLATION.md)** - Step-by-step installation for Chrome/Firefox\n\n## External Dependencies\n\n### Rust Dependencies\n\n#### Core Dependencies (Always Included)\n- **sqlite-wasm-rs**: Production-ready SQLite WASM bindings with precompiled features\n- **rusqlite**: Primary SQLite interface for native Rust builds, providing safe bindings to SQLite C library\n- **wasm-bindgen**: Facilitates communication between Rust and JavaScript in WASM context\n- **js-sys**: Provides bindings to JavaScript's built-in objects and functions\n- **web-sys**: Offers bindings to Web APIs including IndexedDB\n- **serde**: Handles serialization/deserialization for data exchange\n- **tokio**: Provides async runtime support for handling asynchronous operations\n\n#### Optional Dependencies (Feature-Gated)\n\n**Telemetry** (enabled with `--features telemetry`):\n- **prometheus**: Metrics collection and exposition\n- **opentelemetry**: Distributed tracing framework\n- **opentelemetry_sdk**: OpenTelemetry SDK implementation\n- **opentelemetry-prometheus**: Prometheus exporter for OpenTelemetry\n- **opentelemetry-otlp** (native only): OTLP exporter for sending traces to collectors\n\nThese dependencies are completely optional - when the `telemetry` feature is not enabled, zero telemetry code is compiled and none of these crates are included in your binary.\n\n### JavaScript Dependencies\n- **Bootstrap 5.1.3**: UI framework for responsive design and component styling\n- **Feather Icons**: Icon library for user interface elements\n\n### Browser APIs\n- **IndexedDB**: Primary storage API for persistent data storage\n- **WebAssembly**: Runtime environment for executing the compiled Rust code\n- **Fetch API**: Used for loading WASM modules and handling HTTP requests\n\n### Development Tools\n- **wasm-pack**: Build tool for generating WASM packages with JavaScript bindings\n- **Node.js 18+**: Required for development tooling and testing infrastructure\n- **Rust 1.85.0+**: Compiler targeting the 2024 edition for latest language features\n\nThe library is designed to work entirely in the browser environment without requiring any server-side components, making it suitable for offline-first applications and client-side data processing scenarios.\n\n## License\n\nAbsurderSQL is licensed under the **GNU Affero General Public License v3.0 (AGPL-3.0)**.\n\nThis is a strong copyleft license that requires:\n- **Source code disclosure**: Any modifications must be shared under AGPL-3.0\n- **Network copyleft**: If you run modified code as a web service, you must provide source to users accessing it over the network\n- **Patent protection**: Includes patent grant provisions\n- **Freedom to share**: Users can redistribute and modify the software\n\nSee [LICENSE.md](LICENSE.md) for the full license text.\n\n**Why AGPL-3.0?** This license ensures that improvements to AbsurderSQL remain open source and benefit the entire community, even when used in cloud/SaaS environments.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnpiesco%2Fabsurder-sql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnpiesco%2Fabsurder-sql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnpiesco%2Fabsurder-sql/lists"}