Drop types_wasm_generated.rs — fold WASM-compat into types_generated.rs via cfg #74

Open
opened 2026-05-19 16:47:00 +00:00 by timur · 1 comment
Owner

Problem

The scaffolder emits a duplicate types file at crates/<name>/src/<domain>/types_wasm_generated.rs for WASM-target compatibility. Two parallel definitions of the same types is the wrong shape: native code and WASM code both want the same Recipe / User / ServiceDefinition structs.

What to do

  • Merge the WASM-compat type definitions into the main types_generated.rs using #[cfg(target_arch = "wasm32")] (and the inverse) blocks where the shapes genuinely diverge — but only for the fields/methods that need to differ.
  • Where the types are identical across targets (the common case), no cfg is needed; remove the duplication.
  • Delete types_wasm_generated.rs emission.
  • Verify both native and --target wasm32-unknown-unknown builds compile.

Acceptance

  • Fresh scaffold emits one types_generated.rs per domain, not two.
  • cargo build clean on native.
  • cargo build --target wasm32-unknown-unknown -p <name> clean (or unchanged from prior behaviour if the build was already supported).
## Problem The scaffolder emits a duplicate types file at [`crates/<name>/src/<domain>/types_wasm_generated.rs`](https://forge.ourworld.tf/lhumina_code/hero_service/src/branch/development/crates/hero_service/src/catalog/types_wasm_generated.rs) for WASM-target compatibility. Two parallel definitions of the same types is the wrong shape: native code and WASM code both want the same `Recipe` / `User` / `ServiceDefinition` structs. ## What to do - Merge the WASM-compat type definitions into the main `types_generated.rs` using `#[cfg(target_arch = "wasm32")]` (and the inverse) blocks where the shapes genuinely diverge — but only for the fields/methods that need to differ. - Where the types are identical across targets (the common case), no `cfg` is needed; remove the duplication. - Delete `types_wasm_generated.rs` emission. - Verify both native and `--target wasm32-unknown-unknown` builds compile. ## Acceptance - Fresh scaffold emits one `types_generated.rs` per domain, not two. - `cargo build` clean on native. - `cargo build --target wasm32-unknown-unknown -p <name>` clean (or unchanged from prior behaviour if the build was already supported).
Author
Owner

Implemented on lab/74-fold-wasm-types (compare).

Approach

Added generate_unified_rust_structs in crates/generator/src/rust/rust_struct.rs. It builds both per-typedef outputs (via the existing native and wasm generators) and:

  • emits each typedef once with no cfg gating when the two outputs are byte-identical (the common case — enums, embedded structs);
  • emits each typedef twice, each gated by #[cfg(target_arch = "wasm32")] / its inverse, only when the shapes genuinely diverge (root objects: native adds OsisObject derive + injected sid: SmartId / created_at: u64 / updated_at: u64; wasm keeps the schema fields as declared);
  • emits the wasm-only inline OTOML primitives (OTime, OCur, OLocation, OAddress) in a gated __wasm_otoml submodule;
  • gates the native-only hero_rpc_osis::otoml::* / OsisObject imports.

crates/generator/src/generate/rust_types.rs now calls the unified emitter once per domain instead of emitting two parallel files, and cleans up any stale types_wasm_generated.rs left over from prior scaffold runs. The flat-layout mod.rs (build/layout.rs) and the per-domain mod.rs lose their target-arch branches — types.rs includes the unified file unconditionally and the cfg gating lives inside the generated file itself.

generate_rust_wasm_structs is kept (still used by the SDK and rpc2 trait emit paths in build/emit/rust_sdk.rs and build/emit/rust_rpc2.rs, which want a fully self-contained types file for separate WASM-targeted SDK crates).

Verification

  • Generator unit tests: 127 pass (125 prior + 2 new in rust_struct.rs::tests covering the dedup and the root-object cfg gating).
  • cargo build -p hero_recipes (native): clean; only pre-existing unused-import warning unchanged from prior behaviour.
  • cargo build -p hero_recipes_sdk --target wasm32-unknown-unknown: clean.
  • Standalone wasm32 build of the regenerated unified types_generated.rs in an isolated crate: clean.
  • hero_recipes itself does not build for wasm32 due to its tokio/runtime deps — same as prior behaviour, the cfg-gated types module compiles fine in isolation.

Acceptance

  • Fresh scaffold emits one types_generated.rs per domain — verified via the regenerated example/recipe_server/crates/hero_recipes/src/recipes/ (committed in aad13ff).
  • cargo build clean on native.
  • cargo build --target wasm32-unknown-unknown clean against the unified types file.

Ready for review.

Implemented on `lab/74-fold-wasm-types` ([compare](https://forge.ourworld.tf/lhumina_code/hero_rpc/compare/development...lab/74-fold-wasm-types)). ## Approach Added `generate_unified_rust_structs` in `crates/generator/src/rust/rust_struct.rs`. It builds both per-typedef outputs (via the existing native and wasm generators) and: - emits each typedef **once** with no `cfg` gating when the two outputs are byte-identical (the common case — enums, embedded structs); - emits each typedef **twice**, each gated by `#[cfg(target_arch = "wasm32")]` / its inverse, only when the shapes genuinely diverge (root objects: native adds `OsisObject` derive + injected `sid: SmartId` / `created_at: u64` / `updated_at: u64`; wasm keeps the schema fields as declared); - emits the wasm-only inline OTOML primitives (`OTime`, `OCur`, `OLocation`, `OAddress`) in a gated `__wasm_otoml` submodule; - gates the native-only `hero_rpc_osis::otoml::*` / `OsisObject` imports. `crates/generator/src/generate/rust_types.rs` now calls the unified emitter once per domain instead of emitting two parallel files, and cleans up any stale `types_wasm_generated.rs` left over from prior scaffold runs. The flat-layout `mod.rs` (`build/layout.rs`) and the per-domain `mod.rs` lose their target-arch branches — `types.rs` includes the unified file unconditionally and the cfg gating lives inside the generated file itself. `generate_rust_wasm_structs` is **kept** (still used by the SDK and rpc2 trait emit paths in `build/emit/rust_sdk.rs` and `build/emit/rust_rpc2.rs`, which want a fully self-contained types file for separate WASM-targeted SDK crates). ## Verification - Generator unit tests: 127 pass (125 prior + 2 new in `rust_struct.rs::tests` covering the dedup and the root-object cfg gating). - `cargo build -p hero_recipes` (native): clean; only pre-existing unused-import warning unchanged from prior behaviour. - `cargo build -p hero_recipes_sdk --target wasm32-unknown-unknown`: clean. - Standalone wasm32 build of the regenerated unified `types_generated.rs` in an isolated crate: clean. - `hero_recipes` itself does not build for wasm32 due to its tokio/runtime deps — same as prior behaviour, the cfg-gated types module compiles fine in isolation. ## Acceptance - [x] Fresh scaffold emits one `types_generated.rs` per domain — verified via the regenerated `example/recipe_server/crates/hero_recipes/src/recipes/` (committed in `aad13ff`). - [x] `cargo build` clean on native. - [x] `cargo build --target wasm32-unknown-unknown` clean against the unified types file. Ready for review.
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#74
No description provided.