Remove the printer layer and make the Kubb AST the single generation IR
enhancement@kubb/plugin-zod@kubb/core@kubb/plugin-tsplugin-faker
## Background
Kubb has two AST layers. The schema AST (`SchemaNode` in `@kubb/ast`) is consumed by the per-plugin printers. The code/file AST (`FileNode`/`SourceNode`/`CodeNode`) is consumed by the parsers (`parserTs` for `.ts` and `.tsx`, `parserMd` for `.md`), which are keyed by file extension.
How a value reaches the output today:
- `printerTs` maps `SchemaNode` to `ts.Node` (the TypeScript compiler AST), then collapses it to a string through `parserTs.print`.
- `printerZod` and `printerFaker` build raw strings directly, with no intermediate AST.
- Either way the value inside a `ConstNode` (the `= z.object({…})` or `= { … }` part) ends up as a `TextNode`, which is a raw string.
Printer and parser are different jobs. The printer translates a schema into a target representation and carries the target-specific policy: resolved names, cyclic `z.lazy` or getters, date `direction`, and style options. The parser turns the code AST into a file. The printer is the piece this change removes.
## Goal
Make the Kubb AST the complete intermediate representation. The three schema plugins (`plugin-ts`, `plugin-zod`, `plugin-faker`) produce only Kubb AST nodes, with no `ts.Node` and no hand-built strings, and `plugin-ts` stops importing `typescript`. All TypeScript-syntax knowledge (the `ts.factory` builders and the `ts` compiler printer) moves into `@kubb/parser-ts`, which becomes the only TS-aware serializer. Then `definePrinter` is deleted. The generated output must stay byte-identical.
Two new IR families land in `@kubb/ast`:
- Expression IR for zod and faker values: `Identifier`, `Literal`, `Call{callee,args,typeArgs?}`, `Member{object,property}` for chains like `z.iso.date`, `Object{properties:(prop|getter{memoize?}|spread)[]}`, `Array`, `Arrow{params,body,singleLine?}`, `Spread`, `As{expression,type}`, and a transitional `RawExpression{value}`. A method chain is `Call{ callee: Member{ object: prev, property }, args }`.
- Type IR for TypeScript types, growing the existing `nodes/function.ts` seed (`TypeExpression`, `TypeLiteralNode`, `IndexedAccessTypeNode`) into full coverage of what `plugin-ts/src/factory.ts` builds: type literals, unions and intersections with parentheses, `T[]` and `Array<T>`, tuples, `Omit`, `NonNullable`, `Extract`, type references, literal and keyword types, URL template types, and property JSDoc.
## Constraints that span the work
Byte-parity is the gate. Values reuse the existing `buildObject`, `buildList`, and `objectKey` helpers from `@kubb/ast/utils/codegen.ts` inside a new `printExpression`, since those helpers define the current formatting. Types reproduce the same `ts.Node` shapes inside `parser-ts` so the compiler printer prints identical output. The gate at every plugin stage is `plugins/tests/3.0.x/main.test.ts` (`toMatchFileSnapshot`) plus the per-plugin and per-printer suites, all byte-identical to baseline.
Release order is cross-repo. `@kubb/ast` and `@kubb/parser-ts` (this repo) ship as additive minors first. The plugins ([kubb-labs/plugins](https://github.com/kubb-labs/plugins)) migrate against them. The coordinated major that removes `definePrinter` comes last.
The `printer: { nodes }` override surface changes from strings and `ts.Node` to Kubb IR nodes, which is breaking. `RawExpression` lets existing string overrides wrap through `createRaw(str)` during migration. Each plugin's `printer.nodes` page in `kubb-labs/docs` needs updating.
## Honest note
The output stays byte-identical, so the win is structural rather than behavioral. The plugins drop their dependency on the TypeScript compiler and all string templating, target syntax lives in one place (`parser-ts`), and the override surface gets a real API instead of string concatenation. It is still a large breaking change across both repos, and the type IR (sub-issue 2) is the expensive part. If appetite drops, the type IR can land last, keeping `printerTs` on `ts.Node` for now, while zod, faker, and the expression IR ship first.
## Sub-issues
- [ ] 1. Core (`@kubb/ast`): add the expression IR and type IR
- [ ] 2. Core (`@kubb/parser-ts`): serialize the IR and relocate `factory.ts`
- [ ] 3. `plugin-zod`: emit the expression IR
- [ ] 4. `plugin-faker`: emit the expression IR
- [ ] 5. `plugin-ts`: emit the type IR, drop `typescript`, remove `definePrinter`
- [ ] 6. Docs: update the `printer.nodes` override pages in `kubb-labs/docs`
0 条评论