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

@contract-kit/provider-drizzle-turso

v0.1.4

Published

Drizzle ORM + Turso/libSQL provider for contract-kit - adds typed DbPort using drizzle-orm

Readme

@contract-kit/provider-drizzle-turso

Drizzle ORM + Turso/libSQL provider for Contract Kit. Adds a typed database port to your hexagonal application using Drizzle ORM with Turso's libSQL.

Features

  • 🎯 Factory-based: Create providers with your schema at the call site
  • 🔒 Type-safe: Full TypeScript inference from your Drizzle schema
  • 🌐 Turso-ready: Works with Turso cloud or local libSQL
  • 🏗️ Schema-agnostic: You control where your schema files live
  • 🔌 Clean separation: Runtime provider is separate from build-time CLI config

Installation

bun add @contract-kit/provider-drizzle-turso drizzle-orm @libsql/client

TypeScript Requirements

This package requires TypeScript 5.0 or higher for proper type inference.

Setup

1. Define your schema

Create your Drizzle schema file wherever makes sense for your app:

// src/db/schema.ts
import { sqliteTable, text } from "drizzle-orm/sqlite-core";

export const todos = sqliteTable("todos", {
  id: text("id").primaryKey(),
  title: text("title").notNull(),
  completed: text("completed").notNull().default("false"),
});

2. Configure Drizzle CLI (build-time)

Create drizzle.config.ts in your app root for the Drizzle CLI:

// drizzle.config.ts
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dialect: "sqlite",
  dbCredentials: {
    url: process.env.TURSO_DB_URL!,
  },
});

3. Create the provider (runtime)

Import your schema and create the provider:

// src/lib/providers/db.ts
import * as schema from "@/db/schema";
import { createDrizzleTursoProvider } from "@contract-kit/provider-drizzle-turso";

export const drizzleTursoProvider = createDrizzleTursoProvider({ schema });

4. Type your ports

Define your app's ports type:

// src/lib/ports.ts
import type { DbPort } from "@contract-kit/provider-drizzle-turso";
import * as schema from "@/db/schema";

export type AppPorts = {
  db: DbPort<typeof schema>;
  // other ports...
};

5. Wire it up in your server

// src/lib/app.ts
import { createServer } from "@contract-kit/server";
import { drizzleTursoProvider } from "./providers/db";

export const app = createServer({
  ports: {},
  providers: [drizzleTursoProvider],
  // ... other config
});

6. Use in your use cases

// src/application/todos/listTodos.ts
import { useCase } from "@/lib/useCase";
import * as schema from "@/db/schema";

export const listTodos = useCase
  .query("todos.list")
  .input(z.object({}))
  .output(z.array(z.object({ id: z.string(), title: z.string() })))
  .run(async ({ ctx }) => {
    const db = ctx.ports.db.db; // LibSQLDatabase<typeof schema> - fully typed!

    const rows = await db.select().from(schema.todos);
    return rows;
  });

Configuration

The provider reads configuration from environment variables with the TURSO_ prefix:

| Variable | Required | Description | |----------|----------|-------------| | TURSO_DB_URL | Yes | Turso/libSQL database URL (e.g., libsql://your-db.turso.io or file:local.db) | | TURSO_DB_AUTH_TOKEN | No | Turso auth token (required for cloud databases, optional for local) |

Example .env

# For Turso cloud
TURSO_DB_URL=libsql://my-app-db.turso.io
TURSO_DB_AUTH_TOKEN=eyJhbGciOiJFZERTQSIsInR5cCI...

# For local development
TURSO_DB_URL=file:local.db

Advanced Usage

Multiple databases

You can create multiple database providers with different port names:

import * as mainSchema from "@/db/schema";
import * as analyticsSchema from "@/db/analytics-schema";
import { createDrizzleTursoProvider } from "@contract-kit/provider-drizzle-turso";

export const mainDbProvider = createDrizzleTursoProvider({
  schema: mainSchema,
  portName: "db", // default
});

export const analyticsDbProvider = createDrizzleTursoProvider({
  schema: analyticsSchema,
  portName: "analyticsDb",
});

// Then in your ports type:
export type AppPorts = {
  db: DbPort<typeof mainSchema>;
  analyticsDb: DbPort<typeof analyticsSchema>;
};

Accessing the Drizzle instance

The DbPort exposes the typed Drizzle database instance:

import { eq } from "drizzle-orm";

const db = ctx.ports.db.db; // LibSQLDatabase<TSchema>

// All Drizzle operations are available:
await db.select().from(schema.todos);
await db.insert(schema.todos).values({ id: "1", title: "Hello" });
await db.update(schema.todos).set({ title: "Updated" }).where(eq(schema.todos.id, "1"));
await db.delete(schema.todos).where(eq(schema.todos.id, "1"));

// Transactions:
await db.transaction(async (tx) => {
  await tx.insert(schema.todos).values({ id: "1", title: "Todo 1" });
  await tx.insert(schema.todos).values({ id: "2", title: "Todo 2" });
});

// Access the underlying libSQL client for advanced operations:
const client = ctx.ports.db.client;
const result = await client.execute("SELECT * FROM todos WHERE id = ?", ["1"]);

Key Design Principles

Runtime vs. Build-time Separation

This provider follows a clean separation of concerns:

  • Build-time (Drizzle CLI): Configured via drizzle.config.ts

    • Used for generating migrations
    • Used for introspecting the database
    • Lives in your app repository
  • Runtime (Provider): Configured via factory function

    • Used for connecting to the database at runtime
    • Used for executing queries in your use cases
    • Gets the schema from your imports

Schema Location Independence

The provider does not care where your schema file lives. You:

  1. Define your schema file wherever makes sense (src/db/schema.ts, db/schema.ts, etc.)
  2. Import it in your app: import * as schema from "@/db/schema"
  3. Pass it to the factory: createDrizzleTursoProvider({ schema })

This keeps the provider flexible and your app in control of its structure.

API Reference

DbPort<TSchema>

The port interface exposed on ctx.ports.db:

interface DbPort<TSchema extends Record<string, any> = any> {
  db: LibSQLDatabase<TSchema>;
  client: Client;
}
  • db: The typed Drizzle database instance for ORM operations
  • client: The underlying libSQL client for advanced operations not covered by Drizzle

createDrizzleTursoProvider<TSchema>(options)

Factory function to create a Drizzle Turso provider.

Parameters:

  • options.schema (required): Your Drizzle schema object
  • options.portName (optional): Port name, defaults to "db"

Returns: A ServiceProvider that can be used with createServer

Example:

const provider = createDrizzleTursoProvider({
  schema: mySchema,
  portName: "db", // optional
});

License

MIT