langium-zod / generateZodSchemas
Function: generateZodSchemas()
function generateZodSchemas(config): string;Defined in: api.ts:138
Main entry point for programmatic Zod schema generation from a Langium grammar.
Accepts a ZodGeneratorConfig that specifies either a parsed Langium Grammar object or a pre-built AstTypesLike descriptor, then runs the full extraction → projection → code-generation pipeline and returns the generated TypeScript source as a string. When config.outputPath is set the result is also written to disk. Conformance artifacts are generated when config.conformance is provided.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | ZodGeneratorConfig | Generator configuration including the grammar or AST types, optional output path, include/exclude filters, projection, and feature flags. |
Returns
string
The generated TypeScript source containing all Zod schema exports.
Remarks
This is the primary API for most consumers. It combines extractTypeDescriptors, detectRecursiveTypes, and generateZodCode into a single call. Use the lower-level functions directly only when you need fine-grained control over individual pipeline stages (e.g. to inspect descriptors before code generation, or to cache extraction results across multiple code-generation runs).
The function is synchronous and writes to disk only when config.outputPath is set. It does not shell out or spawn child processes.
Config option decision tree:
- Does your grammar have recursive rules (e.g.
Expression: ... | left=Expression)? → no action needed; cycle detection is automatic. If you run a custom pipeline, pass the full (unprojected) descriptor set todetectRecursiveTypesfirst. - Does your grammar have cross-references (
ref:properties)? → if you need runtime ref-text validation in a live language server, enablecrossRefValidation: trueand use the emittedcreate*Schema()factories. Otherwise leave it off — unconstrainedReferenceSchemais lighter and sufficient for batch/offline validation. - Do you want to strip Langium internal bookkeeping fields (
$container,$document,$cstNode, etc.)? → setstripInternals: true. These fields are never meaningful in a validation context and inflate the generated schema. - Do you need form labels and descriptions driven by the grammar? → enable
formMetadata: true. Only properties whose grammar rule has a JSDoc/grammar comment get adescription; every property gets a humanizedtitleregardless. - Are you using Zod 4's
z.looseObject? → the defaultobjectStyle: 'loose'emitsz.looseObject(...). Switch toobjectStyle: 'strict'+.strict()on the schema only when you need hard rejection of unknown properties (e.g. strict API request validation).
Throws
ZodGeneratorError when required configuration is missing, when conformance is enabled without outputPath, or when a grammar property type cannot be mapped to a Zod schema.
Examples
import { createLangiumGrammarServices } from 'langium/grammar';
import { NodeFileSystem } from 'langium/node';
import { generateZodSchemas } from 'langium-zod';
const { grammar } = createLangiumGrammarServices(NodeFileSystem);
// assume `parsedGrammar` is a Grammar node obtained from Langium
const source = generateZodSchemas({
grammar: parsedGrammar,
outputPath: 'src/generated/zod-schemas.ts',
stripInternals: true,
});
console.log(source); // TypeScript source with Zod schema exports// Using a pre-built AstTypesLike descriptor (skips grammar parsing)
import { generateZodSchemas } from 'langium-zod';
import { collectAst } from 'langium/grammar';
const astTypes = collectAst(myGrammar);
const source = generateZodSchemas({ astTypes });Use When
- You have a parsed Langium
Grammarobject and want Zod schemas as a TypeScript string. - You are integrating langium-zod into a build pipeline (Vite plugin, codegen script, etc.).
- You need conformance artifacts (type-guard files) alongside the schema output.
- You want to write generated schemas to disk in a single call.
Avoid When
- You only need to inspect the intermediate type descriptors without generating code — use extractTypeDescriptors directly instead.
- You are running inside the Langium DI container — prefer DefaultZodSchemaGenerator which injects services automatically.
- You want to generate schemas for only a subset of types at runtime — pass
include/excludein the config rather than post-processing the output.
Never
- NEVER omit both
grammarandastTypes— the function throws ZodGeneratorError immediately. BECAUSE there is no default grammar source and no way to recover silently. FIX: provide at least{ grammar: parsedGrammar }or{ astTypes: collectAst(grammar) }. - NEVER enable
conformancewithout settingoutputPath— the function will throw before writing any output. BECAUSE the conformance module needs to derive a sibling output path from the schema file's directory. FIX: always setoutputPathwhenconformanceis truthy. - NEVER pass a
Grammar[]array when grammars share type names across files without verifying that Langium'scollectAst()merges them correctly. BECAUSE duplicate type names will silently overwrite each other in the type map, producing truncated schemas. FIX: runcollectAstseparately and inspect the merged map before generation. - NEVER call with
crossRefValidation: trueon grammars with no cross-reference properties — it emits deadcreate*Schemafactory functions that add noise without benefit. FIX: only enablecrossRefValidationwhen your grammar has at least oneref:property. - NEVER remove the
// @ts-nocheckcomment from generated output files. BECAUSE the getter-based recursive property syntax (emitted for self-referential types) is not always accepted by TypeScript's strict object-literal type checker — removing the comment causes immediate TS build failures in grammars with recursive rules. FIX: treat generated files as opaque artifacts; place any hand-written extensions in a separate file that imports the schema. - NEVER commit generated schemas as the sole copy of your schema logic. BECAUSE any grammar edit (new rule, renamed property, changed cardinality) produces stale schemas that pass TypeScript but fail at Zod validation runtime. FIX: wire
langium-zod generateas a pre-build or CI step so schema freshness is enforced automatically.