From 0f5722e0910b4e09b81e47cc41ddb88c072c5692 Mon Sep 17 00:00:00 2001 From: Jacob Sapoznikow Date: Wed, 10 Jul 2024 21:04:37 +0000 Subject: [PATCH] more rpc-rs stuff --- Cargo.toml | 2 +- crates/rpc-rs/Cargo.toml | 1 + crates/rpc-rs/README.md | 85 ++----------------------------------- crates/rpc-rs/src/macros.rs | 3 ++ 4 files changed, 9 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e30fee3..a7688c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,7 +148,7 @@ webui = { path = "./apps/webui" } bindings = { path = "./apps/bindings" } commands = { path = "./crates/commands" } plugins = { path = "./crates/plugins" } -rpc-rs = { path = "./crates/rpc-rs", features = ["axum", "tauri"] } +rpc-rs = { path = "./crates/rpc-rs", features = ["axum", "tauri", "prisma"] } [workspace] resolver = "2" diff --git a/crates/rpc-rs/Cargo.toml b/crates/rpc-rs/Cargo.toml index afb432b..4bf1ae9 100644 --- a/crates/rpc-rs/Cargo.toml +++ b/crates/rpc-rs/Cargo.toml @@ -11,6 +11,7 @@ authors.workspace = true default = [] axum = ["dep:axum", "dep:http-body-util"] tauri = ["dep:tauri"] +prisma = [] [dependencies] specta.workspace = true diff --git a/crates/rpc-rs/README.md b/crates/rpc-rs/README.md index 0635cf3..f7a00b6 100644 --- a/crates/rpc-rs/README.md +++ b/crates/rpc-rs/README.md @@ -10,88 +10,10 @@ for use with Web technologies, such as JavaScript and TypeScript. It follows the CRUD (Create, Read, Update, Delete) pattern, and its syntax allows developers to easily create complex applications with relatively simple code. -## Syntax +## Examples -```rust -//! This code may not be completely accurate! I haven't yet built the library and this -//! is all plans! I also don't have ANY intellisense in a markdown file, so I can't check -//! for dumb syntactical errors! - -use std::sync::Arc; -use serde::{Serialize, Deserialize}; -use specta::Type; -use database::{prisma::{PrismaClient, game}, Game}; -use rpc_rs::{Router, Module, ModuleBuilder, PrismaObject}; - -// The `PrismaObject` derive macro and trait handle the `db_params` function, -// which transforms this struct into a `Vec`. This struct is also -// read from the request body via Serde, hence the `Deserialize` derive macro -// being used here. The `#[prisma(module = ...)]` helper ensures that the derive -// macro finds the correct place to resolve all of the `SetParam` creation -// functions. -#[derive(Debug, Clone, Serialize, Deserialize, Type, PrismaObject)] -#[prisma(module = "database::prisma::game")] -pub struct GameCreation { - pub name: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub curseforge: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub thunderstore: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub spacedock: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub ckan: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub modrinth: Option, -} - -pub fn games_module(mut module: ModuleBuilder>) -> Module> { - module - // This closure is: FnMut(ModuleBuilder::State, GameCreation) -> impl Future> + Send + Sync + 'static - // The error conversion is handled automatically (via traits) - .create(|db, data: GameCreation| (async move { - // [C]RUD - db.game().create(data.name.clone(), data.db_params()).exec().await - })()) // <- Async closures have to be executed to get the `impl Future<...>`. - // This closure is: FnMut(ModuleBuilder::State, i32) -> impl Future> + Send + Sync + 'static - .read(|db, id: i32| (async move { // The `id: i32` can be `_: ()` if you don't need any input here. - // C[R]UD - db.game().find_first(vec![game::id::equals(id)]).exec().await - })()) - .update(...) // Insert your own functionality here. - .delete(...) - // All the operations get assigned to the `Option<...>` fields in the `ModuleBuilder` - // struct. These will get reassigned to the ones in the `Module` struct and finalized - // when the `build` method is called. - .build() -} - -pub fn build_router() -> Router> { - Router::>::new() - .attach(games_module) // Accepts: FnOnce(ModuleBuilder) -> Module - // This closure is: FnMut(Router::State, ()) -> impl Future, Error>> + Send + Sync + 'static - .query("games", |db, _: ()| (async move { // This is useful if you just need a read function. - db.game().find_many(vec![]).exec().await - })()) - // The `finish` function finalizes all the state holders and prepares it to be - // mounted with either `axum` or `tauri`. - .finish() -} - -#[tokio::main] -pub async fn main() { - let router = build_router(); - let db = Arc::new(PrismaClient::_builder().build().await.unwrap()); - // Creating the endpoint for axum or the plugin for tauri requires the state object. - let endpoint = router.axum(db); - - let router = ...; // Axum stuff. - - router.nest("/rpc", endpoint); - - // Start your app with axum! -} -``` +See [here](https://github.com/RedstoneWizard08/Wormhole/blob/main/crates/commands/src/router.rs) +for a great example of how to use this library. ## Integrations @@ -102,3 +24,4 @@ rpc-rs integrates extremely well with the following libraries and tools: - `specta` - `serde` - `serde_json` +- `prisma-client-rust` (Custom build) diff --git a/crates/rpc-rs/src/macros.rs b/crates/rpc-rs/src/macros.rs index e2e8ff1..4e7b21c 100644 --- a/crates/rpc-rs/src/macros.rs +++ b/crates/rpc-rs/src/macros.rs @@ -8,6 +8,7 @@ /// - `module` - The path to the module inside the generated `prisma` mod. /// - `container` - The module's name. If you use `client.xxx.create(...)`, the container would be `xxx`. /// - `primary_key` - The name of the model's primary key. +#[cfg(feature = "prisma")] #[macro_export] macro_rules! prisma_single_module { { @@ -64,6 +65,7 @@ macro_rules! prisma_single_module { /// - `module` - The path to the module inside the generated `prisma` mod. /// - `container` - The module's name. If you use `client.xxx.create(...)`, the container would be `xxx`. /// - `primary_key` - The name of the model's primary key. +#[cfg(feature = "prisma")] #[macro_export] macro_rules! prisma_multi_module { { @@ -111,6 +113,7 @@ macro_rules! prisma_multi_module { /// - `module` - The path to the module inside the generated `prisma` mod. /// - `container` - The module's name. If you use `client.xxx.create(...)`, the container would be `xxx`. /// - `primary_key` - The name of the model's primary key. +#[cfg(feature = "prisma")] #[macro_export] macro_rules! prisma_module { ($router: ident += [$single: expr, $multi: expr] {