LibSQL Implementation
The LibSQL implementation uses the @libsql/client
library, providing support for both local SQLite files and remote LibSQL instances.
Installation
bash
npm install applesauce-sqlite @libsql/client
Basic Usage
NOTE: The LibsqlEventDatabase
implements the IAsyncEventDatabase
interface which means you MUST use the AsyncEventStore
instead of the normal EventStore
.
Local Database
js
import { AsyncEventStore } from "applesauce-core";
import { LibsqlEventDatabase } from "applesauce-sqlite/libsql";
// Create a local file-based database
const database = new LibsqlEventDatabase("file:./events.db");
// Create EventStore with SQLite backend
const eventStore = new AsyncEventStore(database);
// Initialize the database (required for LibSQL)
await database.initialize();
// Use as normal
eventStore.add(someNostrEvent);
Remote Database
js
import { AsyncEventStore } from "applesauce-core";
import { LibsqlEventDatabase } from "applesauce-sqlite/libsql";
// Connect to a remote LibSQL instance
const database = new LibsqlEventDatabase("libsql://your-database.turso.io");
// Create EventStore with SQLite backend
const eventStore = new AsyncEventStore(database);
// Initialize the database
await database.initialize();
// Use as normal
eventStore.add(someNostrEvent);
Options
The LibsqlEventDatabase
constructor accepts the following options:
js
const database = new LibsqlEventDatabase("file:./events.db", {
search: true, // Enable full-text search (default: false)
searchContentFormatter: customFormatter, // Custom search content formatter
});
Search Support
Enable full-text search using SQLite's FTS5 extension:
js
const database = new LibsqlEventDatabase("file:./events.db", {
search: true,
});
await database.initialize();
// Now you can search events
const results = await eventStore.getByFilters({
search: "bitcoin lightning",
});
Custom Search Formatter
Customize how content is indexed for search:
js
const database = new LibsqlEventDatabase("file:./events.db", {
search: true,
searchContentFormatter: (event) => {
// Extract searchable content from event
return event.content + " " + event.tags.map((t) => t[1]).join(" ");
},
});
await database.initialize();
Advanced Usage
Using with Existing Client
You can also use an existing LibSQL Client
instance:
js
import { createClient } from "@libsql/client";
import { LibsqlEventDatabase } from "applesauce-sqlite/libsql";
const client = createClient({
url: "libsql://your-database.turso.io",
authToken: "your-auth-token",
});
const database = new LibsqlEventDatabase(client, { search: true });
await database.initialize();
Async Operations
LibSQL operations are asynchronous, so you need to use await
:
js
// All database operations are async
await eventStore.add(someNostrEvent);
const event = await eventStore.getEvent(eventId);
const hasEvent = await eventStore.hasEvent(eventId);
Rebuilding Search Index
If you need to rebuild the search index:
js
await database.rebuildSearchIndex();
Closing the Database
Always close the database when done:
js
database.close();
Or use automatic cleanup with Symbol.dispose
:
js
{
const database = new LibsqlEventDatabase("file:./events.db");
await database.initialize();
// ... use database
} // Automatically closed when out of scope
Performance Considerations
- Remote support: Can connect to remote LibSQL instances
- Async operations: All operations are asynchronous
- Network latency: Remote databases have network overhead
- Local performance: Local file databases perform similarly to other implementations
Example: Complete Application
js
import { AsyncEventStore } from "applesauce-core";
import { ProfileModel, TimelineModel } from "applesauce-core/models";
import { LibsqlEventDatabase } from "applesauce-sqlite/libsql";
import { Relay } from "applesauce-relay";
// Create persistent event store with search
const database = new LibsqlEventDatabase("file:./my-app.db", {
search: true,
});
const eventStore = new AsyncEventStore(database);
// Initialize the database
await database.initialize();
// Connect to relay and store events
const relay = new Relay("wss://relay.example.com");
const subscription = relay.subscription([{ kinds: [0, 1] }]).subscribe(async (event) => {
await eventStore.add(event); // Automatically persisted
});
// Use models with persisted data
const profile = eventStore.model(ProfileModel, "pubkey...");
profile.subscribe(async (parsed) => {
console.log("Profile loaded from database:", parsed);
});
// Search functionality
const searchResults = await eventStore.getByFilters({
search: "bitcoin",
kinds: [1], // Only text notes
});
console.log(`Found ${searchResults.length} notes about bitcoin`);
Remote Database Configuration
Turso (LibSQL Cloud)
js
import { createClient } from "@libsql/client";
import { LibsqlEventDatabase } from "applesauce-sqlite/libsql";
const client = createClient({
url: "libsql://your-database.turso.io",
authToken: "your-auth-token",
});
const database = new LibsqlEventDatabase(client, { search: true });
await database.initialize();
Self-Hosted LibSQL
js
const database = new LibsqlEventDatabase("http://localhost:8080");
await database.initialize();
When to Use
Choose LibSQL when:
- You need remote database support
- You're using Turso or other LibSQL services
- You want to share data across multiple instances
- You need async database operations
- You're building distributed applications
- You want to leverage LibSQL-specific features