Using with Turso

This page covers the practical steps for using Nanoka with Turso/libSQL in a Cloudflare Worker. For the full adapter API reference, see /api/adapters.

Install

pnpm add @libsql/client

Setup

Create the Turso client inside the fetch handler so each request gets a fresh connection, then pass it to tursoAdapter:

import { nanoka } from '@nanokajs/core'
import { tursoAdapter } from '@nanokajs/core/turso'
import { createClient } from '@libsql/client'
import { User } from './models/user'

export interface Env {
  TURSO_URL: string
  TURSO_AUTH_TOKEN: string
}

export default {
  async fetch(req: Request, env: Env, ctx: ExecutionContext) {
    const client = createClient({
      url: env.TURSO_URL,
      authToken: env.TURSO_AUTH_TOKEN,
    })
    const adapter = tursoAdapter(client)
    const app = nanoka(adapter)
    app.model(User)
    // routes...
    return app.fetch(req, env, ctx)
  },
}

Secrets

Store credentials as Wrangler secrets, never in source code or wrangler.jsonc:

wrangler secret put TURSO_URL
wrangler secret put TURSO_AUTH_TOKEN

For local development, add them to .dev.vars (keep this file in .gitignore):

TURSO_URL=libsql://your-db.turso.io
TURSO_AUTH_TOKEN=your-token

Local Development

Use a local SQLite file during development to avoid needing a live Turso database:

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

Or set TURSO_URL=file:local.db in .dev.vars and leave TURSO_AUTH_TOKEN empty. Apply migrations to the local file:

npx drizzle-kit migrate

Migrations for Turso

Update drizzle.config.ts to use the turso dialect:

import { defineConfig } from 'drizzle-kit'

export default defineConfig({
  dialect: 'turso',
  schema: './drizzle/schema.ts',
  out: './drizzle/migrations',
  dbCredentials: {
    url: process.env.TURSO_URL!,
    authToken: process.env.TURSO_AUTH_TOKEN,
  },
})

Apply migrations:

npx drizzle-kit migrate

Switching from D1 to Turso

The following changes are required when switching an existing D1-based app to Turso:

1. Add dependency:

pnpm add @libsql/client

2. Update import in worker:

- import { d1Adapter } from '@nanokajs/core'
+ import { tursoAdapter } from '@nanokajs/core/turso'
+ import { createClient } from '@libsql/client'

3. Update env interface:

- export interface Env {
-   DB: D1Database
- }
+ export interface Env {
+   TURSO_URL: string
+   TURSO_AUTH_TOKEN: string
+ }

4. Update adapter initialization:

- const app = nanoka(d1Adapter(env.DB))
+ const client = createClient({ url: env.TURSO_URL, authToken: env.TURSO_AUTH_TOKEN })
+ const app = nanoka(tursoAdapter(client))

5. wrangler.jsonc: Remove the d1_databases binding. The Turso credentials are managed as secrets and do not appear in wrangler.jsonc.

6. drizzle.config.ts: Change dialect from 'sqlite' to 'turso' and add dbCredentials.

7. Migration command: Replace wrangler d1 migrations apply with drizzle-kit migrate.