Reference
libSQL JavaScript and TypeScript Reference
The following runtime environments are known to be compatible:
- Node.js version 12 or later
- Deno
- CloudFlare Workers
- Netlify & Vercel Edge Functions
The JavaScript SDK comes with TypeScript bindings and supports environments where either language can be used. Both ESM and CJS modules are provided.
Installing
Begin by installing the @libsql/client
dependency in your project:
Initializing
Import createClient
to initialize a client that you can use to query your database:
If you’re using libsql locally or an sqlite file, you can ignore passing authToken
.
In-Memory Databases
libSQL supports connecting to in-memory databases for cases where you don’t require persistence:
import { createClient } from "@libsql/client";
const client = createClient({
url: ":memory:",
});
Local Development
You can work locally using an SQLite file and passing the path to createClient
:
import { createClient } from "@libsql/client";
const client = createClient({
url: "file:path/to/db-file.db",
authToken: "...",
});
The @libsql/client/web
does not support local file URLs.
Embedded Replicas
You can work with embedded replicas by passing your Turso Database URL to syncUrl
:
import { createClient } from "@libsql/client";
const client = createClient({
url: "file:path/to/db-file.db",
syncUrl: "libsql://[databaseName]-[organizationName].turso.io",
authToken: "...",
});
Embedded Replicas only works where you have access to the file system.
Manual Sync
The sync()
function allows you to sync manually the local database with the remote counterpart:
await client.sync();
Periodic Sync
You can automatically sync at intervals by configuring the syncInterval
(seconds) property when instantiating a new libSQL client:
import { createClient } from "@libsql/client";
const client = createClient({
url: "file:path/to/db-file.db",
syncUrl: "libsql://[databaseName]-[organizationName].turso.io",
syncInterval: 60,
authToken: "...",
});
Encryption
To enable encryption on a SQLite file, pass the encryptionKey
:
import { createClient } from "@libsql/client";
const db = createClient({
url: "file:encrypted.db",
encryptionKey: process.env.ENCRYPTION_KEY,
});
Encrypted databases appear as raw data and cannot be read as standard SQLite databases. You must use the libSQL client for any operations — learn more.
Response
Each method listed below returns a Promise<ResultSet>
:
Property | Type | Description |
---|---|---|
rows | Array<Row> | An array of Row objects containing the row values, empty for write operations |
columns | Array<string> | An array of strings with the names of the columns in the order they appear in each Row, empty for write operations |
rowsAffected | number | The number of rows affected by a write statement, 0 otherwise |
lastInsertRowid | bigint | undefined | The ID of a newly inserted row, or undefined if there is none for the statement |
Simple query
You can pass a string or object to execute()
to invoke a SQL statement:
Placeholders
libSQL supports the use of positional and named placeholders within SQL statements:
libSQL supports the same named placeholder characters as SQLite — :
, @
and $
.
Transaction Modes
Mode | SQLite command | Description |
---|---|---|
write | BEGIN IMMEDIATE | The transaction may execute statements that read and write data. Write transactions executed on a replica are forwarded to the primary instance, and can’t operate in parallel. |
read | BEGIN TRANSACTION READONLY | The transaction may only execute statements that read data (select). Read transactions can occur on replicas, and can operate in parallel with other read transactions. |
deferred | BEGIN DEFERRED | The transaction starts in read mode, then changes to write as soon as a write statement is executed. This mode change may fail if there is a write transaction currently executing on the primary. |
Batch Transactions
A batch consists of multiple SQL statements executed sequentially within an implicit transaction. The backend handles the transaction: success commits all changes, while any failure results in a full rollback with no modifications.
const result = await client.batch(
[
{
sql: "INSERT INTO users VALUES (?)",
args: ["Iku"],
},
{
sql: "INSERT INTO users VALUES (?)",
args: ["Iku 2"],
},
],
"write"
);
Interactive Transactions
Interactive transactions in SQLite ensure the consistency of a series of read and write operations within a transaction’s scope. These transactions give you control over when to commit or roll back changes, isolating them from other client activity.
Method | Description |
---|---|
execute() | Similar to execute() except within the context of the transaction |
commit() | Commits all write statements in the transaction |
rollback() | Rolls back the entire transaction |
close() | Immediately stops the transaction |
Interactive transactions in libSQL lock the database for writing until committed or rolled back, with a 5-second timeout. They can impact performance on high-latency or busy databases.
ATTACH
You can attach multiple databases to the current connection using the ATTACH
attachment:
import { createClient } from "@libsql/client";
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const txn = await db.transaction("read");
await txn.execute('ATTACH "<database-id>" AS attached');
const rs = await txn.execute("SELECT * FROM attached.users");
Make sure to allow ATTACH
and create a token
with the permission to attach a database — learn
more
Was this page helpful?