This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
libsql-js is a Node.js/Bun/Deno native binding for libSQL that provides a better-sqlite3-compatible API. The project consists of:
- Rust native module (
src/lib.rs,src/auth.rs) - N-API bindings using napi-rs - JavaScript wrapper layers - Two APIs:
compat.js- Synchronous, better-sqlite3-compatible APIpromise.js- Async/Promise-based API
- TypeScript declarations - Generated from JS files via
tsc
The codebase uses a dual-API architecture:
-
Native Rust Layer (
src/lib.rs):- Wraps the async
libsqlcrate using Tokio runtime - Exports both sync and async N-API functions via napi-rs
- Implements
DatabaseandStatementstructs - Handles error conversion from libSQL errors to JavaScript errors (JSON-encoded)
- Manages authentication via
Authorizerinsrc/auth.rs
- Wraps the async
-
JavaScript Wrapper Layers:
compat.js- Calls*Syncfunctions from native module, blocks event looppromise.js- Calls async functions, returns Promises viaEnv::execute_tokio_future- Both wrap errors using
SqliteErrorclass (sqlite-error.js) - Both use
Authorizationmodule (auth.js) for table-level access control
Errors from Rust are JSON-encoded with structure:
{
"message": "error message",
"libsqlError": true,
"code": "SQLITE_ERROR",
"rawCode": 1
}JavaScript wrappers parse this and create SqliteError instances (except SQLITE_AUTH which preserves JSON, and SQLITE_NOTOPEN which becomes TypeError).
The library supports three connection modes:
- Local - File path or
:memory:databases - Remote - URLs starting with
http://,https://,libsql://, orwss:// - Embedded Replica - Local database with
syncUrloption for syncing with remote
LIBSQL_JS_DEV=1 npm run buildThis compiles:
- Rust native module via
napi build(targeting current platform) - TypeScript declarations via
tsc(fromcompat.jsandpromise.js)
The LIBSQL_JS_DEV=1 environment variable is required for local development.
npm run build:debugBuilds without optimizations for debugging.
npm run buildBuilds optimized release artifacts for the current platform.
Integration tests use the ava test runner and test both APIs:
# Run all integration tests (from root)
npm test
# From integration-tests directory
cd integration-tests
npm i
npm testIndividual test suites:
npm run test:sqlite- Tests sync API with better-sqlite3 comparisonnpm run test:libsql- Tests sync API with libsqlnpm run test:async- Tests promise APInpm run test:extensions- Tests extension loadingnpm run test:concurrency- Tests concurrent access
Tests require linking the local package:
export LIBSQL_JS_DEV=1
npm link
cd integration-tests
npm link libsqlThe .cargo/config.toml sets special linker flags for macOS to allow undefined symbols during linking:
rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]This is required for N-API modules on macOS.
The CI builds for multiple targets using Docker containers and cross-compilers. See .github/workflows/CI.yml for the build matrix, which includes:
- macOS (x64, ARM64)
- Linux GNU (x64, ARM64)
- Linux musl (x64, ARM64)
- Windows (x64)
src/lib.rs- Main Rust implementation with Database/Statement structssrc/auth.rs- Table-level authorization systemcompat.js- Synchronous API wrapperpromise.js- Promise-based API wrappersqlite-error.js- Error classauth.js- Authorization builder for JavaScriptCargo.toml- Rust dependencies (libsql, napi, tokio)package.json- Defines dual exports:.(compat) and./promise
TypeScript declarations are generated from JSDoc in the JavaScript files:
tscruns withemitDeclarationOnly: true- Outputs
compat.d.tsandpromise.d.ts index.d.tscontains native module type definitions
The library supports encryption at rest via libsql's encryption feature:
encryptionCipher- Cipher to use (passed to libSQL)encryptionKey- Key for local database encryptionremoteEncryptionKey- Key for remote database encryption