jigs-map 0.0.3

HTML map generator for jigs pipelines
Documentation
  • Coverage
  • 100%
    6 out of 6 items documented0 out of 3 items with examples
  • Size
  • Source code size: 43.93 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.46 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 43s Average build duration of successful builds.
  • all releases: 1m 36s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • ValeriaVG/jigs
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • ValeriaVG

jigs

⚠️ Very early stage. This project is in active, exploratory development and is nowhere close to being production ready. APIs will change, things will break, and entire ideas may be thrown out. Star it, watch it, play with it — but don't ship it.

A jig is a custom-made tool that controls the location or motion of other tools.

HTTP handlers, RPC services, agentic workflows, data pipelines and even event listeners all have the same shape: something comes in and, after several steps, something comes out.

And the more steps there are in this process, the harder it becomes to debug, fix and maintain the code that does it.

So jigs is a small Rust framework that lets you be explicit about your processing steps and write your code like this:

#[jig]
fn handle(request: Request) -> Response {
    request
        .then(log_incoming)
        .then(set_auth_state)
        .then(route_to_feature)
        .then(log_response)
}

Every step is a jig too, so you can compose processing pipelines of virtually any size.

The main advantage, though, is that jigs generates a graph of your codebase at compile time and lets you navigate it with ease.

Pipeline map

Install

cargo add jigs

To enable per-step tracing, turn on the trace feature:

cargo add jigs --features trace

Quickstart

use jigs::{jig, Request, Response};

#[jig]
fn validate(r: Request<u32>) -> Request<u32> { r }

#[jig]
fn handle(r: Request<u32>) -> Response<String> {
    Response::ok(format!("got {}", r.0))
}

fn main() {
    let response = Request(42u32).then(validate).then(handle);
    assert_eq!(response.inner.unwrap(), "got 42");
}

There are four kinds of jigs, distinguished by their input and output types:

Input Output Purpose
Request Request enrich, validate, transform
Request Response terminal handler
Response Response post-process the outgoing message
Request Branch<Req,Resp> guard that may short-circuit

The type system enforces ordering: once you hold a Response, you cannot chain a jig that expects a Request. Errored responses and Branch::Done short-circuit the rest of the pipeline.

See examples/ for sync, async, and HTTP usage.

Generate a map

Every #[jig] registers itself in a global inventory at link time, so you can render an interactive HTML map and a Markdown/Mermaid version straight from your code — no scanning, no build script.

use jigs::{jig, Request, Response};

#[jig]
fn validate(r: Request<u32>) -> Request<u32> { r }

#[jig]
fn handle(r: Request<u32>) -> Response<String> {
    Response::ok(format!("got {}", r.0))
}

fn main() -> std::io::Result<()> {
    let dir = env!("CARGO_MANIFEST_DIR");
    std::fs::write(
        format!("{dir}/map.html"),
        jigs::map::to_html(Some("handle"), "my service", None),
    )?;
    std::fs::write(
        format!("{dir}/map.md"),
        jigs::map::to_markdown(Some("handle"), "my service"),
    )?;
    Ok(())
}

The third argument to to_html is an optional editor URL template; pass e.g. Some("vscodium://file/{path}:{line}") for VSCodium, vscode://file/{path}:{line} for VS Code or Cursor, idea://open?file={path}&line={line} for JetBrains IDEs. With None the link falls back to file:// and opens with your OS default.

The Markdown form embeds a Mermaid flowchart that renders inline on GitHub — see examples/http/map.md.

Trace the exact steps in runtime

Things break, and the bigger the system, the harder it is to figure out where exactly things went wrong. jigs lets you pinpoint an error or a bottleneck with ease:

log_incoming     ✓  0.1ms
set_auth_state   ✓  2.3ms
route_to_feature ✗  ERROR 500
  └─ validate_route  ✓  0.4ms
  └─ check_permissions ✗  ERROR: DB Timeout

With the trace feature on, drain the per-thread buffer and render it in either of two formats:

let entries = jigs::trace::take();
print!("{}", jigs::log::render_tree(&entries));   // human-readable
print!("{}", jigs::log::render_ndjson(&entries)); // one JSON object per line

The NDJSON form is meant for automated log ingestion; each line carries name, depth, duration_ns, ok and an optional error message.

Everything agnostic

jigs works with any existing or future framework that has two distinct types for incoming and outbound messages. Check the examples to see it in action.

Roadmap

  • Basic functionality
  • Time tracing (behind the trace feature)
  • Logging utils (tree + NDJSON via jigs-log)
  • Generation of interactive map at compile time (see above)
  • Add more complex examples

Maybe Roadmap

  • Runtime tracing with interactive map
  • Ability to trace and view remote jigs services as one system

License

MIT — see LICENSE.