npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alexbruf/turso-level

v0.1.0

Published

An abstract-level database backed by Turso / libSQL

Readme

turso-level

An abstract-level database backed by Turso / libSQL.

Use any library from the level ecosystem on any serverless platform — Vercel, Netlify, Cloudflare Workers, Fly.io, Railway, or your own server.

📌 New to abstract-level? Head over to the Level FAQ.

Tests abstract-level License

Install

Node.js:

npm install @alexbruf/turso-level @libsql/client

Edge runtimes (Cloudflare Workers, Vercel Edge, Netlify Edge):

npm install @alexbruf/turso-level @tursodatabase/serverless

Usage

Node.js

import { TursoLevel } from '@alexbruf/turso-level'
import { createClient } from '@libsql/client'

const client = createClient({
  url: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
})

const db = new TursoLevel({ client })

await db.put('hello', 'world')
const value = await db.get('hello') // 'world'

for await (const [key, value] of db.iterator({ gte: 'a', lte: 'z' })) {
  console.log(key, value)
}

Edge runtimes (Cloudflare Workers, Vercel Edge, etc.)

import { TursoLevel } from '@alexbruf/turso-level'
import { createClient } from '@tursodatabase/serverless/compat'

const client = createClient({
  url: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
})

const db = new TursoLevel({ client })

Local development (SQLite file)

import { TursoLevel } from '@alexbruf/turso-level'
import { createClient } from '@libsql/client'

const client = createClient({ url: 'file:local.db' })
const db = new TursoLevel({ client })

Embedded replicas (Node.js — Fly.io, Railway, VPS)

Reads are local (microseconds). Writes go to the remote primary and sync back.

import { TursoLevel } from '@alexbruf/turso-level'
import { createClient } from '@libsql/client'

const client = createClient({
  url: 'file:replica.db',
  syncUrl: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
  syncInterval: 60,
})

const db = new TursoLevel({ client })

With TinaCMS

// tina/database.ts — Node.js / serverless (Vercel, Netlify, etc.)
import { TursoLevel } from '@alexbruf/turso-level'
import { createClient } from '@libsql/client'
import { createDatabase } from '@tinacms/datalayer'
import { GitHubProvider } from 'tinacms-gitprovider-github'

const client = createClient({
  url: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
})

export const database = createDatabase({
  level: new TursoLevel({ client }),
  gitProvider: new GitHubProvider({
    owner: process.env.GITHUB_OWNER,
    repo: process.env.GITHUB_REPO,
    token: process.env.GITHUB_PERSONAL_ACCESS_TOKEN,
    branch: process.env.GITHUB_BRANCH,
  }),
})

Setup

Creating a Turso database

# Install CLI
brew install tursodatabase/tap/turso

# Auth
turso auth login

# Create database
turso db create my-db

# Get connection details
turso db show my-db --url
turso db tokens create my-db

Set environment variables:

TURSO_DATABASE_URL=libsql://my-db-yourorg.turso.io
TURSO_AUTH_TOKEN=eyJ...

Table creation

The default createTable: true runs CREATE TABLE IF NOT EXISTS on open — no migrations needed for development.

For production, create the table explicitly:

turso db shell MY_DB \
  "CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID;"

Then pass createTable: false:

const db = new TursoLevel({ client, createTable: false })

Namespace (shared databases)

Use namespace to isolate this adapter's table when sharing a database:

const db = new TursoLevel({ client, namespace: 'tina' })
// → uses table "tina_kv" instead of "kv"

Which package to use?

| Runtime | Package | Import | |---------|---------|--------| | Node.js, Bun, Deno | @libsql/client | @libsql/client | | Cloudflare Workers, Vercel Edge, Netlify Edge | @tursodatabase/serverless | @tursodatabase/serverless/compat |

Both expose the same createClient() API — the adapter works identically with either.

API

new TursoLevel(options)

| Option | Type | Default | Description | |--------|------|---------|-------------| | client | Client | required | A @libsql/client instance from createClient() | | namespace | string | '' | Table name prefix. '' → table kv; 'tina' → table tina_kv | | createTable | boolean | true | Run CREATE TABLE IF NOT EXISTS on open |

All other options are forwarded to abstract-level.

TursoLevel inherits the full abstract-level API: put, get, del, getMany, batch, iterator, keys, values, clear, sublevel, and more.

How it works

Turso is libSQL (a SQLite fork) as a managed service. Entries are stored in a two-column table:

CREATE TABLE kv (
  key   TEXT PRIMARY KEY,
  value TEXT NOT NULL
) WITHOUT ROWID;

WITHOUT ROWID keeps the B-tree compact — the primary key IS the data, so there's no rowid indirection overhead.

Iteration uses cursor-based pagination. Since libSQL's HTTP protocol is stateless, there's no persistent server-side cursor. The iterator fetches rows in pages of 100, using WHERE key > lastKey to advance between pages.

Batches use libSQL's client.batch() with 'write' mode, which executes all statements as a single atomic transaction.

Limitations

  • No snapshot isolation — iterators read live data. Declared via supports.snapshots = false.
  • No seek() — repositioning an open iterator is not implemented.
  • UTF-8 keys and values only — libSQL TEXT columns only.

Tests

876 tests pass — the full abstract-level compliance suite runs against an in-memory libSQL database (no Turso account needed to run tests).

bun test

License

Apache-2.0