# exporters

Schema → String / Json / MoonBit source code 导出工具包。

本包提供多条独立导出管线（Prompt / JSON Schema / MoonBit struct / MoonZod Schema）。每条管线对 `@core.SchemaType` 的 17 个变体做逐一渲染，支持内联展开和命名引用两种模式。

---

## 公开 API

### Prompt 导出

- `schema_to_prompt(schema) -> String` — 将 Schema 渲染为 TypeScript-interface 风格的提示文本（全内联）
- `schema_to_prompt_named(schema, include_names?) -> String` — 提取带 `name` 的 Schema 生成模块化接口，带拓扑排序和类型引用

### JSON Schema 导出

- `to_json_schema(schema) -> Json` — 标准 JSON Schema（完整约束注释）
- `to_json_schema_skeleton(schema) -> Json` — 轻量级骨架（仅类型结构，无约束）
- `to_json_schema_named(schema, include_names?) -> Json` — 命名 Schema 导出为 `$defs` + `$ref`

### MoonBit 结构导出

- `schema_to_moonbit_struct(schema) -> String` — 生成 MoonBit `pub struct` / `pub enum` 定义
- `schema_to_moonbit_struct_full(schema) -> String` — 生成定义 + 静态 `Type::to_schema()` 方法

### 代码生成

- `schema_to_moon_zod_code(schema) -> String` — 将 Schema 反转为可 copy-paste 的 moon_zod 源码
- `schema_to_moon_zod_code_named(schema, include_names?) -> String` — 带命名 Schema 引用的源码生成
- `schema_to_moon_zod_code_inline_with_refs(schema, include_names) -> String` — 内联渲染，可选命名引用替换

---

## 文件结构

```
exporters/
├── prompt.mbt                  # schema_to_prompt / schema_to_prompt_named 公共 API
├── prompt_renderer.mbt         # StringRenderer trait + NamedPromptRenderer 实现
├── json_schema.mbt             # to_json_schema / to_json_schema_named / to_json_schema_skeleton 公共 API
├── json_schema_renderer.mbt    # JsonSchemaRenderer trait + NamedJsonRenderer 实现
├── moonbit_struct.mbt          # schema_to_moonbit_struct / _full 公共 API
├── schema_exporter.mbt         # schema_to_moon_zod_code / _named / _inline 公共 API
└── pkg.generated.mbti          # moon info 生成的接口描述（勿手动编辑）
```

---

## 实现说明

### 渲染器架构

导出管线统一采用 **trait 分发** 模式：

1. 每个 `SchemaType` 变体对应 trait 中的一个方法
2. 顶层的 `render_type` / `render_json_type` 做单点分发
3. 渲染器只负责「类型 → 文本/Json」的转换，约束注释、命名引用、描述文本由各模块独立处理

```
Schema ──► render_type(renderer, schema) ──► StringRenderer ──► String
         └── render_json_type(renderer, schema) ──► JsonSchemaRenderer ──► Json
```

#### Prompt 导出（`prompt.mbt` + `prompt_renderer.mbt`）

- `schema_to_prompt()` 内部复用 `NamedPromptRenderer([])`，named 集合为空 → 全内联展开
- `schema_to_prompt_named()` 收集所有带 `name` 的 Schema，拓扑排序后生成 `export interface / export type` 定义
- `include_names?` 参数支持选择性导出（`None` = 全部，`Some([])` = 无，`Some([...])` = 指定）
- named wrapper schemas（primitive、array、optional、default、transform、tuple、any、unknown、preprocess）统一生成 `export type X = T`
- named intersection 当包含非 object 分支时输出 `export type X = A & B`，否则合并 object 字段

#### JSON Schema 导出（`json_schema.mbt` + `json_schema_renderer.mbt`）

- `NamedJsonRenderer` 的 `include_annotations` 参数统一三种模式：
  - `include_annotations=true` → `to_json_schema()`（完整约束）
  - `include_annotations=false` → `to_json_schema_skeleton()`（仅结构）
- optional/default/prefault 影响对象必填列表；只有 nullable/nullish 添加 null 分支
- `Strip` 模式导出 `additionalProperties: false`（与运行时幻觉防御对齐）
- object intersection 合并为单个 closed object；同名字段用属性级 `allOf` 保留各自约束
- `$defs` 本体展开，子节点使用完整名称集合引用，包括合法的递归自引用

### 代码生成架构

本包包含两条**反向代码生成**管线，均不采用 trait 分发，而是直接 match `SchemaType` 生成目标语言源码。

#### MoonBit 结构导出（`moonbit_struct.mbt`）

- `schema_to_moonbit_struct()` 将 `ObjectType` 映射为 `pub struct`，`EnumType` 映射为 `pub enum`
- `schema_to_moonbit_struct_full()` 额外生成静态 `Type::to_schema() -> @moon_zod.Schema` 方法，实现 struct ↔ Schema 往返
- 基础类型映射：`String → String`，`Number → Int64 / Double`（按 `.int()` 规则区分），`Boolean → Bool`
- `ArrayType → Array[T]`；nullable 和可空 UnionType 递归映射为 `@moon_zod.JsonNullable[T]`，字段缺失另加外层 `?`
- `AnyType / UnknownType` 当前回退为 `Json`
- `TupleType` / 非可空 `UnionType` / `IntersectionType` 当前回退为 `Json // TODO`
- 字段名和类型名自动转义（MoonBit 关键字、保留字、首字母数字）
- 约束注释以行内注释形式附加在 struct field 上

#### MoonZod 代码导出（`schema_exporter.mbt`）

- `schema_to_moon_zod_code()` 将运行时 Schema 反转为可 copy-paste 的 moon_zod 方法链源码
- 输出格式：`let name = @moon_zod.string().min(3).describe("...").name("name")`
- 根 Schema 无 `name` 时自动赋予 `"Root"`
- `schema_to_moon_zod_code_named()` 提取所有命名 Schema，拓扑排序后输出 `let name = ...` 定义列表
- 源码通过 `Rule.constraint` 和 `TransformKind` 还原规则、排他边界和内建转换
- `json_to_literal()` 将 Json 值转为 MoonBit 构造函数调用（`Json::string(...)` / `Json::number(...)` / `true` / `false` / `null`）
- 自定义 preprocess/transform/refine 无法序列化，checked API 返回 Err，旧入口明确 abort；不再生成恒等占位闭包
- 源码保留 required_error、invalid_type_error、显式规则消息和品牌元数据；递归节点生成辅助函数

---

## 已知限制

- 当前 `moonbit_struct.mbt` 中 `TupleType` 仍回退为 `Json`，`any/unknown` 仅做最低限度映射。待后续整体重构时重新评估。
- MoonBit 结构导出尚不支持 `tuple` / `intersection` / `union` 等复杂类型的精确类型映射，当前回退为 `Json`。
- 自定义 `TransformType` / `PreprocessType` 闭包无法忠实序列化；checked 源码导出返回 Err，旧源码导出入口会 abort。
详见 [Core 迁移说明](../CHANGELOG.md#core-migration)。使用 `try_to_json_schema(view=InputView/OutputView)` 区分结构阶段；生成源码的实际编译测试在 `moon_zod_lab/scripts/check_generated_source.py`，依赖和未发布源码的验证方式见 lab README。

`JsonNullable[T]` 使用 `JsonNull` / `JsonValue(T)`，提供 JSON 的 `null | 值`
编解码。普通 Option 在数组中的标准编码为 `[值] | null`，不能用于生成这里的
nullable 元素。生成类型的 `FromJson` 与 `ToJson` 往返已加入实际编译测试。
checked OutputView 的 intersection 通过 `output_merge.mbt` 递归合并结构；涉及
可缺失重叠值或无法表达的条件结构时返回 Err。独立校验器回归位于
`moon_zod_lab/scripts/check_output_contracts.py`（依赖 jsonschema 4.23.0，手动运行）。
