Movatterモバイル変換


[0]ホーム

URL:


Extra
rspc Integration

rspc Integration

Prisma Client Rust has first-class support forrspc (opens in a new tab),a server-agnostic router that can automatically generate TypeScript bindings.

The examples use the following schema:

modelPost {    idString@id@default(cuid())    titleString    comments Comment[]}modelComment {    idString@id@default(cuid())    contentString    post   Post@relation(fields: [postID], references: [id])    postIDString}

Setup

When therspc feature is enabled for bothprisma-client-rust andprisma-client-rust-cli,all data types generated by PCR will implementspecta::Type,and aFrom<queries::Error> implementation is generated forrspc::Error.

Queries

The following is possible when combining PCR and rspc:

use rspc::Router;fnmain()->Router {Router::<prisma::PrismaClient>::new().query("posts",|db, _: ()|asyncmove {let posts= db.post().find_many(vec![]).exec().await?;Ok(posts)        }).build()}

When TypeScript is generated it will look something like this:

exporttypeOperations= {    queries: { key: ["posts"], result:Array<Post> }};exportinterfacePost { id:string, title:string }

This also works forselect & include:

use rspc::Router;fnmain()->Router {Router::<prisma::PrismaClient>::new().query("posts",|db, _: ()|asyncmove {let posts= db.post().find_many(vec![]).select(post::select!({                    id                    title                })).exec().await?;Ok(posts)        }).build()}

The generated TypeScript will look something like this:

exporttypeOperations= {    queries: { key: ["posts"], result:Array<{ id:string, title:string}> }};

As of 0.6.4, dedicated types will be generated for named include/selects.These are only provided for extenuating cirsumstances though,and it is instead recommended that you use helpers fromrspcsuch asrspc.inferProcedureResult to access procedure resultsinstead of relying on the named types.

Relation types

It is important to note that the types generated for models do not have fields for relations.This is done to provide a better experience when usinginclude,at the expense of a worse experience usingwith/fetch for fetching relations.

This tradeoff was made as a result of our experience buildingSpacedrive (opens in a new tab).Instead of all our TypeScript functions having to verify at runtime whether a relation had been loaded or not,as is the case when usingwith/fetch,each function has to explicitly specify the relations it wants loaded:

import { User, Post }from"./exported-types"// Only recieves scalar fields of UserfunctionneedsOneUser(user:User) {}// Receives scalar fields + posts relation of UserfunctionneedsOneUserWithPosts(user:User& { posts:Post[] }) {}

There are a few downsides to this approach:

  • It is necessary to know the name and type of the relation you are including in TypeScript(though this is being worked on)
  • with/fetch can be modified dynamically
  • with/fetch provides better editor autocomplete

However, we've found that these downsides are outweighed by the benefits of having full type-safety across your backend and frontend.

Error Handling

Sincerspc::Error can implementFrom<queries::Error>,all of Rust's regular error handling conventions are available.

The? operator can be used to extract success values and return early if an error is encountered,automatically converting the Prisma error to an rspc error.This has the problem of needing to wrap the extracted value inOk before return from a resolver.

Another approach is adding.map_err(Into::into) before returning from a resolver.This causes the Prisma error to be converted to an rspc error while keeping the Result intact,as demonstrated below:

use rspc::Router;fnmain()->Router {Router::<prisma::PrismaClient>::new().query("posts",|db, _: ()|asyncmove {            db.post().find_many(vec![]).exec().await.map_err(Into::into)        }).build()}

For specifics on error handling in rpsc, seethe documentation (opens in a new tab).

MigrationsQuery Traits

[8]ページ先頭

©2009-2025 Movatter.jp