Modularize generator/src/{rust,js,rhai,openrpc} into build/emit/* (follow-up to #56) #58

Open
opened 2026-05-18 23:19:07 +00:00 by timur · 0 comments
Owner

Context

#56 split the 2653-line crates/generator/src/build/build.rs into focused submodules under build/{config,builder,error,fs,layout}.rs + build/emit/*.rs. Public API unchanged, no behaviour change.

The issue body proposed emit/{rust_types,rust_rpc,openrpc,js,rhai,python}.rs as per-output-target emit files. But in this crate, that per-target code lives in crate::generate::Generator (and the modules it dispatches to: crate::rust::*, crate::js::*, crate::rhai::*, crate::openrpc::*), NOT in build.rs. So #56 split along what build.rs actually does (bins, server-crate mods, SDK scaffolding, docs index) and left Generator untouched — that move would have been a much larger refactor with behaviour-change risk.

This issue tracks finishing the job: pull per-target emission OUT of Generator and into build/emit/ so the file names match the issue body of #56 and a reader can find each output target in one place.

Current location of per-target emitters

Target Lives in today
Rust types (types_generated.rs, types_wasm_generated.rs) crates/generator/src/rust/rust_struct.rs
Rust server (osis_server_generated.rs) crates/generator/src/rust/rust_osis.rs
Rust RPC (rpc_generated.rs + preserved rpc.rs stub) crates/generator/src/rust/ (alongside the above)
OpenRPC (schema.openrpc.json per domain) crates/generator/src/openrpc/
JS/TS SDK crates/generator/src/js/
Rhai bindings crates/generator/src/rhai/
Python SDK doesn't exist — see #55

crate::generate::Generator (generate.rs) is the orchestrator that calls into each.

Proposed split

Move the dispatch logic + the actual emit wrappers into build/emit/:

build/emit/
  rust_types.rs   — wraps crate::rust::rust_struct emitters; writes types_generated.rs + types_wasm_generated.rs
  rust_server.rs  — extend with osis_server emission (currently only does server-crate mod.rs/lib.rs)
  rust_rpc.rs     — wraps the RPC-trait emitter; writes rpc_generated.rs + preserves rpc.rs
  openrpc.rs      — wraps crate::openrpc emitter; writes schema.openrpc.json per domain
  js.rs           — wraps crate::js emitter; writes sdk/js output
  rhai.rs         — wraps crate::rhai emitter; writes the rhai bindings crate scaffold
  python.rs       — NEW (per #55); writes the Python SDK

The lower-level emitter modules (crates/generator/src/{rust,js,rhai,openrpc}/) stay — they hold the actual generation logic. The build/emit/*.rs wrappers become the single entry point for each output target, and Generator::generate() shrinks to a thin dispatch.

Why this is bigger than #56

  • It crosses the build/generate/ boundary (current public/internal split between consumer-facing config and codegen internals).
  • It risks behaviour change because each emitter has its own conditional flags, preserved-file rules, and ordering constraints that interact via Generator.
  • Path resolution (output_dir, sdk_output_dir, server_output_dir) currently flows through Generator's builder methods. Moving emit out means rethinking how paths are passed.

Acceptance

  • Every file under crates/generator/src/build/emit/ corresponds to exactly one output target, named per the proposal above.
  • crate::generate::Generator becomes a thin orchestrator (≤ 300 LOC) that hands off to the emit modules.
  • recipe_server builds unchanged; cargo test -p hero_rpc_generator stays green; cargo build --workspace stays green.
  • No public API change (OschemaBuilder, OschemaBuildConfig, BuildError, BuildResult stay re-exported from hero_rpc_osis::build).

Notes

  • Python emitter ships with #55 (codegen alignment + service.toml source of truth). This issue can land before or after #55 — but it should land after the new emitter is settled if before, to avoid double work.
  • Refs umbrella hero_skills#262.
## Context [#56](https://forge.ourworld.tf/lhumina_code/hero_rpc/issues/56) split the 2653-line `crates/generator/src/build/build.rs` into focused submodules under `build/{config,builder,error,fs,layout}.rs` + `build/emit/*.rs`. **Public API unchanged, no behaviour change.** The issue body proposed `emit/{rust_types,rust_rpc,openrpc,js,rhai,python}.rs` as per-output-target emit files. But in this crate, that per-target code lives in `crate::generate::Generator` (and the modules it dispatches to: `crate::rust::*`, `crate::js::*`, `crate::rhai::*`, `crate::openrpc::*`), NOT in `build.rs`. So #56 split along what `build.rs` actually does (bins, server-crate mods, SDK scaffolding, docs index) and left `Generator` untouched — that move would have been a much larger refactor with behaviour-change risk. This issue tracks finishing the job: pull per-target emission OUT of `Generator` and into `build/emit/` so the file names match the issue body of #56 and a reader can find each output target in one place. ## Current location of per-target emitters | Target | Lives in today | |---|---| | Rust types (`types_generated.rs`, `types_wasm_generated.rs`) | `crates/generator/src/rust/rust_struct.rs` | | Rust server (`osis_server_generated.rs`) | `crates/generator/src/rust/rust_osis.rs` | | Rust RPC (`rpc_generated.rs` + preserved `rpc.rs` stub) | `crates/generator/src/rust/` (alongside the above) | | OpenRPC (`schema.openrpc.json` per domain) | `crates/generator/src/openrpc/` | | JS/TS SDK | `crates/generator/src/js/` | | Rhai bindings | `crates/generator/src/rhai/` | | Python SDK | **doesn't exist** — see [#55](https://forge.ourworld.tf/lhumina_code/hero_rpc/issues/55) | `crate::generate::Generator` ([`generate.rs`](https://forge.ourworld.tf/lhumina_code/hero_rpc/src/branch/development/crates/generator/src/generate.rs)) is the orchestrator that calls into each. ## Proposed split Move the dispatch logic + the actual emit wrappers into `build/emit/`: ``` build/emit/ rust_types.rs — wraps crate::rust::rust_struct emitters; writes types_generated.rs + types_wasm_generated.rs rust_server.rs — extend with osis_server emission (currently only does server-crate mod.rs/lib.rs) rust_rpc.rs — wraps the RPC-trait emitter; writes rpc_generated.rs + preserves rpc.rs openrpc.rs — wraps crate::openrpc emitter; writes schema.openrpc.json per domain js.rs — wraps crate::js emitter; writes sdk/js output rhai.rs — wraps crate::rhai emitter; writes the rhai bindings crate scaffold python.rs — NEW (per #55); writes the Python SDK ``` The lower-level emitter modules (`crates/generator/src/{rust,js,rhai,openrpc}/`) stay — they hold the actual generation logic. The `build/emit/*.rs` wrappers become the single entry point for each output target, and `Generator::generate()` shrinks to a thin dispatch. ## Why this is bigger than #56 - It crosses the `build/` ↔ `generate/` boundary (current public/internal split between consumer-facing config and codegen internals). - It risks behaviour change because each emitter has its own conditional flags, preserved-file rules, and ordering constraints that interact via `Generator`. - Path resolution (`output_dir`, `sdk_output_dir`, `server_output_dir`) currently flows through `Generator`'s builder methods. Moving emit out means rethinking how paths are passed. ## Acceptance - Every file under `crates/generator/src/build/emit/` corresponds to exactly one output target, named per the proposal above. - `crate::generate::Generator` becomes a thin orchestrator (≤ 300 LOC) that hands off to the emit modules. - `recipe_server` builds unchanged; `cargo test -p hero_rpc_generator` stays green; `cargo build --workspace` stays green. - No public API change (`OschemaBuilder`, `OschemaBuildConfig`, `BuildError`, `BuildResult` stay re-exported from `hero_rpc_osis::build`). ## Notes - Python emitter ships with [#55](https://forge.ourworld.tf/lhumina_code/hero_rpc/issues/55) (codegen alignment + `service.toml` source of truth). This issue can land before or after #55 — but it should land after the new emitter is settled if before, to avoid double work. - Refs umbrella [hero_skills#262](https://forge.ourworld.tf/lhumina_code/hero_skills/issues/262).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_rpc#58
No description provided.