Skip to content

[Drizzle ORM]: feat: Add getTableMetadata for JSON-serializable table introspection - #5773

Open
nbouvrette wants to merge 2 commits into
drizzle-team:mainfrom
nbouvrette:feat/get-table-metadata
Open

[Drizzle ORM]: feat: Add getTableMetadata for JSON-serializable table introspection#5773
nbouvrette wants to merge 2 commits into
drizzle-team:mainfrom
nbouvrette:feat/get-table-metadata

Conversation

@nbouvrette

Copy link
Copy Markdown

Summary

Adds a new dialect-agnostic public export to drizzle-orm:

import { getTableMetadata, type TableMetadata, type ColumnMetadata } from 'drizzle-orm'

const meta = getTableMetadata(usersTable)
// {
//   name: 'users',
//   schema: null,
//   baseName: 'users',
//   columns: {
//     id:   { name: 'id',   dataType: 'number', columnType: 'PgSerial', sqlType: 'serial', notNull: true, hasDefault: true,  primary: true,  isUnique: false, generated: null, generatedIdentity: null, enumValues: null },
//     name: { name: 'name', dataType: 'string', columnType: 'PgText',   sqlType: 'text',   notNull: true, hasDefault: false, primary: false, isUnique: false, generated: null, generatedIdentity: null, enumValues: null },
//   },
// }

getTableMetadata walks a Drizzle Table and produces a plain, JSON-serializable object containing the column properties that downstream tools care about: name, dataType, columnType, sqlType, notNull, hasDefault, primary, isUnique, generated, generatedIdentity, enumValues, plus dialect-specific extras when present (length, dimensions, size, textType, baseColumn for arrays — recursive).

Key properties:

  • One generic export, all four dialects (pg, mysql, sqlite, singlestore) — no per-dialect imports
  • Pure data: no functions, no SQL fragments, no Symbol-keyed properties — JSON.parse(JSON.stringify(meta)) deep-equals meta
  • Backward compatible: existing getTableConfig is untouched

Why

Today, validation extensions like drizzle-zod (and drizzle-valibot, drizzle-typebox, drizzle-arktype) require users to import the runtime Table object to derive a Zod schema. That import transitively pulls in pgTable, every column constructor, and the rest of drizzle-orm/pg-core into shared client bundles where Zod schemas are used (tRPC + React forms, etc.). Measured cost in a real Vite-built app: ~56 KB gzipped on first load.

Exposing the metadata as a plain object lets downstream packages (and any third-party codegen tool) operate on data alone — no need to import Table at runtime on the client. This is the foundation issue #941 has been waiting on: with this in place, a thin drizzle-zod companion entry that consumes TableMetadata directly becomes possible, and the runtime cost drops to a few KB. (Follow-up PRs in drizzle-kit and drizzle-zod can land independently; this PR stands on its own.)

The shape was chosen by reading what drizzle-zod, drizzle-valibot, drizzle-typebox, and drizzle-arktype all currently consume from Column instances — a strict superset of what each needs, and a strict subset of what getTableConfig returns. FK references, indexes, composite primary keys, checks, RLS, and policies are intentionally not included: none of the validation extensions consume them, and including dialect-specific extras would force the function to import per-dialect packages.

What this PR is NOT

  • Not a change to createInsertSchema / createSelectSchema in drizzle-zod
  • Not a CLI / codegen change in drizzle-kit
  • Not a deprecation of getTableConfig

It's a pure additive primitive that other packages can build on.

Test plan

  • 32 new unit tests across tests/get-table-metadata-{pg,mysql,sqlite,singlestore,serializable}.test.ts
  • Covers: basic shapes, schema-qualified tables, every primitive column dataType, notNull / hasDefault / primary / isUnique flags, dialect-specific extras (length, dimensions, size, textType), recursive array baseColumn, enumValues, generated / generatedIdentity
  • One cross-dialect serialization contract test: JSON.parse(JSON.stringify(getTableMetadata(t))) deep-equals the original (guarantees no functions, SQL, or Symbols leak through)
  • pnpm test in drizzle-orm/ is green: 599/599 tests pass, including exports.test.ts (no export-name conflicts)

Run locally with:

cd drizzle-orm
pnpm test -- get-table-metadata

… introspection

Adds a dialect-agnostic `getTableMetadata(table)` API to drizzle-orm that
extracts plain, JSON-serializable metadata from any Drizzle Table — column
name, dataType, columnType, sqlType, notNull, hasDefault, primary, isUnique,
generated/generatedIdentity, enumValues, plus dialect-specific extras
(length, dimensions, size, textType, baseColumn for arrays) when applicable.

The output is a pure-data object: no functions, SQL fragments, or
Symbol-keyed properties. This unblocks bundle-friendly schema-introspection
patterns for drizzle-zod / valibot / typebox / arktype, which today require
importing the runtime Table object (and transitively the full pg-core /
mysql-core / sqlite-core / singlestore-core runtimes) into client bundles.
See drizzle-team#941.

Works across all four dialects (pg, mysql, sqlite, singlestore) via a single
generic export. Existing `getTableConfig` is unchanged.

Tests: 32 new tests across four dialect-specific files plus a JSON
round-trip serialization contract test. Full drizzle-orm suite passes
(599/599).

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

Copy link
Copy Markdown
Author

@AndriiSherman @Sukairo-02 any chance you could consider this PR? its an highly voted issue and I'm happy to get it to the finish line with whatever feedback you can provide.

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.

1 participant