Skip to content

SurrealKit

Type generation

surrealkit typegen introspects a live database and emits a structured description of its schema. JSON is the primary output; TypeScript interfaces for the SurrealDB JavaScript SDK can be generated alongside it.

surrealkit typegen --user root --pass secret

By default this writes a JSON document to database/types/schema.json. SurrealKit's internal bookkeeping tables (__entity, __rollout, __seed) are excluded from the output.

FlagDefaultDescription
--out <path>[typegen] json, else {folder}/types/schema.jsonWrite the JSON to a specific path
--stdoutoffPrint the JSON to stdout instead of writing the JSON file. Configured TypeScript is still written
--compactoffEmit compact, single-line JSON instead of pretty-printed
--typescript <path>[typegen] typescriptAlso write TypeScript to this .ts file or directory
--checkoffWrite nothing, and exit non-zero when a generated file is missing or out of date
--strictoffFail instead of warning when an output cannot be produced exactly as configured
--no-generated-atoffLeave generatedAt out of the JSON
--from <schema.json>Read the schema document from a file instead of a database
# Pretty-printed JSON to the default location
surrealkit typegen --user root --pass secret

# Pipe compact JSON into another tool
surrealkit typegen --stdout --compact --user root --pass secret

The JSON document includes the namespace, database, generation timestamp, and a typed description of every table, field, and function in the schema.

TypeScript generation is opt-in through the [typegen] section of surrealkit.toml. Set typescript to the directory where the generated index.ts should be written:

[typegen]
typescript = "./src/types"
format = "biome check --write"
KeyDescription
typescriptWhere generated TypeScript goes. Setting it enables TypeScript output for typegen and sync. A path ending in .ts, .mts or .cts, such as src/types/database.ts, is the file itself; any other path is a directory.
filenameThe file to write inside the typescript directory. Defaults to index.ts; another name leaves index.ts free for your own barrel file.
formatOptional formatter command run on the generated file after writing (for example biome check --write, prettier --write, or eslint --fix).
jsonWhere the JSON document goes. Setting it makes sync write the document too, and typegen writes it there instead of database/types/schema.json. A path ending in .json is the file itself; any other path is a directory, and the file in it is schema.json.
strictFail instead of warning when an output cannot be produced exactly as configured. Defaults to false.
generated_atSet to false to leave the generatedAt timestamp out of the JSON, so the same schema always produces the same bytes.
schema_version1 (the default) or 2, which writes schema document v2 instead.

Unknown keys in [typegen] are an error, so a misspelt key cannot turn an output off without a message. surrealkit typegen --typescript <path> and --out <path> override the configured TypeScript and JSON paths for one run.

Generated files are written atomically, to a temporary file beside the real one and then renamed, so a bundler or tsc --watch never reads half a file, and a failure leaves the previous version in place. A file whose content would not change is not rewritten.

With typescript configured, surrealkit typegen writes both the JSON document and an index.ts:

// Generated by SurrealKit - do not edit.
// Run `surrealkit typegen` to regenerate.

import type { RecordId } from 'surrealdb';

export interface User {
  id: RecordId<'user'>;
  name: string;
  email: string;
}

The emitter targets the SurrealDB JavaScript SDK (v2): one interface per table, every record carrying a typed id: RecordId<'table'>, with schema field types mapped to the SDK's wrapper types.

When format is set, SurrealKit appends the generated file path to the command and runs it, so the output matches your project's house style. The command inherits the working directory so the formatter discovers your project's own config. The formatter runs on the temporary file, which has the same directory and extension as the real one but a name such as index.surrealkit-tmp-<pid>-<n>.ts, so a formatter that only accepts files matching a pattern has to accept that name too. Formatter failures (a missing binary or a non-zero exit) are reported as warnings, unless strict is set.

When [typegen] typescript or json is configured, surrealkit sync regenerates the outputs after it applies schema changes, so the generated types never drift from the database. With --watch, they stay current while you edit the schema:

surrealkit sync --watch --user root --pass secret

Regeneration is gated on actual schema changes (or a missing output file), so idle watch ticks do not re-introspect the database.

surrealkit typegen --check writes nothing, and exits with a non-zero code when a configured output is missing or differs from what would be generated. It compares content, so an unchanged schema passes even though generatedAt would be a new time:

surrealkit typegen --check --user root --pass secret

--strict and --no-generated-at turn on strict and generated_at = false for one run.

Typegen understands every SurrealDB field type, including regex, range, table<…>, file<…>, tuples such as [A, B], object literals such as { a: int }, and literal values. Anything it cannot represent is reported as a diagnostic rather than typed unknown without a message. A field type it cannot parse is an error, which fails a strict run, and a field without TYPE is still unknown, with an informational message under --verbose.

typegen reads one database: the --target you name, else the target marked primary = true, else the only declared target, else the ambient connection from --host, --ns and --db. With --schema, that target must accept the module in its schemas list.

surrealkit typegen --target staging

A project with exactly one declared target therefore introspects that target, not the ambient connection.

Note

There is one [typegen] typescript directory for the whole project, so surrealkit sync --all regenerates the same index.ts once per module and target pair, and the last pair to run leaves its output in place. Generate types from a single target rather than from a fan-out.

Type generation is also available from the surrealkit::typegen module when embedding SurrealKit in Rust:

use surrealkit::typegen::{generate, render_typescript, write_typescript};
use surrealkit::Surreal;
use surrealkit::engine::any::Any;

async fn run(db: &Surreal<Any>) -> anyhow::Result<()> {
    // Introspect the database into a structured document (no filesystem IO).
    let doc = generate(db).await?;

    // Render TypeScript as a string …
    let ts = render_typescript(&doc)?;
    println!("{ts}");

    // … or write it to `<dir>/index.ts`.
    write_typescript(&doc, std::path::Path::new("src/types"))?;
    Ok(())
}

generate returns a SchemaTypes document that the JSON and TypeScript emitters share, so a single introspection can produce both formats. write_typescript_formatted writes the file and runs an optional formatter command in the same call, and generate_with_diagnostics also returns what typegen could not represent.

[typegen] schema_version = 2 writes schema document v2, a format for tools that generate their own code from the schema, instead of the version 1 JSON. The TypeScript output does not change. Two commands work with it without a running database:

  • surrealkit compile builds the document from your schema files in an embedded engine with no network access. Set [typegen] engine to the SurrealDB minor version you deploy to, such as "4.0", and compile reports an error when its embedded engine is a different minor version.

  • surrealkit typegen --from <schema.json> generates the configured outputs from a document on disk.

External emitters, declared as [typegen.emit.<name>] with a command and an out directory, read the document on standard input and return files to write, such as the Effect schemas from the effect-surrealkit package. [typegen] acknowledge lets a named error diagnostic through a strict run, with the reason it is acceptable. The schema document v2 specification and the external emitter protocol describe both in full.

Was this page helpful?