Skip to content

feat(db): support Drizzle's casing option in void/db and void db - #494

Merged
Brooooooklyn merged 4 commits into
mainfrom
feat/db-casing
Oct 19, 2026
Merged

Brooooooklyn merged 4 commits into
mainfrom
feat/db-casing

Conversation

@Brooooooklyn

Copy link
Copy Markdown
Member

Fixes #466

What

// void.config.ts
database: 'pg'                                     // unchanged shorthand
database: { dialect: 'pg', casing: 'snake_case' }  // new object form
database: { casing: 'snake_case' }                 // D1 (default dialect)

With casing: 'snake_case', a column declared without a name (createdAt: timestamp()) is stored as created_at, both in void/db queries and in what void db generate writes.

database.casing ──► runtime void/db (D1, pg, mysql: db, createDb, createPrimaryDb)
                ├─► void db seed
                └─► .void/drizzle.config.json "casing" → void db generate / push / deploy drift check

Design

  • Why the object form: all database options stay under one key, and the string shorthand keeps working. dialect defaults to "sqlite" (D1).
  • Validation: unknown keys, a bad dialect or a bad casing each give a clear config error. schema.json accepts both forms.
  • One way to read it: every reader of database goes through getDatabaseDialect / getDatabaseCasing. That covers application analysis (deploy, Hyperdrive, manifest dialect), the CLI (db, gen, init, wrapper), nitro, routing, the drizzle plugin and the framework plugin. void init keeps the casing when it changes the dialect.
  • No casing means no change: without casing, the generated void/db module and the drizzle-kit config are byte-identical to main. This was checked in all 12 dialect × schema × forced-virtual combinations.
  • Introspection (drizzle-kit's separate introspect.casing) is not touched.
  • Auth: the built-in auth tables name every column explicitly, so casing doesn't change them. A real sign-up worked with snake_case on.

Tests

Area Test
Runtime, real queries db-casing.test.ts: D1 (Miniflare, inside a request and outside it via createPrimaryDb), PGlite, and fake MySQL hit snake_case columns
drizzle-kit real drizzle-kit generate writes created_at; config writer emits casing
Plugins plugin-vite-environment.test.ts: Pages, class A (TanStack Start) and class B (SvelteKit) apps read casing from the config
Config / init / seed / prepare object-form parsing and errors; init keeps casing; seed uses casing; void prepare agrees with the plugin on db.d.ts
  • On main's source, 36 of these tests fail; with the change, all 482 pass.
  • Undoing each wiring point fails at least one test.
  • check:sdk (12/12), check:platform (7/7), vp fmt --check, vp lint, and 38 db/deploy/config/inference unit files (642 tests) all pass.
  • A scratch app (dev, build + preview, void db generate/migrate/seed/push, deploy drift check) showed snake_case columns in D1 (PRAGMA table_info).

Docs: docs/guide/database.md (Column casing) and docs/reference/config.md.

🤖 Generated with Claude Code

`database` in the Void config now also takes an object,
`{ dialect?: 'sqlite' | 'pg' | 'mysql', casing?: 'snake_case' | 'camelCase' }`.
The string shorthand (`'pg'`, `'mysql'`) is unchanged.

`casing` is passed to every Drizzle instance on the app schema (the
runtime `void/db` module for D1, PostgreSQL and MySQL, and `void db
seed`) and to the drizzle-kit config that `void db generate`, `push` and
the deploy drift check use, so a schema written for `snake_case` gets
snake_case columns from both. Without `casing`, the generated module and
drizzle-kit config are unchanged.

Every reader of `database` goes through getDatabaseDialect or the new
getDatabaseCasing, `void init` keeps the casing when it changes the
dialect, and schema.json accepts the object form. Built-in auth tables
name their columns explicitly, so they are not affected.

Fixes #466

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T10:05:26.250445Z e123ca4 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e467dad055

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/void/src/cli/init.ts
Choosing "No database" treated `database: { casing: 'snake_case' }` as
already D1 and left it in place, although casing alone still makes Void
serve `void/db`. Remove the whole `database` field whenever it is set,
as main did for `'pg'` and `'mysql'`. Switching to D1 still keeps the
casing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member Author

@codex review

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://feat-db-casing-void-cloud.voidzero-docs.workers.dev (commit e123ca4)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://98b01d6c-void-cloud.voidzero-docs.workers.dev e123ca4 2026-10-19T10:02:20.159Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://77f56d0f-void-cloud.voidzero-docs.workers.dev cd7a2b4 2026-10-19T09:54:49.720Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://70a5b8ed-void-cloud.voidzero-docs.workers.dev 5d289b2 2026-10-19T09:47:35.065Z Visit the dashboard ↗

Comment thread packages/void/src/cli/db.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d289b2817

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/void/src/plugin-framework.ts
…ng is set

A D1 app's installed packages kept their own void/db, which never gets
database.casing. Inline them like PostgreSQL and MySQL apps when casing
is configured, so they share the app's virtual module.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd7a2b4b69

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/void/src/plugin-framework.ts
…asing is set

A D1 build keeps Kit's output, so installed packages that import void
stayed external and loaded their own void/db without database.casing.
Bundle them when casing is set, as the dev server now inlines them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: e123ca43a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Brooooooklyn
Brooooooklyn merged commit 293ea34 into main Oct 19, 2026
20 checks passed
@Brooooooklyn
Brooooooklyn deleted the feat/db-casing branch October 19, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

void/db: support Drizzle's casing option

1 participant