Building an emitter for irgen involves understanding the transition from Target-Agnostic IR to Target-Specific code. This guide walks you through the internal pipeline and the best practices for code emission.
The IR Pipeline
- DeclIR: Captured directly from the DSL (raw intent).
- DomainIR: Enriched semantic model (e.g., BackendEntity).
- TargetIR: The final contract for the emitter. It includes resolved policies.
1// Example: TargetIR for a Backend Entity
2export interface BackendTargetIR {
3 appName: string;
4 entities: BackendEntity[];
5 policies: BackendPolicy; // Fully resolved decisions
6}Creating a New Emitter
To add a new emitter, you need to register it in the Emitter Engine and map it to a target in the Registry.
1import { emitterEngine } from "../engine.js";
2import { registerTargetEmitter } from "../registry.js";
3
4async function myCustomEmitter(ir: MyTargetIR, outDir: string) {
5 // 1. Traverse IR
6 // 2. Generate files (using fs or ts-morph)
7}
8
9// Register
10emitterEngine.registerEmitter("my-custom", myCustomEmitter);
11registerTargetEmitter("my-target", "my-custom");Using the Emitter SDK
irgen provides a small SDK with common utilities for emitters, such as string casing and smart file writing. For now this SDK is an internal, blessed utility for built-in emitters, not a guaranteed public API for third-party extensions.
1import { casing, writeIfChanged } from "../utils/sdk.js";
2
3const className = casing.pascal(entity.name);
4writeIfChanged(path.join(outDir, "models", `${casing.kebab(entity.name)}.ts`), content);Debugging & Inspection
Use the CLI flags to inspect the state of the IR at different stages:
--inspect-decl: See the raw input from DSL.--inspect-domain: See the enriched semantic model.--inspect-ir: See the final contract sent to the emitter.
Emitter Discipline
Emitters should be 'dumb'. All architectural decisions (like which DB provider to use or what naming convention to follow) should be resolved in the Lowering phase and encoded into the TargetIR. If your emitter is making a decision, that logic likely belongs in a Policy and a Lowering step.