Skip to content

Commit

Permalink
general improvements and restructure of the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Sep 29, 2022
1 parent 03a0515 commit 9b42e66
Show file tree
Hide file tree
Showing 23 changed files with 493 additions and 354 deletions.
5 changes: 4 additions & 1 deletion README.md
@@ -1,3 +1,6 @@
<p align="center">
<img width="150" height="150" src="/docs/public/logo.png" alt="Logo">
</p>
<h1 align="center">rspc</h1>
<p align="center">🚧 Work in progress 🚧</p>
<div align="center">
Expand Down Expand Up @@ -33,7 +36,7 @@

## Example

You define a `rspc` router and attach resolvers to it like below. This will be very familiar if you have used [trpc](https://trpc.io/) or [GraphQL](https://graphql.org) before.
You define a `rspc` router and attach procedures to it like below. This will be very familiar if you have used [trpc](https://trpc.io/) or [GraphQL](https://graphql.org) before.

```rust
let router = <rspc::Router>::new()
Expand Down
6 changes: 1 addition & 5 deletions docs/markdown/breaking-changes.md
Expand Up @@ -5,7 +5,7 @@ index: 3

# 0.0.5 to 0.0.6 - rspc

This release comes with a huge amount of breaking changes. These changes are going to allow for many benefits in the future such as a rich plugin ecosystem. If your having trouble upgrading open a GitHub Issue or jump in the Discord server.
This release comes with a huge amount of breaking changes. These changes are going to allow for many benefits in the future such as a rich plugin ecosystem. If your having trouble upgrading open a GitHub Issue or jump in the Discord server. New [rspc vscode extension](https://marketplace.visualstudio.com/items?itemName=oscartbeaumont.rspc-vscode) too!

### Httpz integration

Expand All @@ -30,10 +30,6 @@ const client = createClient<Operations>({
});
```

#### Axum extractors

TODO - Document changes here - Currently `cookies` can be access from `httpz` but not access through `TCtx` because it doesn't satisfy `'static`.

### New Typescript bindings format

The internal format of the generated Typescript bindings has changed. The import has also changed so ensure you update your code as follows.
Expand Down
25 changes: 20 additions & 5 deletions docs/markdown/client/index.md
@@ -1,7 +1,7 @@
---
title: Create Vanilla Client
header: Vanilla Client
index: 20
index: 30
---

The vanilla client allows you to consume your API on the frontend. This client is the minimal core and it is recommended that you use the [React](/client/react) or [Solid](/client/solid) integration for building application.
Expand All @@ -12,7 +12,7 @@ To get started first install the minimal runtime package.
npm i @rspc/client
```

Next you need to export the Typescript bindings from your `rspc::Router` by using either [export_ts_bindings](/server/router#export_ts_bindings) or [export_ts](/server/router#exporting-the-typescript-bindings).
Next you need to export the Typescript bindings from your `rspc::Router` by using either [export_ts_bindings](/server/router#exporting-the-typescript-bindings) or [export_ts](/server/router#exporting-the-typescript-bindings).

```rust
let router = <rspc::Router>::new()
Expand All @@ -39,8 +39,23 @@ const userOne = await client.query(["getUser", 1]);
const userTwo = await client.mutation(["addUser", { name: "Monty Beaumont" }]);
```

[View full example](https://github.com/oscartbeaumont/rspc/tree/main/packages/example/react.tsx)
# Transports

## Websockets
rspc has multiple different transports which can be used.

TODO: Document using websocket transport
```ts
import { createClient, FetchTransport, WebsocketTransport, NoOpTransport } from "@rspc/client";
import type { Procedures } from "./bindings.ts"; // The bindings exported from your Rust code!

const fetchClient = createClient<Procedures>({
transport: new FetchTransport("http://localhost:4000/rspc"),
});

const wsClient = createClient<Procedures>({
transport: new WebsocketTransport("ws://localhost:8080/rspc/ws"),
});


const noOpClient = createClient<Procedures>({
transport: new NoOpTransport(),
});
1 change: 1 addition & 0 deletions docs/markdown/client/react.md
@@ -1,5 +1,6 @@
---
title: React
index: 31
---

rspc can be used on the frontend with [React](https://reactjs.org) via the powerful [React Query](https://tanstack.com/query/v4) library which provides caching, refetching and a lot more.
Expand Down
3 changes: 2 additions & 1 deletion docs/markdown/client/solidjs.md
@@ -1,8 +1,9 @@
---
title: SolidJS
index: 32
---

rspc can be used on the frontend with [SolidJS](https://www.solidjs.com/) via [solid-query](https://github.com/ardeora/solid-query) which provides caching, refetching and a lot more.
rspc can be used on the frontend with [SolidJS](https://www.solidjs.com/) via [Tanstack Solid Query](https://tanstack.com/query/v4/docs/adapters/solid-query) which provides caching, refetching and a lot more.

To get started first install the required packages.

Expand Down
@@ -1,11 +1,13 @@
---
title: Deployment
index: 53
---

Coming soon...
## Coming soon...

We will document how to deploy an rspc API to:

- [Vercel Functions](https://vercel.com/docs/concepts/functions) - Tracked in issue [#9](https://github.com/oscartbeaumont/rspc/issues/9)
- [Netlify Functions](https://www.netlify.com/products/functions/)
- [Fly.io](https://fly.io)
- [Docker Container](https://www.docker.com/)
3 changes: 2 additions & 1 deletion docs/markdown/ecosystem/prisma-client-rust.md
@@ -1,7 +1,8 @@
---
title: Prisma Client Rust
index: 51
---

More extensive docs coming soon...
## More extensive docs coming soon...

For now check out the Prisma Client Rust documentation on working with [rspc](https://prisma.brendonovich.dev/extra/rspc).
6 changes: 6 additions & 0 deletions docs/markdown/ecosystem/zer.md
@@ -0,0 +1,6 @@
---
title: Zer
index: 52
---

## Coming soon...
7 changes: 3 additions & 4 deletions docs/markdown/integrations/axum.md
@@ -1,12 +1,13 @@
---
title: Axum
index: 40
---

**rspc** has a built-in integration with [Axum](https://github.com/tokio-rs/axum) so that you can expose your API over HTTP.
rspc has a built-in integration with [Axum](https://github.com/tokio-rs/axum) so that you can expose your API over HTTP.

### Enable feature

For the integration to work you must enable the `axum` feature of **rspc**. Ensure the rspc line in your `Cargo.toml` file looks like the following:
For the integration to work you must enable the `axum` feature of rspc. Ensure the rspc line in your `Cargo.toml` file looks like the following:

```toml
[dependencies]
Expand All @@ -29,8 +30,6 @@ let app = axum::Router::new()
.layer(cors);
```

[View full example](https://github.com/oscartbeaumont/rspc/blob/main/examples/axum.rs)

### Extracting Context from Request

**Warning: The Axum extractor API is probally going to be removed in a future release. If you are using this API, I would appreciate a message in the Discord about your usecase so I can ensure the replacement API can do everything you need.**
Expand Down
6 changes: 3 additions & 3 deletions docs/markdown/integrations/tauri.md
@@ -1,13 +1,13 @@
---
title: Tauri
index: 30
index: 41
---

**rspc** has a built-in integration with [Tauri](https://tauri.app/) so that you can expose your API to your frontend code using Tauri's IPC.
rspc has a built-in integration with [Tauri](https://tauri.app/) so that you can expose your API to your frontend code using Tauri's IPC.

### Enable feature

For the integration to work you must enable the `tauri` feature of **rspc**. Ensure the rspc line in your `Cargo.toml` file looks like the following:
For the integration to work you must enable the `tauri` feature of rspc. Ensure the rspc line in your `Cargo.toml` file looks like the following:

```toml
[dependencies]
Expand Down
94 changes: 72 additions & 22 deletions docs/markdown/overview.md
Expand Up @@ -4,44 +4,94 @@ header: rspc
index: 1
---

**A blazing fast and easy to use TRPC-like server for Rust.**
rspc is a typesafe router which allows you to build APIs in Rust which have end to end typesafey. You define your logic in a Rust function on your backend and use the React hooks or Typescript client to call it. Your rspc router is transport agnostic which means you can serve it from any HTTP server of your choice such as [Axum](https://github.com/tokio-rs/axum) or even from [Tauri](https://tauri.app).

Why rspc?
-**Typesafety** - allows your team to move faster and **eliminate** a whole class of common bugs
-**Developer experience** - you **define a function** in Rust and can **call it from the frontend** with no extra magic
-**Minimal runtime** - small runtime footprint so your can get the **full potential of Rust's speed**
-**Middleware** - For easily extending your procedures with **auth, logging and more**
- 🚧 **Work in progress** - rspc is still **early in development**. It's stable but you may find use cases which aren't well supported.

You get the type safety of [GraphQL](https://graphql.org) without the complexity of it.

Let's skip the talk and get to the code. Let's start with the Rust side.

```rust
let router = <Router>::new()
use rspc::Router;

// We define the rspc Router
let router = Router::<MyCtx>::new()
// Then we define a new query called "version" which takes no arguments (`()`) and returns "1.0.0"
.query("version", |t| t(|ctx, args: ()| "1.0.0"))
.mutation("createUser", |t| t(|ctx, user_id: i32| User::create(user_id)))
// Finally we define a mutation called "createUser" which takes a user's name as a `String` and returns a `User`.
.mutation("createUser", |t| {
t(|ctx, name: String| async move {
ctx.db
.post()
.find_many(vec![])
.exec()
.await?
.map_err(Into::into) // Result<User, Error>
})
})
// You can stack as many procedures as you want!
.build();

// Finally we export the typescript bindings from the router.
router.export_ts("./bindings.ts").unwrap();
```
[View more examples](https://github.com/oscartbeaumont/rspc/tree/main/examples)

### Project status
When you run this code it will create a `bindings.ts` file which will look similar to the following.

🚧 Work in progress 🚧
```typescript
// This file was generated by [rspc](https://github.com/oscartbeaumont/rspc). Do not edit this file manually.

Expect breaking changes however it should be stable enough to build a project.
export type Procedures = {
queries:
{ key: "version", input: never, result: string },
mutations:
{ key: "createUser", input: string, result: User },
subscriptions: never,
};

### Introduction
export interface User { name: string; }
```

**rspc** is a library which helps you built completely typesafe APIs with a Rust backend and Typescript frontend.
Now that we have these Typescript bindings we can use them to call the API on the frontend in a typesafe manner.

Your `rspc::Router` is converted into [Typescript](https://www.typescriptlang.org) types which can be used on the frontend to prevent simple mistakes from ending up in production!
```tsx
import type { Procedures } from "./bindings.ts"; // These are the bindings exported from your Rust code!

This library fits a use case between REST and [GraphQL](https://graphql.org). It allows you to built API's with the typesafey of GraphQL without the complexity involved.
const rspc = createReactQueryHooks<Procedures>();

rspc acts as a type safe router on top of whatever HTTP or Websocket server you are already using such as [Axum](https://github.com/tokio-rs/axum).
function MyReactApp() {
// If you've used Tanstack Query this will look familiar because it's using it under the hood.
const { data: version } = rspc.useQuery("version");
const { mutate: createUser } = rspc.useMutation("createUser");

### Features
// This would throw a Typescript error because the type of version is inferred to be a string from the Rust code.
let x: number = version;

-**End-to-end typesafety** - Call your Rust code from Typescript with complete typesafety!
-**Per Request Context** - Great for database connection & authentication data
-**Middleware** - For extending your resolvers with auth, logging and more
-**Merging routers** - Great for separating code between files
-**Minimal runtime** - Near zero runtime footprint
return (
<div>
<h1>rspc</h1>
<p>Version: {version}</p>

### Inspiration
<button onClick={() => createUser("Monty Beaumont")}>Create User!</button>
</div>
);
}
```

This project is based off [trpc](https://trpc.io) and was inspired by the bridge system [Jamie Pine](https://github.com/jamiepine) designed for [Spacedrive](https://www.spacedrive.com). A huge thanks to everyone who helped inspire this project!
If you still confused about what rspc is check out [Brendan](http://github.com/brendonovich) explain it in caveman terms [in this clip](https://clips.twitch.tv/WonderfulPrettyMagpieBudBlast-S1dyvf5tBAqIwjt1).

### Production users

### Roadmap
- [Spacedrive](https://spacedrive.com)
- [Twidge](https://github.com/VarunPotti/twidge)
- [Unreleased] [Mattrax](https://mattrax.app)

Refer to [GitHub Issue](https://github.com/oscartbeaumont/rspc/issues/2).
### Inspiration

This project is based off [trpc](https://trpc.io) and was inspired by the bridge system [Jamie Pine](https://github.com/jamiepine) designed for [Spacedrive](https://www.spacedrive.com). A huge thanks to everyone who helped inspire this project!
8 changes: 7 additions & 1 deletion docs/markdown/quickstart.md
Expand Up @@ -3,7 +3,13 @@ title: Quickstart
index: 2
---

**Get rspc up and running in your own project.**
## Setup your editor

If you are using [Visual Studio Code](https://code.visualstudio.com) you should install the [rspc extension](https://marketplace.visualstudio.com/items?itemName=oscartbeaumont.rspc-vscode) for useful code shortcuts.

## Manual setup

Get rspc up and running in your own project.

### Create new project (optional)

Expand Down
30 changes: 0 additions & 30 deletions docs/markdown/related.md

This file was deleted.

12 changes: 6 additions & 6 deletions docs/markdown/server/common-errors.md
Expand Up @@ -2,16 +2,16 @@
title: Common errors
---

rspc uses traits to allow for any nearly any type to be returned from your resolvers, however this can make the error messages hard to understand so some guidance is provided here.
rspc uses traits to allow for any nearly any type to be returned from your procedures, however this can make the error messages hard to understand so some guidance is provided here.

#### the trait `IntoLayerResult<_>` is not implemented for type

This error means the type which you returned from your resolver is not valid. This is probably because it doesn't implement the traits:
This error means the type which you returned from your procedure is not valid. This is probably because it doesn't implement the traits:

- [`serde::Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html)
- [`specta::Type`](https://docs.rs/specta/latest/specta/trait.Type.html)

To fix this error ensure the custom types which you return from your resolver have the derive macros as shown below or that the type is a [Rust primitive type](https://doc.rust-lang.org/book/ch03-02-data-types.html).
To fix this error ensure the custom types which you return from your procedure have the derive macros as shown below or that the type is a [Rust primitive type](https://doc.rust-lang.org/book/ch03-02-data-types.html).

```rust
use rspc::Type;
Expand Down Expand Up @@ -79,14 +79,14 @@ enum MyStruct {

#### type mismatch in closure arguments

This is probably caused by you incorrectly hardcoding the type for the request context (first argument) of the resolver closure.
This is probably caused by you incorrectly hardcoding the type for the request context (first argument) of the procedure closure.

```rust
// INVALID CODE
Router<()>::new() // Here we set the context to `()` but we set the closures argument type to `i32`.
Router::<()>::new() // Here we set the context to `()` but we set the closures argument type to `i32`.
.query("debug", |t| t(|ctx: i32, _: ()| {}))

// SOLUTION
Router<()>::new() // Here we don't set the type of the context on the closure and Rust infers it.
Router::<()>::new() // Here we don't set the type of the context on the closure and Rust infers it.
.query("debug", |t| t(|ctx, _: ()| {}))
```

0 comments on commit 9b42e66

Please sign in to comment.