Expand description
The AI-native Rust backend platform. Generated apps depend on this one
crate (plus tokio) and write use jerrycan::prelude::*;.
The CLI/MCP binary joins this package in Phase 1 behind a cli feature.
Re-exports§
pub use jerrycan_db as db;
Modules§
- app
App(spec §4.1): assembles mounted modules + app-level routes, validates the route table at build time (fail loud), and dispatches requests.- clock
- Injectable time. Handlers/extensions take
Dep<Clock>and callnow(); tests control it viaTestApp::clock().advance(..). The serve engine’s own timeouts deliberately stay on real tokio time — Clock is for DOMAIN time (rate windows, schedules, expiry), not transport timeouts. - cors
- CORS (spec §v2.2). Lives in core because preflight must be answered BEFORE
routing (an
OPTIONSto a method-mismatched route is rejected 405 before any middleware runs), so CORS is a pre-routing + response-decoration concern integrated intoroute_policy/dispatch in later tasks — not aMiddleware. - dep
- Dependency injection (spec §4.3) — async, nested, per-request memoized,
override-able in tests. Resolution order: cache → overrides → singletons → factories.
Singletons and factories are disjoint by construction (
insert_value/insert_factoryeach remove the opposite key), so there is no singleton-vs-factory tiebreak to define. - error
- jerrycan’s single error type. Every error carries a stable
code(JC####) that maps to a documentation anchor — the error-driven-docs contract (spec §8). - extract
- Request context and extractors (spec §4.1). Everything a handler needs is
visible in its signature; each parameter implements
FromRequest. - handler
- Handler abstraction (spec §4.1): a handler is a plain async fn whose
parameters implement
FromRequestand whose return implementsIntoResponse. Extraction failures short-circuit into error responses. - http
- A general purpose library of common HTTP types
- middleware
- Middleware (spec §4.1):
async fn handle(&self, ctx, next). Composable, ordering explicit, no tower, no magic. - module
Module(spec §4.2): the unit of routing, packaging, and ownership. Bundles routes, nested subroutes, module-scoped dependencies and middleware. Flattening composes URL prefixes and layers environments (inner wins).- multipart
multipart/form-data(RFC 7578). The parser half is a pure incremental state machine — fed chunks, drained as events, no IO — so the grammar is unit-testable at every chunk straddle and fuzzable in isolation (fuzz/fuzz_targets/multipart_parse.rs). The extractor half (Task 7) adapts it to the request body lanes.- platform
- The jerrycan platform: shared core consumed by both the CLI (main.rs) and the MCP server (platform::mcp). One pipeline, two renderings (cli-ux.md).
- prelude
- response
- Response model. Handlers return anything implementing
IntoResponse;Result<T, Error>renders errors as{"code","message"}JSON (spec §4.1). - router
- Method routing + segment trie with
{param}captures (spec §4.1). Conflicting routes are detected at build time — fail loud before serving. Path segments are percent-decoded after ‘/’-splitting; malformed encodings surface asRouteMatch::Malformed(a clean 400, never a panic). - serde_
json - Serde JSON
- serde_
urlencoded x-www-form-urlencodedmeets Serde- test_
client - In-memory test client (spec §4.1 “Test client”): no sockets, no network.
override_depis THE testing seam — fake any dependency, run real requests.
Macros§
- path_
param #[macro_export]landspath_param!at thejerrycan_corecrate root; this re-export makesjerrycan::path_param!resolve through the facade. Admit a custom newtype as aPathparameter. The type must implementFromStrwith aDisplayerror; a parse failure maps to the sameJC0400invalid-path-parameter error the built-in impls produce.
Structs§
- App
- The application builder. Generated
app/src/main.rsis exactly this: provide app-level deps, mount modules, serve. - Body
Error - Mid-stream body failure. Reaching hyper as a body error aborts the connection, so the client sees a truncated (invalid) chunked stream rather than a clean end — truncation must be detectable.
- Body
Sender - Push side of
StreamBody::channel. - Built
App - The frozen, immutable runtime form. Cheap to share across connections.
- Clock
- An injectable source of “now”. Cloning is cheap and, for a test clock, shares the same controllable offset — so a handle handed to a test moves in lockstep with the clock the handler resolves.
- Cors
Config - CORS policy. Build with
CorsConfig::new(origins), chain options, install withApp::cors(config). - Created
- 201 Created with a JSON body.
- Dep
- A resolved dependency. Derefs to
T; cloning isArc-cheap. - Error
- The one error type of the framework (spec §4.1 “Errors”).
- Headers
- Read-only access to request headers in a handler signature.
- JcBody
- The response body: a fixed buffer for buffered handlers, or a stream when a
handler returns
StreamBody(downloads, exports). Wraps aBoxBodyso the response type is stable whichever shape the body takes; its error channel isBodyError, which a mid-stream failure rides to abort the connection. - Json
- JSON body wrapper:
Json(value)serializes withapplication/json. - Method
Router - Per-path method table:
get(list).post(create)(spec §4.1). - Module
- Flask’s Blueprint, Rust-grade. Built by route crates’
pub fn module(). - Multipart
- Streaming
multipart/form-dataextractor. Parts arrive in wire order and must be consumed sequentially;next_partdiscards any unread remainder of the previous part. Requirescontent-type: multipart/form-datawith a valid boundary — anything else is415 JC0415. - Next
- The remainder of the middleware chain plus the endpoint handler.
- NoContent
- 204 No Content.
- Path
- Typed path parameter:
Path<i64>binds the LEAF-MOST (last) captured parameter; use a tuple to address all parameters root→leaf —Path<(A, B)>/Path<(A, B, C)>grab two/three{param}s in route order. Param types are the sealedPathParamset (integers,String,bool, floats,char); custom newtypes opt in through thepath_param!macro. - Path
Params - A by-name view of the request’s captured path parameters. Where
Path<T>binds positionally (the leaf-most segment, or a root→leaf tuple),PathParamsreads a SPECIFIC mount param BY NAME — the accessor a DI factory needs, since a factory resolves each argument throughFromRequestand cannot borrow&RequestCtxto callRequestCtx::param. The membership-verifying tenancy guard uses it to read the tenant fkclub_idunder/clubs/{club_id}even when a leaf{id}follows (issues #78/#79). Rejects a task context (JC1003), like every other HTTP-coupled extractor. - Query
- Typed query string:
Query<MyParams>via serde. - RawBody
- The request body as EXACT bytes — the extractor for webhook signature
verification, where the digest must cover the wire bytes, not a re-serialized
value. Works on buffered routes (cheap clone) and
stream_body()routes (drains and caches). See the auth docs for the Stripe/Twilio recipes. - Redirect
- An HTTP redirect: an empty body plus a
Locationheader and a 3xx status. Use the constructor that names the semantics you want —to/see_other/temporary/permanent— rather than hand-setting a status code. - Request
Ctx - The mutable view of one in-flight request. Handlers receive extractors, not this type; middleware and the DI resolver work through it.
- Stream
Body - A streaming response body: downloads, CSV exports, anything produced
incrementally. Defaults:
application/octet-stream, 200 OK, 30s frame timeout (a producer that stalls longer aborts the connection). - Task
Context - Resolve dependencies OUTSIDE an HTTP request — background jobs, startup
wiring, CLI commands. Built from
BuiltApp::task_context. - TestApp
- Test
Part - One part for
TestApp::post_multipart. - Test
Response
Enums§
- Cors
Origins - Which origins may make cross-origin requests.
Traits§
- Extension
- Spec §6: capabilities register through one seam. An extension receives the builder and returns it — providers, routes, middleware, anything.
- From
Request - Types that can be produced from the request. Implemented by all extractors
and by
Dep<T>(seedepmodule). - Handler
- Implemented for async fns of arity 0..=8 over
FromRequestparameters. - Into
Response - Conversion of handler return values into HTTP responses.
- Middleware
- Wraps request handling. Call
next.run(&mut *ctx).awaitto continue; return early to short-circuit (auth rejections, rate limits, …).
Functions§
- delete
- get
- now_
rfc3339 - The current UTC instant as an RFC3339 string with seconds precision and a
Zsuffix (e.g.2026-07-26T12:34:56Z) — the exact shape jerrycan’sdatetimefields ride as (String) and the OpenAPI/fixture format uses. - patch
- post
- put
Type Aliases§
- Middleware
Future - Boxed future returned by middleware. The lifetime ties to the request.
- Response
- The concrete response type. Streaming bodies ride the same
IntoResponseseam as buffered ones, so handler signatures won’t change. - Result
- Convenience alias used across jerrycan and generated apps.
Attribute Macros§
- main
#[jerrycan::main]— boots the async runtime aroundasync fn main. Delegates to#[tokio::main]; the app must (and generated apps do) depend on tokio directly. The user’s tokens pass through UNCHANGED, preserving their spans so compiler diagnostics point at the user’s code, not at this attribute.