Skip to content

Codegen Plugin

This document covers practical usage of the optional codegen plugin.

  • Generates deterministic TypeScript row types from chkit schema definitions.
  • Optionally generates Zod schemas from the same definitions.
  • Optionally generates typed ingestion functions for inserting rows into ClickHouse tables.
  • Optionally generates a self-contained runtime migration module with all migration SQL inlined, for environments without filesystem access (e.g., Cloudflare Workers).

The plugin is designed so your existing chkit workflow can stay the same.

  • chkit generate integration:
    • After a successful migration/snapshot generate, codegen runs automatically by default (runOnGenerate: true).
    • Result: migration artifacts and generated types stay in sync in normal dev flow.
  • chkit check integration:
    • check evaluates codegen freshness via plugin hook.
    • If generated types are missing/stale, failedChecks includes plugin:codegen.
    • Result: CI enforcement works without adding a separate codegen step.
  • chkit codegen command:
    • Optional manual trigger.
    • Useful when you explicitly want to regenerate or run an isolated --check.

In clickhouse.config.ts, register codegen(...) from @chkit/plugin-codegen.

Recommended typed setup:

import { defineConfig } from '@chkit/core'
import { codegen } from '@chkit/plugin-codegen'
export default defineConfig({
schema: './src/db/schema/**/*.ts',
plugins: [
codegen({
outFile: './src/generated/chkit-types.ts',
emitZod: false,
emitIngest: false,
ingestOutFile: './src/generated/chkit-ingest.ts',
emitMigrations: false,
migrationsOutFile: './src/generated/chkit-migrations.ts',
tableNameStyle: 'pascal',
bigintMode: 'string',
includeViews: false,
runOnGenerate: true,
failOnUnsupportedType: true,
}),
],
})

Legacy path-based registration via { resolve: './plugins/codegen.ts', options: {...} } remains supported.

  • outFile (default: ./src/generated/chkit-types.ts)
  • emitZod (default: false)
  • emitIngest (default: false)
  • ingestOutFile (default: ./src/generated/chkit-ingest.ts)
  • emitMigrations (default: false)
  • migrationsOutFile (default: ./src/generated/chkit-migrations.ts)
  • tableNameStyle (default: pascal) values: pascal | camel | raw
  • bigintMode (default: string) values: string | bigint
  • includeViews (default: false)
  • runOnGenerate (default: true)
  • failOnUnsupportedType (default: true)

Invalid option values fail fast at startup via plugin config validation.

  • chkit codegen
    • Optional manual command to generate and write output atomically.
  • chkit codegen --check
    • Optional manual check to validate output is current without writing.
    • Fails with:
      • codegen_missing_output (types file missing)
      • codegen_stale_output (types content drift)
      • codegen_missing_ingest_output (ingest file missing, when emitIngest is enabled)
      • codegen_stale_ingest_output (ingest content drift, when emitIngest is enabled)
      • codegen_missing_migrations_output (migrations file missing, when emitMigrations is enabled)
      • codegen_stale_migrations_output (migrations content drift, when emitMigrations is enabled)

Useful flags:

  • --out-file <path>
  • --emit-zod / --no-emit-zod
  • --emit-ingest / --no-emit-ingest
  • --ingest-out-file <path>
  • --emit-migrations / --no-emit-migrations
  • --migrations-out-file <path>
  • --bigint-mode <string|bigint>
  • --include-views

When configured, chkit check includes a plugins.codegen block in JSON output and can fail with plugin:codegen.

plugin:codegen is added to failedChecks when the plugin check returns an error finding (for example stale or missing generated artifacts).

When runOnGenerate is enabled (default), chkit generate runs codegen after successful migration/snapshot generation.

If codegen fails in that path, chkit generate fails.

When emitMigrations is enabled, the plugin generates a self-contained TypeScript module that inlines all migration SQL. This is designed for environments without filesystem access at runtime — such as Cloudflare Workers, Deno Deploy, or serverless functions — where reading .sql files from disk is not possible.

The generated file exports:

  • migrations — an array of MigrationEntry objects, each containing a name and the raw sql string.
  • runMigrations(executor, options?) — applies pending migrations against a provided executor, tracking progress in a _chkit_migrations journal table.

The runMigrations function accepts any object that satisfies the MigrationExecutor interface:

interface MigrationExecutor {
execute(sql: string): Promise<void>
query<T>(sql: string): Promise<T[]>
}

This keeps the generated module independent of any specific ClickHouse client library. Wrap your client to match this interface.

import { runMigrations } from './generated/chkit-migrations'
const result = await runMigrations(executor)
// result.applied — migrations that were run
// result.skipped — migrations already in the journal

You can override the journal table name:

await runMigrations(executor, { journalTable: 'my_migrations' })

When runOnGenerate is enabled (the default), the migration module is regenerated every time chkit generate produces new migrations. chkit check and chkit codegen --check detect stale or missing migration output via the codegen_missing_migrations_output and codegen_stale_migrations_output error codes.

  • Query-level type inference is not included.
  • Arbitrary SQL expression typing is not included.
  • Views/materialized views are opt-in and emitted conservatively.