- Rust 92.4%
- JavaScript 4.7%
- HTML 2.7%
- Makefile 0.2%
Makes `lab blueprint --schemas-dir` emit a compiling, runnable approach-B service workspace (core + server + sdk) and recovers the generator/osis crates that despiegk's hero-lib-base merge left half-broken on development. Generator: - Wire the WorkspaceScaffolder to the openrpc_server! server emitter: generate_server_crate now emits main.rs + <dom>_impl.rs via generate::server_main, an oschema-backed Cargo.toml (no jsonrpsee/hero_rpc2), per-domain rpc_<dom>.sock service.toml, and copies the schema tree to oschema/. - Port the SDK emitter to herolib_macros::openrpc_client! over herolib_openrpc (dropped the deleted hero_rpc_derive/hero_rpc2 + the rhai sibling). - Port the tests-crate emitter to drive the typed SDK client (connect_socket), and the core crate Cargo.toml off the deleted hero_rpc2. - server_main: store structs now mirror the macro WIRE types (wire_type(): every integer width -> i64, floats -> f64, str -> String, optionals -> Option) so the CRUD arms convert wire<->store by identity move; resolve the OSIS data dir under PATH_ROOT at runtime. - Re-export the server_main emitter API from the crate root. - Restore the workspace [workspace.dependencies] the emitters reference. - Update unit tests + openrpc tests to the tightened contract (underscored CRUD, no _new, single-param methods, no schema-declared sid). osis (hero_rpc_osis): recover the build after the bad merge — - find is first-class (`pub mod find;` off src/find.rs, not the deleted hero_rpc2::find re-export); remove the dangling `pub mod rpc;`. - sid re-export sources herolib_oschema::types::SmartId (the SmartId the OsisObject derive + DBTyped are defined over), fixing wire<->store types. - _regex_for_codegen always available (generated FindParams use it). Workspace: re-enable generator/blueprinter/osis/openrpc_http_client_lib; rename herolib_derive -> herolib_macros throughout; drop the dead hero_rpc_derive crate (deleted upstream, resurrected by the bad merge). Gate: `cargo test -p hero_rpc_generator` green (151) + `--ignored emitted_main_compiles` green; a scaffolded hero_crm server boots and round-trips CRUD through OSIS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .cargo | ||
| .forgejo/workflows | ||
| .hero | ||
| benches | ||
| blueprints/service | ||
| crates | ||
| docs | ||
| examples | ||
| tests | ||
| .gitignore | ||
| BENCH_RESULTS.md | ||
| Cargo.toml | ||
| GETTING_STARTED.md | ||
| OPTIMIZATION_FINDINGS.md | ||
| README.md | ||
| REFACTOR_INSTRUCTIONS.md | ||
Hero RPC
Schema-driven code generation and scaffolding for building distributed Hero
services. Define your data model in .oschema files, and Hero RPC scaffolds a
complete workspace: SmartID storage types, an OSIS-backed JSON-RPC server, an
admin dashboard, a public web surface, and a typed client SDK — all built on the
hero_lib runtime + macros (herolib_derive::openrpc_server! /
openrpc_client!, hero_lifecycle, herolib_oschema_server).
Architecture (post hero_lib-base refactor): this repo no longer ships its own RPC transport or server runtime. The RPC surface — wire types, the service trait, dispatch, the
serve_domainslauncher, and the client transport — is generated by hero_lib's macros and run byhero_lifecycle. This repo owns only what is unique to it: the OSIS data+index layer, the schema-driven code generator, and the blueprint templates. SeeREFACTOR_INSTRUCTIONS.md.
Packages
| Crate | Description |
|---|---|
hero_rpc_osis |
OSIS — the blueprint-unique data layer: SmartID storage (DBTyped), OTOML serialization, the OSchema language re-exports, and an optional index feature for full-text _find via the hero_indexer service. No RPC/server runtime (that lives in hero_lib). |
hero_rpc_generator |
Schema-driven workspace scaffolder library — emits the full Hero service tree (server + admin + web + sdk) from .oschema files, targeting hero_lib's openrpc_server!. |
blueprinter |
Tera-based template engine the lab blueprint CLI runs on; consumes either the template tree at blueprints/ or the schema-driven path (delegates to hero_rpc_generator). |
hero_rpc_client |
Cross-platform HTTP/WASM RPC client for generated services (native transport via herolib_openrpc). |
The RPC macros (openrpc_server!, openrpc_client!, rhai_openrpc!,
#[derive(OsisObject)]) and the server/transport runtime come from hero_lib
(herolib_derive, hero_lifecycle, herolib_oschema_server, herolib_openrpc).
How It Works
1. Define your schema
Create .oschema files that describe your data model:
Difficulty = "easy" | "medium" | "hard"
# Recipe [rootobject]
Recipe = {
sid: str
@index
name: str
@index
description: str
difficulty: Difficulty
prep_time: u32
ingredients: [str]
created_at: otime
}
service RecipeService {
version: "1.0.0"
description: "Recipe management"
get_by_category(category: Category) -> [Recipe]
}
2. Scaffold a workspace
Generate a complete 6-crate workspace (lib + server + admin + web + sdk
- benches + tests + .forgejo) from your schemas via
lab(fromhero_skills):
lab blueprint --dst ./hero_recipes --name hero_recipes --schemas-dir schemas
The schema-driven path runs whenever --schemas-dir is set; without it
lab blueprint falls back to the Tera template tree under
blueprints/service/ (the bare service skeleton). Either way the work
is done by libraries exposed by this repo —
hero_rpc_generator::build::WorkspaceScaffolder for the schema path
and blueprinter::expand for the template path. lab just drives the
CLI; the engines and the canonical templates live here.
This creates:
hero_recipes/
├── Cargo.toml # Workspace root
├── schemas/
│ └── recipes/recipes.oschema
├── crates/
│ ├── hero_recipes/ # Core types + DB persistence
│ │ ├── Cargo.toml
│ │ └── build.rs # Code generation on cargo build
│ ├── hero_recipes_server/ # JSON-RPC server binary
│ │ ├── Cargo.toml
│ │ └── src/main.rs
│ ├── hero_recipes_client/ # Cross-platform client SDK
│ │ └── Cargo.toml
│ ├── hero_recipes_rhai/ # Rhai scripting bindings
│ │ ├── Cargo.toml
│ │ └── src/lib.rs
│ └── hero_recipes_admin/ # Admin panel (Unix socket)
│ ├── Cargo.toml
│ └── src/main.rs
3. Build and run
Use Nu shell to build and manage generated services:
cargo build -p hero_recipes # Generates types + handlers
service recipes install # Build + install binaries
service recipes start # Start via hero_proc
service recipes start --update # Rebuild, reinstall, restart
service recipes start --update --reset # Rebuild + reset data
service recipes stop # Stop via hero_proc
service recipes status # Check status
The server exposes a single unified Unix socket:
$HERO_SOCKET_DIR/hero-recipes/rpc.sock (default: ~/hero/var/sockets/hero-recipes/rpc.sock)
All domains, management methods, and discovery are served through this one socket:
POST /rpc— JSON-RPC 2.0 API with CRUD operations per root objectGET /health— Health checkGET /openrpc.json— OpenRPC specificationGET /.well-known/heroservice.json— Discovery manifest
Context isolation is handled via the X-Hero-Context header (integer, default 0 = admin).
4. Use the client
Generated client code provides typed access:
use hero_recipes_client::RecipeClient;
let client = RecipeClient::new("http://localhost:8080", "root", "recipes")?;
let recipes = client.recipe_list().await?;
Package Details
hero_rpc_osis
The core framework. Handles:
- OSchema parsing — Reads
.oschemafiles and produces an AST - Code generation — Generates Rust types, server handlers, client SDKs, and Rhai bindings via
build.rs - SmartID (SID) — 4-6 character base-36 distributed identifiers for all objects
- Filesystem persistence — OTOML-format storage with directory-based organization (
DBTyped<T>) - SmartID — short, collision-free base-36 IDs, shared with hero_lib (
herolib_oschema::types::SmartId) - Optional full-text
_find— theindexfeature wires@indexfields to the hero_indexer service - Workspace scaffolding —
lab blueprint --schemas-dir <dir>drivesWorkspaceScaffolderfromhero_rpc_generatorto emit a complete service workspace
Feature flags on hero_rpc_osis:
index— async full-text_findviahero_indexer_sdk(pulls tokio + tracing)rhai— Rhai scripting bindings for the local storage APItest-support— tempfile-backed ephemeral helpers
The RPC server runtime is no longer in this repo. Serving an OSIS-backed service goes through hero_lib:
herolib_derive::openrpc_server!generates the trait + dispatch +serve_domainslauncher, the generatedimpl …Apidelegates toDBTyped, andhero_lifecycleruns it.
Generated client (from hero_lib)
The typed client is generated by herolib_derive::openrpc_client! over the
herolib_openrpc transport (UDS-HTTP). The generated <Svc>Client owns its
transport and exposes a method per RPC method:
let client = MyServiceClient::connect_socket("my_service/rpc.sock").await?;
let entries = client.entry_list(Default::default()).await?;
hero_rpc_client (this repo) remains as a lightweight cross-platform
(native + WASM) client used by generated SDKs where a hand-rolled client is
needed; its native transport is herolib_openrpc::OpenRpcTransport.
Architecture
.oschema files
│
├──→ hero_rpc_generator ──→ scaffolds the service workspace:
│ (WorkspaceScaffolder) server + admin + web + sdk crates
│
└──→ at build/serve time, hero_lib macros do the rest:
herolib_derive::openrpc_server! → wire types + trait + dispatch + serve_domains
herolib_derive::openrpc_client! → typed client over herolib_openrpc
hero_lifecycle → socket bind, --info, lifecycle
hero_rpc_osis (this repo) → DBTyped storage behind the trait impl
Code generation flow:
build.rsin the core crate callsOschemaBuilder::generate()- OSchema files are parsed into an AST
- Rust types with
#[derive(OsisObject)]are generated for each root object - Server handlers (CRUD + custom methods) are generated for the
_servercrate - Client methods are generated for the
_clientcrate - OpenRPC specification JSON is emitted alongside
Runtime flow:
_serverbinary starts, creates a single Unix socket per service- Registers domain handlers with the unified Axum JSON-RPC router
- Context isolation via
X-Hero-Contextheader (integer: 0 = admin, ≥1 = user) hero_routermaps external TCP to service sockets (services never open TCP ports)_clientSDK connects via HTTP and sends JSON-RPC 2.0 requests
Building
cargo check --workspace
cargo build --workspace
Note: This repo uses Nu shell scripts for all build and lifecycle management. Makefiles and bash scripts are not used. Do not add them.
Requirements
- Rust 1.93.0+
- Edition 2024
- Nu shell for service lifecycle management
Related Projects
- hero_lib — Core Rust libraries (otoml, derive, sid, infra)
- hero_skills — Hero service conventions (hero_sockets, hero_context, hero_proc_sdk)
- hero_proc — Process supervisor and lifecycle manager
Architecture Decision Records
- ADR 001: Configurable Socket and Data Paths
- ADR 002: Single Source of Truth — Types, CRUD, and Seeding
License
Apache-2.0