JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 572
  • Score
    100M100P100Q83607F
  • License MIT

Core database utilities and schema definition for btst

Package Exports

  • @btst/db

Readme

Better DB

Database utilities without the auth domainβ€”a focused fork of Better Auth's database layer.

Better DB gives you Better Auth's proven adapter pattern and CLI-driven schema generation, focused purely on database management.

Features

  • 🎯 Focused β€” Database utilities without auth complexity
  • πŸ”„ Upstream Syncable β€” Stays aligned with Better Auth updates
  • πŸ”§ Battle-tested β€” Built on Better Auth's proven architecture
  • πŸš€ Multi-ORM β€” Prisma, Drizzle, Kysely, MongoDB, and more
  • πŸ”Œ Extensible β€” Plugin system for custom tables
  • ⚑ CLI-driven β€” Generate schemas with a single command

Quick Start

# Install core and your preferred adapter
npm install @btst/db @btst/adapter-prisma
npm install -D @btst/cli

Define your schema:

// db.ts
import { defineDb } from "@btst/db";

export const db = defineDb({
  post: {
    modelName: "post",
    fields: {
      title: {
        type: "string",
        required: true,
      },
      content: {
        type: "string",
        required: true,
      },
      published: {
        type: "boolean",
        defaultValue: false,
      },
      authorId: {
        type: "string",
        required: true,
      },
      createdAt: {
        type: "date",
        defaultValue: () => new Date(),
      },
    },
  },
  author: {
    modelName: "author",
    fields: {
      name: {
        type: "string",
        required: true,
      },
      email: {
        type: "string",
        required: true,
        unique: true,
      },
    },
  },
});

export default db;

Generate and run migrations:

# Generate Prisma schema
npx btst generate --config=db.ts --orm=prisma --output=schema.prisma

# Or for Kysely (requires database connection)
DATABASE_URL=sqlite:./dev.db npx btst generate --config=db.ts --orm=kysely --output=migrations/schema.sql
# Or: npx btst generate --config=db.ts --orm=kysely --output=migrations/schema.sql --database-url=sqlite:./dev.db

# Run migrations
npx prisma migrate dev

Use in your app:

import { prismaAdapter } from "@btst/adapter-prisma";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();
const adapter = prismaAdapter(prisma)({});

// Create
await adapter.create({
  model: "post",
  data: { title: "Hello", content: "World", authorId: "1" },
});

// Query
const posts = await adapter.findMany({
  model: "post",
  where: [{ field: "published", value: true }],
});

CLI Commands

Initialize

npx btst init [--output=db.ts]

Generate

# Prisma
npx btst generate --config=db.ts --orm=prisma --output=schema.prisma

# Drizzle
npx btst generate --config=db.ts --orm=drizzle --output=src/db/schema.ts

# Kysely (requires database connection for introspection)
# Using DATABASE_URL environment variable
DATABASE_URL=sqlite:./dev.db npx btst generate --config=db.ts --orm=kysely --output=migrations/schema.sql

# Or using --database-url flag
npx btst generate --config=db.ts --orm=kysely --output=migrations/schema.sql --database-url=sqlite:./dev.db
npx btst generate --config=db.ts --orm=kysely --output=migrations/schema.sql --database-url=postgres://user:pass@localhost:5432/db

# By default, auth tables (User, Session, Account, Verification) are filtered out
# To include them, add --include-better-auth flag
npx btst generate --config=db.ts --orm=prisma --output=schema.prisma --include-better-auth

Migrate

# Kysely only - for Prisma/Drizzle use their native tools
# Using DATABASE_URL environment variable or --database-url param
DATABASE_URL=sqlite:./dev.db npx btst migrate --config=db.ts

# Or using --database-url flag
npx btst migrate --config=db.ts --database-url=sqlite:./dev.db
npx btst migrate --config=db.ts --database-url=postgres://user:pass@localhost:5432/db

# Generate SQL to file instead of running migrations
npx btst migrate --config=db.ts --output=migrations.sql --database-url=sqlite:./dev.db

# By default, auth tables (User, Session, Account, Verification) are filtered out
# To include them, add --include-better-auth flag
npx btst migrate --config=db.ts --output=migrations.sql --include-better-auth --database-url=sqlite:./dev.db

Field Types

defineDb({
  example: {
    modelName: "example",
    fields: {
      // Basic types
      textField: { type: "string" },
      numberField: { type: "number" },
      booleanField: { type: "boolean" },
      dateField: { type: "date" },
      jsonField: { type: "json" },
      
      // Required/Optional
      required: { type: "string", required: true },
      optional: { type: "string", required: false },
      
      // Unique
      uniqueField: { type: "string", unique: true },
      
      // Defaults
      active: { type: "boolean", defaultValue: false },
      createdAt: { type: "date", defaultValue: () => new Date() },
      
      // References
      userId: {
        type: "string",
        references: {
          model: "user",
          field: "id",
          onDelete: "cascade",
        },
      },
    },
  },
})

Adapter API

All adapters provide these methods:

// Create
adapter.create({ model: "post", data: {...} })

// Read
adapter.findOne({ model: "post", where: [...] })
adapter.findMany({ model: "post", where: [...], limit: 10 })
adapter.count({ model: "post", where: [...] })

// Update
adapter.update({ model: "post", where: [...], update: {...} })
adapter.updateMany({ model: "post", where: [...], update: {...} })

// Delete
adapter.delete({ model: "post", where: [...] })
adapter.deleteMany({ model: "post", where: [...] })

See Better Auth Adapter Guide for details.

Plugins

Extend your schema with reusable plugins:

import { defineDb } from "@btst/db";
import { todoPlugin } from "@btst/plugins";

export const db = defineDb({
  post: {
    modelName: "post",
    fields: {
      title: { type: "string", required: true },
    },
  },
}).use(todoPlugin);

Create custom plugins:

import { createDbPlugin } from "@btst/db";

export const tagsPlugin = createDbPlugin("tags", {
  tag: {
    modelName: "tag",
    fields: {
      name: {
        type: "string",
        required: true,
        unique: true,
      },
    },
  },
});

Available Adapters

npm install @btst/adapter-prisma    # Prisma
npm install @btst/adapter-drizzle   # Drizzle
npm install @btst/adapter-kysely    # Kysely
npm install @btst/adapter-memory    # Memory (testing)
npm install @btst/adapter-mongodb   # MongoDB

Relationship with Better Auth

Better DB is a thin wrapper around Better Auth's database layer:

What we keep:

  • βœ… All adapter implementations
  • βœ… CLI generation behavior
  • βœ… Field type system
  • βœ… Plugin architecture

What we exclude:

  • ❌ Auth tables (user, session, account)
  • ❌ OAuth configurations
  • ❌ Authentication middleware

Versioning: @btst/*@1.4.x tracks better-auth@1.4.x

Migration from Better Auth

Replace imports:

// Before
import { prismaAdapter } from "better-auth/adapters/prisma";

// After
import { prismaAdapter } from "@btst/adapter-prisma";

Replace config with schema:

// Before
export const auth = betterAuth({
  database: prismaClient,
  plugins: [...]
});

// After
export const db = defineDb({
  // your tables using Better Auth schema format
  post: {
    modelName: "post",
    fields: {
      title: { type: "string", required: true },
    },
  },
});

Update CLI:

# Before
npx @better-auth/cli generate

# After
npx btst generate

Examples

Blog Platform

import { defineDb } from "@btst/db";

export const db = defineDb({
  post: {
    modelName: "post",
    fields: {
      title: {
        type: "string",
        required: true,
      },
      slug: {
        type: "string",
        required: true,
        unique: true,
      },
      content: {
        type: "string",
        required: true,
      },
      published: {
        type: "boolean",
        defaultValue: false,
      },
      authorId: {
        type: "string",
        required: true,
        references: {
          model: "author",
          field: "id",
          onDelete: "cascade",
        },
      },
      createdAt: {
        type: "date",
        defaultValue: () => new Date(),
      },
    },
  },
  author: {
    modelName: "author",
    fields: {
      name: {
        type: "string",
        required: true,
      },
      email: {
        type: "string",
        required: true,
        unique: true,
      },
      bio: {
        type: "string",
        required: false,
      },
    },
  },
  category: {
    modelName: "category",
    fields: {
      name: {
        type: "string",
        required: true,
      },
      slug: {
        type: "string",
        required: true,
        unique: true,
      },
    },
  },
});

E-commerce

export const db = defineDb({
  product: {
    modelName: "product",
    fields: {
      name: {
        type: "string",
        required: true,
      },
      slug: {
        type: "string",
        required: true,
        unique: true,
      },
      price: {
        type: "number",
        required: true,
      },
      inventory: {
        type: "number",
        defaultValue: 0,
      },
      categoryId: {
        type: "string",
        required: false,
        references: {
          model: "category",
          field: "id",
          onDelete: "set null",
        },
      },
    },
  },
  order: {
    modelName: "order",
    fields: {
      orderNumber: {
        type: "string",
        required: true,
        unique: true,
      },
      customerId: {
        type: "string",
        required: true,
        references: {
          model: "customer",
          field: "id",
          onDelete: "cascade",
        },
      },
      status: {
        type: "string",
        required: true,
        defaultValue: "pending",
      },
      total: {
        type: "number",
        required: true,
      },
      createdAt: {
        type: "date",
        defaultValue: () => new Date(),
      },
    },
  },
  orderItem: {
    modelName: "order_item",
    fields: {
      orderId: {
        type: "string",
        required: true,
        references: {
          model: "order",
          field: "id",
          onDelete: "cascade",
        },
      },
      productId: {
        type: "string",
        required: true,
        references: {
          model: "product",
          field: "id",
          onDelete: "cascade",
        },
      },
      quantity: {
        type: "number",
        required: true,
      },
      price: {
        type: "number",
        required: true,
      },
    },
  },
});

Resources

License

MIT