Expand description
§Rainier
A Laravel-shaped MVC framework for Rust, built on the Rainier ORM DBAL.
Rainier takes Laravel’s structures — a service container, service providers, a router with named routes and middleware groups, form requests, guards, jobs, mailables, facades, events — and gives each one a Rust shape rather than a transliterated PHP one. Where the two languages disagree, the disagreement is resolved in Rust’s favour and the reason is written down in the module that made the call.
use rainier_framework::prelude::*;
async fn index() -> &'static str {
"Hello from Rainier"
}
#[tokio::main]
async fn main() -> Result<()> {
let app = Rainier::new(".")
.with_routes(|router| {
router.get("/", index).name("home");
})
.boot()
.await?;
rainier_framework::console("rainier").run_from_env(&app).await;
Ok(())
}§The crates
Each component is its own crate, and depends only on what it genuinely needs — so an application that wants the queue but not HTTP pays for neither the router nor hyper.
| Crate | What it owns |
|---|---|
support | the error type, futures, type-maps, string inflection |
rainier_orm | the DBAL: entities, queries, DDL, sharding, the Executor port |
container | the IoC container, service providers, lifecycle hooks, facades |
config | the config repository and .env |
events | the event dispatcher — the hook bus |
http | requests, responses, cookies, uploads, extractors |
middleware | the handle(request, next) pipeline and the built-in set |
routing | route declaration, groups, resources, URL generation |
validation | rules, the validator, and request contracts |
view | the Blade-style template engine |
database | Rainier ORM integration, models, repositories |
auth | guards, user providers, hashing, gates |
queue | jobs, queue drivers, the worker |
mail | mailables, the mailer, transports |
server | the HTTP kernel and the hyper server |
console | the artisan-style console |
cache | the cache port and its drivers |
crypt | encryption and message signing |
drivers | shared Redis, Memcached and AWS transports |
filesystem | file storage: local, memory, S3/R2 |
notify | notifications: a message to a recipient, over their channels |
scheduler | cron expressions, the schedule, and its atomic locks |
session | the session bag, its store, and the middleware |
§Where Rainier departs from Laravel
- Middleware is named, not typed, at the route.
.middleware("auth")keepsroutingfrom depending onauth— seemiddleware::registry. - The auth manager is generic over the user model rather than erasing
it behind
dyn Authenticatable, because an application wants its own type back. Seeauth. - Model hooks can veto but not mutate. Several listeners mutating one
row in registration order would make the outcome depend on wiring; see
database::model. - Request bodies are buffered. That is what lets
request.input(..)be synchronous, as$request->input()is; seehttp::body. - Configuration is typed at both ends.
config('cache.driver')has a magic string for the path and another for the value. Rainier haskeys::CACHE_DRIVERand acache::CacheDriverenum, so a misspelled path does not compile and a misspelled driver fails the boot rather than silently caching in-process. Seekeys.
§The Rainier ORM Send story
Rainier ORM used to hold a sea_query statement across its awaits, which
made every repo:: future !Send — unusable inside a handler the server
will tokio::spawn, since sea_query statements hold Rc. That is fixed
upstream: statements are built and dropped in a scope that ends before the
await, and Query’s terminals consume self outside their async block
(an async fn captures every argument whether or not the body moves it
out).
So repo:: and the query builder work directly against a
database::Database. Rainier still renders its repository SQL
synchronously through database::statement — now a design choice that
keeps shard routing and dialect rendering explicit at the framework seam,
rather than a workaround.
One exception remains: rainier_orm::migrate::Migrator::run boxes its steps
behind dyn, so its future cannot be Send on stable.
database::Migrator is the Send alternative — it renders DDL
synchronously and executes plain strings, and its Migration contract
makes every step declare how to undo itself.
Re-exports§
pub use bootstrap::Rainier;pub use commands::console;pub use commands::KeyGenerateCommand;pub use commands::MigrateCommand;pub use commands::MigrateRollbackCommand;pub use commands::QueueWorkCommand;pub use commands::RouteListCommand;pub use commands::ServeCommand;pub use facades::Views;pub use queued_listeners::DispatcherExt;pub use queued_listeners::FromEvent;pub use scheduling::CommandTask;pub use scheduling::JobTask;pub use scheduling::ScheduleExt;pub use scheduling::ScheduleListCommand;pub use scheduling::ScheduleRunCommand;pub use scheduling::ScheduleWorkCommand;pub use testing::TestApp;pub use testing::TestResponse;pub use rainier_auth as auth;pub use rainier_broadcast as broadcast;pub use rainier_cache as cache;pub use rainier_config as config;pub use rainier_console as console_kernel;pub use rainier_container as container;pub use rainier_crypt as crypt;pub use rainier_database as database;pub use rainier_drivers as drivers;pub use rainier_events as events;pub use rainier_filesystem as filesystem;pub use rainier_http as http;pub use rainier_mail as mail;pub use rainier_metrics as metrics;pub use rainier_middleware as middleware;pub use rainier_notify as notify;pub use rainier_openapi as openapi;pub use rainier_queue as queue;pub use rainier_routing as routing;pub use rainier_scheduler as scheduler;pub use rainier_server as server;pub use rainier_session as session;pub use rainier_support as support;pub use rainier_telemetry as telemetry;pub use rainier_validation as validation;pub use rainier_view as view;pub use rainier_websocket as websocket;pub use rainier_orm;
Modules§
- binding
- Route-model binding — Laravel’s
public function show(Post $post). - bootstrap
- Bootstrapping —
Rainier, the builder that assembles an application. - broadcasting
- The half of broadcasting that needs HTTP: the authorisation endpoint, the socket header, and the notification channel.
- commands
- The commands Rainier ships —
route:list,serve,migrate,queue:work,key:generate. - facade
- Facades — static proxies onto container-resolved services.
- facades
- The facades — static proxies onto container-resolved services.
- groups
- The middleware groups Rainier ships — Laravel’s
webandapi, as functions rather than as keys in a map. - keys
- The configuration keys Rainier itself reads — a typed index of the tree.
- notifications
- The notification channel that needs a database.
- observability
- Metrics, tracing and the OpenAPI document, built from configuration.
- prelude
- Everything an application file usually wants in scope.
- queued_
listeners - Listeners that go on the queue —
DispatcherExtandFromEvent. - scheduling
- Scheduling — the tasks and commands that need more than the scheduler crate depends on.
- testing
- A test harness —
TestAppandTestResponse.
Macros§
- bind_
executor - Writes the
Connectionimpl for a concrete Rainier ORMExecutor. - facade
- Declare a facade type and its
Facadeimpl. - param_
key - Declare a route-parameter name for
BoundAs.
Structs§
- Application
- The application: a
Containerwith a boot lifecycle, an environment, and a filesystem layout.
Traits§
- Facade
- A static proxy onto a container-resolved service.
- Service
Provider - A bundle of related bindings and their boot-time wiring.