npm package: @sedrino/db-schema
Description: Migration-first schema planning for AI-authored SQLite/libSQL databases.
Latest version: 0.1.6

# @sedrino/db-schema

Migration-first schema planning for AI-authored SQLite/libSQL databases.

This package is aimed at a workflow where:

1. AI or humans author migrations in a deterministic TypeScript DSL
2. the planner materializes the next schema snapshot JSON
3. the compiler emits generated artifacts such as Drizzle schema code

## Current scope

The first version focuses on the planning layer:

- versioned schema document types
- migration DSL with deterministic operation recording
- schema materialization from migration history
- rebuild-aware SQLite migration emission for supported table-shape changes
- Drizzle source generation for a narrow SQLite + Temporal-aware subset
- inferred Drizzle soft-relations generation from foreign keys
- a libSQL-compatible apply runner with migration/state metadata tables
- a Bun-first CLI for planning migrations, applying them, and emitting schema artifacts

## Install

```bash
bun add @sedrino/db-schema
```

The CLI is Bun-first. If you want to run `sedrino-db`, make sure `bun` is available on `PATH`.

## Example

```ts
import { compileSchemaToDrizzle, createMigration, planMigration } from "@sedrino/db-schema";

const migration = createMigration(
  {
    id: "2026-04-08-001-create-account",
    name: "Create account table",
  },
  (m) => {
    m.createTable("account", (t) => {
      t.id("accountId", { prefix: "acct" });
      t.string("name").required();
      t.temporalInstant("createdAt").required().defaultNow();
    });
  },
);

const plan = planMigration({ migration });
const drizzleSource = compileSchemaToDrizzle(plan.nextSchema);
```

## Supported migration operations

- create, drop, and rename tables
- add, drop, rename, and alter fields
- add and drop indexes
- add and drop unique indexes

The builder also supports higher-level relationship helpers:

- `belongsTo("table", ...)` for indexed foreign keys
- `createJunctionTable(...)` for many-to-many join tables with composite uniqueness and inferred `through(...)` relations

For SQLite safety, field adds, drops, and supported field alterations are emitted as table rebuilds.
Unsafe cases still produce planner warnings and `migrate apply` will refuse to run them.

When a rebuild needs help populating data, the preferred API is higher-level transform helpers:

```ts
import { transforms } from "@sedrino/db-schema";

m.alterTable("account", (t) => {
  t.string("slug")
    .required()
    .backfill(transforms.slugFrom("name"));

  t.alterField("createdAt", (f) => {
    f.temporalInstant().using(transforms.epochMsFromIsoString("createdAt"));
  });
});
```

Raw `backfillSql(...)` and `usingSql(...)` are still available as escape hatches.

Relationship helpers look like:

```ts
m.createTable("contact", (t) => {
  t.id("contactId", { prefix: "ct" });
  t.belongsTo("account", {
    required: true,
    onDelete: "cascade",
  });
});

m.createJunctionTable("userGroupMembership", {
  left: { table: "user" },
  right: { table: "group" },
});
```

Typed JSON fields are also supported. The second `json(...)` argument is a
TypeScript type string that is carried into generated Drizzle code via
`.$type<...>()`:

```ts
m.createTable("account", (t) => {
  t.id("accountId", { prefix: "acct" });
  t.string("name").required();
  t.json("metadata", "{ source?: string; score?: number; tags?: string[] }");
});
```

## Docs

- `docs/index.md`
- `docs/schema-document.md`
- `docs/migrations.md`
- `docs/planning-and-apply.md`
- `docs/expressions-and-transforms.md`
- `docs/relations.md`
- `docs/cli.md`

## CLI

```bash
sedrino-db migrate create create-account --dir db
sedrino-db migrate plan --dir db
sedrino-db migrate apply --dir db --url file:./local.db
sedrino-db migrate validate --dir db
sedrino-db migrate status --dir db --url file:./local.db
sedrino-db schema print --dir db
sedrino-db schema drizzle --dir db --out db/schema/schema.generated.ts
```