@objectstack/driver-turso
v3.3.1
Published
Turso/libSQL Driver for ObjectStack — Edge-first SQLite with embedded replicas and multi-tenancy
Maintainers
Readme
@objectstack/driver-turso
Turso/libSQL driver for ObjectStack — edge-first SQLite with embedded replicas, cloud-only remote mode, and database-per-tenant multi-tenancy.
Architecture
TursoDriver implements a dual-transport architecture:
- Local/Replica modes: Extends
SqlDriverfrom@objectstack/driver-sql. All CRUD, schema, filtering, aggregation, window functions, introspection, and transactions are inherited via Knex + better-sqlite3. - Remote mode: Delegates all operations to
RemoteTransportwhich uses@libsql/clientSDK directly (HTTP/WebSocket). No local SQLite or Knex dependency needed.
TursoDriver extends SqlDriver (dual transport)
├── Transport: local/replica (via Knex + better-sqlite3)
│ ├── Inherited: find, findOne, create, update, delete, count, upsert
│ ├── Inherited: bulkCreate, bulkUpdate, bulkDelete, updateMany, deleteMany
│ ├── Inherited: syncSchema, dropTable, introspectSchema
│ ├── Inherited: aggregate, distinct, findWithWindowFunctions
│ ├── Inherited: beginTransaction, commit, rollback
│ └── Inherited: applyFilters (MongoDB-style + array-style)
├── Transport: remote (via @libsql/client)
│ ├── RemoteTransport: find, findOne, create, update, delete, count, upsert
│ ├── RemoteTransport: bulkCreate, bulkUpdate, bulkDelete, updateMany, deleteMany
│ ├── RemoteTransport: syncSchema, dropTable
│ ├── RemoteTransport: beginTransaction, commit, rollback
│ └── RemoteTransport: execute (raw SQL)
├── Override: name, version, supports (Turso-specific capabilities)
├── Override: connect / disconnect (transport-aware lifecycle)
├── Added: transportMode ('local' | 'replica' | 'remote')
├── Added: sync() — Embedded replica sync via @libsql/client
├── Added: Multi-tenant router with TTL cache
└── Added: TursoDriverConfig (url, authToken, syncUrl, mode, client)Installation
pnpm add @objectstack/driver-tursoConnection Modes
Local File (Embedded SQLite)
import { TursoDriver } from '@objectstack/driver-turso';
const driver = new TursoDriver({
url: 'file:./data/app.db',
});
await driver.connect();In-Memory (Testing)
const driver = new TursoDriver({
url: ':memory:',
});
await driver.connect();Embedded Replica (Hybrid)
Local SQLite file + automatic sync from Turso cloud:
const driver = new TursoDriver({
url: 'file:./data/replica.db',
syncUrl: 'libsql://my-db-orgname.turso.io',
authToken: process.env.TURSO_AUTH_TOKEN,
sync: {
intervalSeconds: 60, // sync every 60 seconds
onConnect: true, // sync on initial connect
},
});
await driver.connect();
// Manual sync
await driver.sync();Remote (Cloud-Only)
Pure remote queries via @libsql/client — no local SQLite needed.
Ideal for Vercel, Cloudflare Workers, and other serverless/edge runtimes:
const driver = new TursoDriver({
url: 'libsql://my-db-orgname.turso.io',
authToken: process.env.TURSO_AUTH_TOKEN,
});
await driver.connect();
// All CRUD operations work the same as local mode
const users = await driver.find('users', { where: { active: true } });Auto-Detection
Transport mode is automatically detected from the URL:
| URL Pattern | Mode | Engine |
|:---|:---|:---|
| file:./data/app.db | local | Knex + better-sqlite3 |
| :memory: | local | Knex + better-sqlite3 |
| file:... + syncUrl | replica | Knex + @libsql/client sync |
| libsql://... | remote | @libsql/client only |
| https://... | remote | @libsql/client only |
You can also force a specific mode:
const driver = new TursoDriver({
url: 'libsql://my-db.turso.io',
authToken: process.env.TURSO_AUTH_TOKEN,
mode: 'remote', // Force remote mode
});Custom Client
Pass a pre-configured @libsql/client instance for advanced use cases
(custom caching, connection pooling, testing):
import { createClient } from '@libsql/client';
const client = createClient({
url: 'libsql://my-db.turso.io',
authToken: process.env.TURSO_AUTH_TOKEN,
});
const driver = new TursoDriver({
url: 'libsql://my-db.turso.io',
client, // Inject pre-configured client
});
await driver.connect();Multi-Tenant Routing
Database-per-tenant architecture with automatic driver caching:
import { createMultiTenantRouter } from '@objectstack/driver-turso';
const router = createMultiTenantRouter({
urlTemplate: 'file:./data/{tenant}.db',
clientCacheTTL: 300_000, // 5 minutes
onTenantCreate: async (tenantId) => {
console.log(`Provisioned database for tenant: ${tenantId}`);
},
});
// In a request handler:
const driver = await router.getDriverForTenant('acme');
const users = await driver.find('users', { where: { active: true } });
// Cleanup on shutdown
await router.destroyAll();Multi-Tenant with Embedded Replicas
Both urlTemplate and driverConfigOverrides.syncUrl support {tenant} placeholder interpolation:
const router = createMultiTenantRouter({
urlTemplate: 'file:./data/{tenant}-replica.db',
groupAuthToken: process.env.TURSO_GROUP_TOKEN,
driverConfigOverrides: {
syncUrl: 'libsql://{tenant}-myorg.turso.io',
sync: { intervalSeconds: 30 },
},
});Concurrency Safety
Concurrent getDriverForTenant() calls for the same tenant are deduplicated — only one driver is created, and all callers share the same instance.
Configuration
interface TursoDriverConfig {
/**
* Database URL.
* - file:./data/local.db → local mode
* - :memory: → local mode (ephemeral)
* - libsql://my-db.turso.io → remote mode
* - https://my-db.turso.io → remote mode
*/
url: string;
/** JWT auth token for the remote Turso database */
authToken?: string;
/**
* AES-256 encryption key for local database file.
* Only effective in local/replica modes.
*/
encryptionKey?: string;
/**
* Maximum concurrent requests to the remote database.
* Effective in replica and remote modes.
* Default: 20
*/
concurrency?: number;
/** Remote sync URL for embedded replica mode (libsql:// or https://) */
syncUrl?: string;
/** Sync configuration (requires syncUrl) */
sync?: {
intervalSeconds?: number; // Default: 60
onConnect?: boolean; // Default: true
};
/**
* Operation timeout in milliseconds for remote operations.
* Effective in replica and remote modes.
*/
timeout?: number;
/**
* Force a specific transport mode.
* If not set, mode is auto-detected from the URL.
*/
mode?: 'local' | 'replica' | 'remote';
/**
* Pre-configured @libsql/client instance.
* Useful for custom caching, connection pooling, or testing.
*/
client?: Client;
}Capabilities
TursoDriver declares enhanced capabilities beyond the base SqlDriver:
| Capability | SqlDriver | TursoDriver (local) | TursoDriver (remote) | |:---|:---:|:---:|:---:| | FTS5 Full-Text Search | ❌ | ✅ | ✅ | | JSON1 Query | ❌ | ✅ | ✅ | | Common Table Expressions | ❌ | ✅ | ✅ | | Savepoints | ❌ | ✅ | ✅ | | Indexes | ❌ | ✅ | ✅ | | Connection Pooling | ✅ | ❌ (concurrency limits) | ❌ | | Embedded Replica Sync | — | ✅ | — | | Multi-Tenant Routing | — | ✅ | ✅ | | Serverless/Edge | — | — | ✅ |
Plugin Registration
import tursoPlugin from '@objectstack/driver-turso';
// Via plugin system
await kernel.enablePlugin(tursoPlugin, {
url: 'file:./data/app.db',
});Testing
pnpm test # Run all testsTests run against in-memory SQLite (:memory:) — no external services required.
License
Apache-2.0 — Copyright (c) 2025 ObjectStack
