Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Website for exploring router schema. Similar to GraphiQL #23

Open
oscartbeaumont opened this issue Jul 31, 2022 · 4 comments
Open

Website for exploring router schema. Similar to GraphiQL #23

oscartbeaumont opened this issue Jul 31, 2022 · 4 comments
Labels
long-term Things that aren't going to be fixed anytime soon but are nice to haves!

Comments

@oscartbeaumont
Copy link
Member

No description provided.

@oscartbeaumont oscartbeaumont mentioned this issue Aug 5, 2022
26 tasks
@marcustut
Copy link
Contributor

This idea is cool! Essentially sort of like a generated docs page for our API.

@oscartbeaumont
Copy link
Member Author

I thought so too! I have always loved using GraphQL Playground to explore the data before the frontend has been developed. It is something I can do in rspc because I have all of the types at runtime on the Rust side as required for the rest of the system to work. Something like trpc can't do the same thing because the types do not exist at runtime (in Javascript) although I am sure if they wanted to they could find a way to store them.

I have been working on this feature locally and have made some progress but I am not ready to publish it yet. Hopefully, it won't be long until an MVP of the playground is released.

@marcustut
Copy link
Contributor

marcustut commented Aug 8, 2022

Was looking into spacedrive and found this repo. I'm in the middle of building an API for personal use, and decided to use Rust as I wanted to learn the language.

I have used TRPC before and it was great to see there's an alternative in Rust, too. As for now, I'm playing around with the axum_handler. However, I'm wondering how does one pass a connection pool to the router, do we use the global context?

In axum we could use the Extension helper to achieve this, is there any ways we could leverage the Extension helper too in RSPC router?

    let router = rspc::Router::<Ctx>::new()
        .config(Config::new().export_ts_bindings("./generated/bindings.ts"))
        .query("version", |_, _: ()| env!("CARGO_PKG_VERSION"))
        .query("echo", |_, v: String| v)
        .query("error", |_, _: ()| {
            Err(rspc::Error::new(
                rspc::ErrorCode::InternalServerError,
                "Something went wrong".into(),
            )) as Result<String, rspc::Error>
        })
        .query("transformMe", |_, _: ()| "Hello, world!".to_string())
        .mutation("sendMsg", |_, v: String| {
            println!("Client said '{}'", v);
            v
        })
        .build()
        .arced();

    let cors = CorsLayer::new()
        .allow_methods(Any)
        .allow_headers(Any)
        .allow_origin(Any);

    let pool = MySqlPoolOptions::new()
        .max_connections(5)
        .connect(&env::var("DATABASE_URL")?)
        .await
        .expect("Failed to connect to database");

    let app = axum::Router::new()
        .route("/", get(|| async { "Hello 'rspc'!" }))
        .route(
            "/rspc/:id",
            router.clone().axum_handler(|Path(path): Path<String>| {
                println!("Client requested operation '{}'", path);
                Ctx {}
            }),
        )
        .route("/rspcws", router.axum_ws_handler(|| Ctx {}))
        .route("/expenses", get(get_expenses))
        .layer(cors)
        .layer(Extension(pool));

This above is my code at the moment.

@oscartbeaumont
Copy link
Member Author

You can technically use an Axum extractor (Path in that example could be an Extension extractor) but I think I am going to remove that within the week as I see it as an anti-pattern, it's less typesafe, is Axum specific (I want to support more webservers) and is hard to maintain on my end.

The best solution is to capture the variables into the axum_handler closure (ensure you have the move keyword on the closure) like .axum_handler(move || Ctx { db }). This will probably require your database to be Arced although if you're using a connection pool I would be surprised if this hasn't already been done for you. You can actually do this same thing in Axum handlers but it is less convenient so a lot of people use extensions that trades the conventience for a runtime time error if the expected extension does not exist. This page on the docs site explains why I took this approach for rspc.

I will get onto documenting this better because it seems to be something that many people have struggled with.

I would give #24 a look as it is someone with the same issue and refer to this example I created for that issue.

In Spacedrive we do:

tauri::Builder::default()
      .plugin(sdcore::rspc::integrations::tauri::plugin(router, {
	      let node = node.clone();
	      move || node.get_request_context()
      }))

And then node.get_request_contex() returns a struct containing the database (technically containing a thing to fetch the database because we use multiple but that's beside the point). The syntax shown in this example uses a scope that allows the node.clone(); to happen outside the closure as we use the node variable further down in the main function (where this snippit it from) and when you move a variable into a closure it can then only be used from within that closure unless you put it in an Arc which allows multiple references hence we run node.clone() for a new reference and move the reference into the closure.

@oscartbeaumont oscartbeaumont added the long-term Things that aren't going to be fixed anytime soon but are nice to haves! label Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
long-term Things that aren't going to be fixed anytime soon but are nice to haves!
Development

No branches or pull requests

2 participants