feat(generator): route codegen into per-domain generated/ subfolders (#96) #101

Merged
timur merged 2 commits from issue-96-generated-folders into development 2026-05-20 23:46:53 +00:00
Owner

Summary

  • Routes all OSchema codegen output into per-domain generated/ subfolders and gitignores it (closes #96)
  • Drops the _generated.rs suffix everywhere — folder name carries the signal
  • Scaffolds parent mod.rs + types.rs include!() wrapper + rpc.rs trait impl as once-only files contributors own
  • Migrates example/recipe_server to the new layout; git status is empty after cargo build --workspace

What changed per emitter

Emitter Path before Path now
rust_types <domain>/types_generated.rs, types_wasm_generated.rs <domain>/generated/{types,types_wasm}.rs
rust_server <domain>/osis_server_generated.rs, rpc_generated.rs <domain>/generated/{server,rpc}.rs
rust_rpc (legacy) (same as rust_server) (same)
openrpc docs/openrpc.json, docs/<domain>/openrpc.json same paths, gitignored
js sdk/js/src/<domain>.js, index.js same, gitignored
rhai <domain>/rhai_types_generated.rs <domain>/generated/rhai_types.rs
python sdk/python/hero_<svc>_sdk/*.py same, package dir gitignored (pyproject.toml stays)
tests_emit <domain>/tests.rs <domain>/generated/tests.rs
rust_rpc2 SDK sdk/rust/src/<domain>.rs sdk/rust/src/generated/<domain>.rs

Module shape (consumer crate)

// crates/<name>/src/<domain>/mod.rs — scaffolded once
pub mod generated;

#[cfg(not(target_arch = "wasm32"))]
mod types;                          // include!()-wrapper at types.rs
#[cfg(not(target_arch = "wasm32"))]
pub use types::*;

#[cfg(target_arch = "wasm32")]
pub use generated::types_wasm::*;
// crates/<name>/src/<domain>/types.rs — scaffolded once
include!("generated/types.rs");

// Add custom impl blocks below — they live in scope with the generated structs.

Module shape (server crate)

// crates/<name>_server/src/<domain>/mod.rs — scaffolded once
pub mod generated;
pub use generated::*;

mod rpc;            // contributor's trait impl, scaffolded once
pub use rpc::*;

generated/mod.rs declares mod rpc; privately (so the parent's mod rpc;
can claim the name) and re-exports the trait + error types via pub use rpc::*.

Gitignore

Per-crate .gitignore next to each domain:

generated/

Repo-root additions (also added to the scaffolder so freshly scaffolded
services pick them up):

docs/openrpc.json
docs/*/openrpc.json
sdk/rust/src/generated/
sdk/rhai/src/generated/
sdk/js/src/
sdk/python/*/
!sdk/python/pyproject.toml
!sdk/python/README.md
!sdk/python/.gitignore

Build ordering

sdk/rust/ and <svc>_admin/ get a tiny build.rs shim with
[build-dependencies] hero_<svc> = { path = ... }. The dep edge forces cargo
to run the core crate's build.rs (which writes the SDK + docs) before
compiling these downstream crates. Without the edge, gitignored codegen
output isn't present when downstream compilation starts.

Acceptance check on example/recipe_server

$ cargo clean && rm -rf docs crates/*/src/*/generated sdk/rust/src/generated …
$ cargo build --workspace
   ... compiles cleanly ...
$ git status
   nothing to commit, working tree clean

No _generated.rs filenames remain in example/recipe_server/.

Out of scope (per the issue body)

  • Migration of services other than recipe_server + hero_service — those land in #90 phase 3.
  • The hero_service template repo + hero_service_scaffold.md skill — separate PRs against hero_service and hero_skills.

🤖 Generated with Claude Code

## Summary - Routes all OSchema codegen output into per-domain `generated/` subfolders and gitignores it (closes #96) - Drops the `_generated.rs` suffix everywhere — folder name carries the signal - Scaffolds parent `mod.rs` + `types.rs` `include!()` wrapper + `rpc.rs` trait impl as once-only files contributors own - Migrates `example/recipe_server` to the new layout; `git status` is empty after `cargo build --workspace` ## What changed per emitter | Emitter | Path before | Path now | |---|---|---| | rust_types | `<domain>/types_generated.rs`, `types_wasm_generated.rs` | `<domain>/generated/{types,types_wasm}.rs` | | rust_server | `<domain>/osis_server_generated.rs`, `rpc_generated.rs` | `<domain>/generated/{server,rpc}.rs` | | rust_rpc (legacy) | (same as rust_server) | (same) | | openrpc | `docs/openrpc.json`, `docs/<domain>/openrpc.json` | same paths, gitignored | | js | `sdk/js/src/<domain>.js`, `index.js` | same, gitignored | | rhai | `<domain>/rhai_types_generated.rs` | `<domain>/generated/rhai_types.rs` | | python | `sdk/python/hero_<svc>_sdk/*.py` | same, package dir gitignored (pyproject.toml stays) | | tests_emit | `<domain>/tests.rs` | `<domain>/generated/tests.rs` | | rust_rpc2 SDK | `sdk/rust/src/<domain>.rs` | `sdk/rust/src/generated/<domain>.rs` | ## Module shape (consumer crate) ```rust // crates/<name>/src/<domain>/mod.rs — scaffolded once pub mod generated; #[cfg(not(target_arch = "wasm32"))] mod types; // include!()-wrapper at types.rs #[cfg(not(target_arch = "wasm32"))] pub use types::*; #[cfg(target_arch = "wasm32")] pub use generated::types_wasm::*; ``` ```rust // crates/<name>/src/<domain>/types.rs — scaffolded once include!("generated/types.rs"); // Add custom impl blocks below — they live in scope with the generated structs. ``` ## Module shape (server crate) ```rust // crates/<name>_server/src/<domain>/mod.rs — scaffolded once pub mod generated; pub use generated::*; mod rpc; // contributor's trait impl, scaffolded once pub use rpc::*; ``` `generated/mod.rs` declares `mod rpc;` privately (so the parent's `mod rpc;` can claim the name) and re-exports the trait + error types via `pub use rpc::*`. ## Gitignore Per-crate `.gitignore` next to each domain: ``` generated/ ``` Repo-root additions (also added to the scaffolder so freshly scaffolded services pick them up): ``` docs/openrpc.json docs/*/openrpc.json sdk/rust/src/generated/ sdk/rhai/src/generated/ sdk/js/src/ sdk/python/*/ !sdk/python/pyproject.toml !sdk/python/README.md !sdk/python/.gitignore ``` ## Build ordering `sdk/rust/` and `<svc>_admin/` get a tiny `build.rs` shim with `[build-dependencies] hero_<svc> = { path = ... }`. The dep edge forces cargo to run the core crate's `build.rs` (which writes the SDK + docs) before compiling these downstream crates. Without the edge, gitignored codegen output isn't present when downstream compilation starts. ## Acceptance check on `example/recipe_server` ``` $ cargo clean && rm -rf docs crates/*/src/*/generated sdk/rust/src/generated … $ cargo build --workspace ... compiles cleanly ... $ git status nothing to commit, working tree clean ``` No `_generated.rs` filenames remain in `example/recipe_server/`. ## Out of scope (per the issue body) - Migration of services other than `recipe_server` + `hero_service` — those land in #90 phase 3. - The hero_service template repo + `hero_service_scaffold.md` skill — separate PRs against `hero_service` and `hero_skills`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(generator): route codegen into per-domain generated/ subfolders (#96)
Some checks failed
Test / test (push) Failing after 1m51s
adf26fd2c4
Phase 1: emitter path changes only.

- rust_types: writes to <domain>/generated/{types,types_wasm,rhai_types}.rs;
  scaffolds parent mod.rs + types.rs include!() wrapper once
- rust_server: writes to <domain>/generated/{server,rpc}.rs;
  scaffolds parent rpc.rs (trait impl) once
- tests_emit: writes to <domain>/generated/tests.rs
- rhai: writes to <domain>/generated/rhai_types.rs
- build/emit/rust_server: writes server crate's <domain>/generated/mod.rs every
  build, scaffolds parent mod.rs once
- build/emit/rust_rpc2: writes sdk/rust/src/generated/{<domain>,mod}.rs;
  scaffolds lib.rs + src/.gitignore once

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(generator,recipe_server): migrate recipe_server to generated/ layout (#96)
Some checks failed
Test / test (push) Failing after 1m28s
Test / test (pull_request) Failing after 2m0s
ff1dd79097
Generator-side fixes:
- rust_rpc emitter: imports go through parent module's re-export
  (`use super::*;` in handwritten rpc.rs, no explicit `super::generated::rpc`
  path — the rpc submodule inside generated/ is now private so it doesn't
  fight with the parent's `mod rpc;`)
- rust_server emitter: injects `use super::super::*;` into the OSIS server
  so it can name handler types from the parent module's `rpc.rs`
- build/emit/rust_server: `mod rpc;` inside `generated/mod.rs` is private,
  contents still surface via `pub use rpc::*`
- scaffolder: repo-root .gitignore template gets the codegen entries

recipe_server migration:
- delete stale `_generated.rs` files (now in generated/)
- update rpc.rs to use new module paths
- add build.rs shim + build-dependency on hero_recipes to sdk/rust and
  hero_recipes_admin so cargo runs the codegen build.rs first
- repo-root .gitignore picks up docs/openrpc.json + SDK trees
- untrack previously-committed codegen output (docs, sdk/js/src, python pkg)

git status is empty after `cargo build --workspace`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
timur merged commit a00ad070b0 into development 2026-05-20 23:46:53 +00:00
Sign in to join this conversation.
No reviewers
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!101
No description provided.