Expand description
The library-tier dev entry point — serve_app, the counterpart to
mesofact::serve_app for a consumer whose routes are Rust handlers.
This is the mesofact_dev::serve(app::router()) that W225 §2’s Consumer DX
sketch promised and that nothing implemented (R832-T1). The two thin bin
targets a library-tier project carries differ by one identifier:
// src/bin/yah-dashboard.rs — the binary CI ships
mesofact::serve_app(yah_dashboard::router(), addr).await
// src/bin/yah-dashboard-dev.rs — the binary you run locally
mesofact_dev::serve_app(yah_dashboard::router(), addr).await§What the dev half of a library-tier consumer actually is
R832-T1 existed because this was an open design question, and the answer is narrower than the standalone tier’s dev binary. Recorded here rather than in a doc, because the next person to add a dev affordance needs it:
The watcher and live-reload do not carry over, and cannot. Both are
functions of a built dist/ tree: crate::Watcher re-runs the bundler
and rotates dist into .mesofact-dev/gen-N, and the SSR pool is
re-spawned against the new generation. A library-tier consumer has no such
tree — its routes are Rust functions, and the only edit that changes one is
a .rs edit, which requires re-linking the very process that would have to
perform the reload. No in-process affordance can close that loop. The loop
is cargo watch -x 'run --bin <name>-dev', and it lives outside the binary
by necessity, not by omission.
The dev object store does carry over, and is the whole of the
difference. A handler that reads or writes R2 builds its store from
environment coordinates. In prod those point at Cloudflare R2; in dev a
running yah camp supplies a local dev-tier S3 driver and injects its
coordinates (R584-T1, W265) — precisely the “local pond emulation” W225 §2
puts in this crate to avoid re-deriving per consumer. DevServer::start
resolves the store (DevStore::resolve — the camp’s when a camp
injected one, an embedded surface otherwise),
DevServer::export_env republishes them under the R2_* names this
process’s own handlers expect, and .mesofact-dev/s3.json carries them for
out-of-process tooling (aws s3 --endpoint-url …, a test harness).
So mesofact_dev::serve_app is mesofact::serve_app plus a local R2 and a
banner. The smallness is the finding, not a shortfall. What the two-bin
pattern buys is the link-graph boundary (W225 §2, “always-release,
two-binary pattern”) — prod clean by construction because its dependency
closure cannot reach this crate — and that boundary is worth having on day
one, when the dev side adds a single service. Every dev affordance added
here later reaches consumers without any of them changing a line.
Not implemented, and deliberately not stubbed: permissive CORS and verbose
error overlays. W225 §2 lists both among the dev affordances, but neither
exists anywhere in mesofact today (no tower_http::cors use in either
crate), so there is nothing to lift — writing them here would be new
product, not an entry point over existing behaviour.
@arch:see(.yah/docs/working/W225-mesofact-consumer-deployment-model.md)
Structs§
Constants§
- DEV_
STATE_ DIR - Directory, relative to a project root, that holds dev-only scratch state —
the S3 surface’s backing store and its discovery file. The standalone tier’s
mes devuses the same name, so a project that starts standalone and grows a Rust half keeps one.gitignoreline.
Functions§
- serve_
app - Start the dev-tier services, publish their coordinates into the environment,
and serve
appuntil Ctrl+C or SIGTERM. The dev counterpart ofmesofact::serve_app, and the whole body of a library-tier project’ssrc/bin/<name>-dev.rs.