Version 0.3 makes failures visible and removes repeated code. Most apps compile without a change. The full list is in the changelog.
Changes that can need an edit
-
ViteManifest::loadand.parse()returnViteManifestError, notString. It implementsstd::error::Error, so?works withanyhowandBox<dyn Error>. Remove a.map_errthat you added for theString. -
The rejection of the
Inertiaextractor isMissingInertiaLayer, notStatusCode. This is important only if you name the rejection type. -
Props that do not serialize give a
500. Before, the page rendered withnullprops. -
The asset version of a production
ViteRootViewis the manifest hash when you set no version. If you have.version(move || hash.clone().into()), you can remove it. -
RequestInfo::refereris the path and query of theReferer, orNone. The scheme and the host are dropped, soback()always stays on your site. -
CsrfLayerchecks each method exceptGET,HEAD,OPTIONSandTRACE. -
Flash cookies from 0.2 are ignored after the upgrade (they live 60 seconds).
Recommended
- async fn users_store(inertia: Inertia, InertiaForm(body): InertiaForm<NewUser>) -> Response {
- if let Some(precognition) = inertia.precognition() {
- return precognition.respond(body.validate());
- }
- if let Err(errors) = body.validate() {
- return inertia.with_errors(errors).redirect("/users/new").into_response();
- }
+ async fn users_store(inertia: Inertia, Validated(body): Validated<NewUser>) -> impl IntoResponse {
create_user(body).await;
- inertia.redirect("/users").with_flash("success", json!("User created")).into_response()
+ inertia.redirect("/users").with_flash("success", "User created")
}InertiaConfig::share(|req| async { … })replaces.shared(shared_props_fn(…)). The closure can read request extensions:req.extension::<CurrentUser>().inertia.page(props)replacesinertia.render("Name", props)for a struct withregister_page!.ViteRootView::auto(manifest_path)replaces a hand-written switch betweendev()andproduction().InertiaConfig::version_str("v1")replaces.version(|| "v1".into()).- Call
veer::bindings::generate_splitat startup in a debug build; see TypeScript bindings. - Use
veer::testingin your tests.
Version 0.2 brings veer to the current Inertia v3 protocol (client 3.8). Most apps need the first two changes; the others apply only if you use the feature. The full list of additions is in the changelog.
Flash data is now the top-level flash field of the page object. This is what the v3 client expects: it does not keep flash in the browser history.
- const success = usePage().props.flash?.success;
+ const success = usePage().flash.success;No change on the Rust side: with_flash works as before.
If you use the ts feature, update ts-rs:
- ts-rs = "11"
+ ts-rs = "12"Then generate the bindings again. The generated PageObject and Flash types changed.
Not a veer change, but check it: axum 0.8 writes path parameters as /users/{id}, not /users/:id.
InertiaResponse::reset_merge and the resetMergeProps field were not part of the protocol. Delete the call. The client asks for a reset (router.reload({ reset: ['posts'] })), and veer then sends the prop without its merge label.
inertia.location(url) answers 409 + X-Inertia-Location only for an Inertia request. A plain browser request now gets a 302, which a browser can follow.
inertia.render(…).with_errors(errors) now shows the errors on that page. In 0.1 they went to the next page. with_errors(…).redirect(…) is unchanged.
errorsis always sent.- A partial reload with only
exceptreturns all other props (0.1 returned none). onlyandexceptaccept dot paths.- A prop that the response leaves out has no merge label.
If frontend code relied on the old behavior, check it.
Flash::errorsis nowHashMap<String, Vec<String>>: all messages of a field.Flashis#[non_exhaustive]and has new fields. Build it fromFlash::default(), and store the complete value;FlashimplementsSerializeandDeserialize.- A store must keep the data when a response that is not a page writes it back.
props::closure::{LazyProp, DeferredProp}are replaced byprops::Prop. The builder methodslazy,optionalanddeferredare unchanged.RequestInfoandPageObjectare#[non_exhaustive]. UseRequestInfo::from_partsandPageObject::new.protocol::ResponseShapehas new variants.props::resolver::resolvereturns aResult.
The DevTools recorder is behind the new devtools feature. Nothing changes if you do not enable it.
- Update the client to
@inertiajs/react(orvue3,svelte) 3.8. - Closure props can return typed values:
.once("plans", || async { load_plans().await }).json!is no longer necessary. - Give closure props TypeScript types with the third argument of
register_page!.