├── .github
├── FUNDING.yml
├── dependabot.yml
├── logo.png
└── logo.svg
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── biome.json
├── crates
├── binario
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
├── cache
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ ├── memory.rs
│ │ ├── state.rs
│ │ └── store.rs
├── client
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
├── core
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
├── devtools
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ ├── tracing.rs
│ │ └── types.rs
├── invalidation
│ ├── Cargo.toml
│ ├── README.md
│ ├── RESEARCH.md
│ └── src
│ │ └── lib.rs
├── legacy
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── config.rs
│ │ ├── error.rs
│ │ ├── internal
│ │ ├── jsonrpc.rs
│ │ ├── jsonrpc_exec.rs
│ │ ├── middleware.rs
│ │ ├── mod.rs
│ │ ├── procedure_builder.rs
│ │ └── procedure_store.rs
│ │ ├── lib.rs
│ │ ├── middleware.rs
│ │ ├── resolver.rs
│ │ ├── resolver_result.rs
│ │ ├── router.rs
│ │ ├── router_builder.rs
│ │ └── selection.rs
├── openapi
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ └── swagger.html
├── procedure
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── dyn_input.rs
│ │ ├── dyn_output.rs
│ │ ├── error.rs
│ │ ├── interop.rs
│ │ ├── lib.rs
│ │ ├── logger.rs
│ │ ├── procedure.rs
│ │ ├── procedures.rs
│ │ ├── state.rs
│ │ └── stream.rs
├── tracing
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ └── traceable.rs
├── validator
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
└── zer
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ └── lib.rs
├── examples
├── anyhow
│ ├── Cargo.toml
│ ├── bindings.ts
│ └── src
│ │ └── main.rs
├── astro
│ ├── .astro
│ │ ├── settings.json
│ │ └── types.d.ts
│ ├── astro.config.mjs
│ ├── package.json
│ ├── src
│ │ ├── components
│ │ │ ├── playground.ts
│ │ │ ├── react.tsx
│ │ │ └── solid.tsx
│ │ ├── env.d.ts
│ │ └── pages
│ │ │ └── index.astro
│ ├── test
│ │ ├── client.test.ts
│ │ ├── index.md
│ │ ├── react.test.tsx
│ │ └── solid.test.tsx
│ └── tsconfig.json
├── axum
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
├── binario
│ ├── Cargo.toml
│ ├── client.ts
│ └── src
│ │ └── main.rs
├── bindings.ts
├── bindings_t.d.ts
├── bindings_t.d.ts.map
├── client
│ ├── Cargo.toml
│ └── src
│ │ ├── bindings.rs
│ │ └── main.rs
├── core
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
├── legacy
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
├── nextjs
│ ├── .gitignore
│ ├── README.md
│ ├── next-env.d.ts
│ ├── next.config.js
│ ├── package.json
│ ├── pages
│ │ ├── _app.tsx
│ │ ├── index.tsx
│ │ ├── using-ssp.tsx
│ │ ├── using-use-mutation.tsx
│ │ ├── using-use-query.tsx
│ │ └── using-use-subscription.tsx
│ ├── src
│ │ └── rspc.ts
│ ├── styles
│ │ ├── Home.module.css
│ │ └── globals.css
│ └── tsconfig.json
└── tauri
│ ├── .gitignore
│ ├── .vscode
│ └── extensions.json
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── public
│ ├── tauri.svg
│ └── vite.svg
│ ├── src-tauri
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── build.rs
│ ├── capabilities
│ │ └── default.json
│ ├── icons
│ │ ├── 128x128.png
│ │ ├── 128x128@2x.png
│ │ ├── 32x32.png
│ │ ├── Square107x107Logo.png
│ │ ├── Square142x142Logo.png
│ │ ├── Square150x150Logo.png
│ │ ├── Square284x284Logo.png
│ │ ├── Square30x30Logo.png
│ │ ├── Square310x310Logo.png
│ │ ├── Square44x44Logo.png
│ │ ├── Square71x71Logo.png
│ │ ├── Square89x89Logo.png
│ │ ├── StoreLogo.png
│ │ ├── icon.icns
│ │ ├── icon.ico
│ │ └── icon.png
│ ├── src
│ │ ├── api.rs
│ │ ├── lib.rs
│ │ └── main.rs
│ └── tauri.conf.json
│ ├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ └── logo.svg
│ ├── index.tsx
│ └── vite-env.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── integrations
├── axum
│ ├── Cargo.toml
│ └── src
│ │ ├── endpoint.rs
│ │ ├── extractors.rs
│ │ ├── jsonrpc.rs
│ │ ├── jsonrpc_exec.rs
│ │ ├── legacy.rs
│ │ ├── lib.rs
│ │ ├── request.rs
│ │ └── v2.rs
└── tauri
│ ├── Cargo.toml
│ ├── build.rs
│ ├── permissions
│ ├── autogenerated
│ │ ├── commands
│ │ │ └── handle_rpc.toml
│ │ └── reference.md
│ ├── default.toml
│ └── schemas
│ │ └── schema.json
│ └── src
│ └── lib.rs
├── package.json
├── packages
├── client
│ ├── package.json
│ ├── src
│ │ ├── client.ts
│ │ ├── error.ts
│ │ ├── index.ts
│ │ ├── next
│ │ │ ├── UntypedClient.ts
│ │ │ ├── index.test.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── transport.ts
│ │ └── typescript.ts
│ └── tsconfig.json
├── query-core
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── react-query
│ ├── package.json
│ ├── src
│ │ └── index.tsx
│ └── tsconfig.json
├── solid-query
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ └── index.tsx
│ └── tsconfig.json
├── svelte-query
│ ├── package.json
│ ├── src
│ │ ├── RspcProvider.svelte
│ │ ├── context.ts
│ │ └── index.ts
│ └── tsconfig.json
├── tanstack-query
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── tauri
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ └── next.ts
│ └── tsconfig.json
└── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── publish.sh
├── rspc
├── Cargo.toml
├── src
│ ├── as_date.rs
│ ├── error.rs
│ ├── extension.rs
│ ├── languages.rs
│ ├── languages
│ │ ├── rust.rs
│ │ └── typescript.rs
│ ├── legacy.rs
│ ├── lib.rs
│ ├── middleware.rs
│ ├── middleware
│ │ ├── into_middleware.rs
│ │ ├── middleware.rs
│ │ └── next.rs
│ ├── mod.rs
│ ├── procedure.rs
│ ├── procedure
│ │ ├── builder.rs
│ │ ├── erased.rs
│ │ ├── meta.rs
│ │ ├── resolver_input.rs
│ │ └── resolver_output.rs
│ ├── procedure_kind.rs
│ ├── router.rs
│ ├── stream.rs
│ ├── types.rs
│ └── util.rs
└── tests
│ ├── router.rs
│ └── typescript.rs
└── turbo.json
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [oscartbeaumont]
2 | custom: ["https://paypal.me/oscartbeaumont"]
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 |
8 | # TODO: Rust
9 | # TODO: npm
10 |
--------------------------------------------------------------------------------
/.github/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specta-rs/rspc/a9caf9b7070cc0017406be1d8322e02baf932645/.github/logo.png
--------------------------------------------------------------------------------
/.github/logo.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | target/
4 |
5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
7 | Cargo.lock
8 |
9 | # These are backup files generated by rustfmt
10 | **/*.rs.bk
11 |
12 | # System Files
13 | .DS_Store
14 |
15 | # Node
16 | node_modules
17 | .pnpm-debug.log*
18 | *.tsbuildinfo
19 | /packages/*/dist
20 |
21 | # Compiled vscode extension
22 | *.vsix
23 |
24 | .svelte-kit
25 | .turbo
26 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [
4 | "./crates/*",
5 | "./rspc",
6 | "./integrations/*",
7 | "./examples/core",
8 | "./examples/axum",
9 | "./examples/client",
10 | "./examples/tauri/src-tauri",
11 | "./examples/legacy",
12 | "./examples/binario",
13 | "./examples/anyhow",
14 | ]
15 |
16 | [workspace.dependencies]
17 | # Private
18 | specta-typescript = { version = "0.0.9", default-features = false }
19 | pin-project-lite = { version = "0.2", default-features = false }
20 | erased-serde = { version = "0.4", default-features = false }
21 |
22 | # Public
23 | specta = { version = "=2.0.0-rc.22", default-features = false }
24 | serde = { version = "1", default-features = false }
25 | serde_json = { version = "1", default-features = false }
26 | futures = { version = "0.3", default-features = false }
27 | futures-core = { version = "0.3", default-features = false }
28 | futures-util = { version = "0.3", default-features = false }
29 | tracing = { version = "0.1", default-features = false }
30 |
31 | [workspace.lints.clippy]
32 | all = { level = "warn", priority = -1 }
33 | cargo = { level = "warn", priority = -1 }
34 | unwrap_used = { level = "warn", priority = -1 }
35 | panic = { level = "warn", priority = -1 }
36 | todo = { level = "warn", priority = -1 }
37 | panic_in_result_fn = { level = "warn", priority = -1 }
38 |
39 | # [patch.crates-io]
40 | # specta = { git = "https://github.com/specta-rs/specta", rev = "bf3a0937cceb29eca11df207076b9e1b942ba7bb" }
41 | # specta-serde = { git = "https://github.com/specta-rs/specta", rev = "bf3a0937cceb29eca11df207076b9e1b942ba7bb" }
42 | # specta-typescript = { git = "https://github.com/specta-rs/specta", rev = "bf3a0937cceb29eca11df207076b9e1b942ba7bb" }
43 |
44 | # specta = { path = "/Users/oscar/Desktop/specta/specta" }
45 | # specta-typescript = { path = "/Users/oscar/Desktop/specta/specta-typescript" }
46 | # specta-serde = { path = "/Users/oscar/Desktop/specta/specta-serde" }
47 | # specta-util = { path = "/Users/oscar/Desktop/specta/specta-util" }
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Oscar Beaumont
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | rspc
5 |
6 |
7 | A blazing fast and easy to use TRPC-like server for Rust.
8 |
9 |
10 |
11 | Website
12 |
13 |
14 |
15 |
16 |
34 |
35 |
36 |
37 | > [!WARNING]
38 | > rspc is no longer being maintained. [Learn more](https://github.com/specta-rs/rspc/discussions/351).
39 |
40 | ## Example
41 |
42 | 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.
43 |
44 | ```rust
45 | let router = ::new()
46 | .query("version", |t| {
47 | t(|ctx, input: ()| "0.0.1")
48 | })
49 | .mutation("helloWorld", |t| {
50 | t(|ctx, input: ()| async { "Hello World!" })
51 | });
52 | ```
53 |
54 | ## Features:
55 |
56 | - Per Request Context - Great for database connection & authentication data
57 | - Middleware - With support for context switching
58 | - Merging routers - Great for separating code between files
59 |
60 | ### Inspiration
61 |
62 | 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!
63 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
3 | "files": {
4 | "include": ["packages/**"],
5 | "ignore": ["node_modules", "dist"]
6 | },
7 | "organizeImports": {
8 | "enabled": true
9 | },
10 | "linter": {
11 | "enabled": true,
12 | "rules": {
13 | "recommended": true,
14 | "suspicious": {
15 | "noExplicitAny": "off"
16 | },
17 | "style": {
18 | "noNonNullAssertion": "off"
19 | },
20 | "correctness": {
21 | "useJsxKeyInIterable": "off"
22 | }
23 | }
24 | },
25 | "formatter": {
26 | "indentStyle": "tab"
27 | },
28 | "vcs": {
29 | "enabled": true,
30 | "clientKind": "git",
31 | "useIgnoreFile": true,
32 | "defaultBranch": "main"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/crates/binario/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rspc-binario"
3 | description = "Binario support for rspc"
4 | version = "0.0.0"
5 | edition = "2021"
6 | publish = false # TODO: Crate metadata & publish
7 |
8 | [dependencies]
9 | binario = "0.0.3"
10 | futures-util.workspace = true
11 | rspc = { path = "../../rspc" }
12 | specta = { workspace = true }
13 | tokio = "1.43.0"
14 |
15 | # /bin/sh RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
16 | [package.metadata."docs.rs"]
17 | all-features = true
18 | rustdoc-args = ["--cfg", "docsrs"]
19 |
20 | [lints]
21 | workspace = true
22 |
--------------------------------------------------------------------------------
/crates/binario/README.md:
--------------------------------------------------------------------------------
1 | # rspc 🤝 Binario
2 |
3 | [](https://docs.rs/rspc-binario)
4 |
5 | > [!CAUTION]
6 | > This crate is a proof of concept.
7 | >
8 | > It is not intended for production use and will likely remain that way.
9 |
10 | Use [Binario](https://github.com/oscartbeaumont/binario) instead of [Serde](https://serde.rs) for serialization and deserialization.
11 |
12 | This is a proof of concept to show that rspc has the ability to support any serialization libraries.
13 |
--------------------------------------------------------------------------------
/crates/cache/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rspc-cache"
3 | version = "0.0.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | moka = { version = "0.12.10", features = ["sync"] }
9 | pin-project-lite = { workspace = true }
10 | rspc = { path = "../../rspc" }
11 |
12 | # /bin/sh RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
13 | [package.metadata."docs.rs"]
14 | all-features = true
15 | rustdoc-args = ["--cfg", "docsrs"]
16 |
17 | [lints]
18 | workspace = true
19 |
--------------------------------------------------------------------------------
/crates/cache/README.md:
--------------------------------------------------------------------------------
1 | # rspc cache
2 |
3 | [](https://docs.rs/rspc-cache)
4 |
5 | > [!CAUTION]
6 | > This crate is still a work in progress. You can use it but we can't guarantee that it's API won't change.
7 |
8 | Provides a simple way to cache the results of rspc queries with pluggable backends.
9 |
10 | Features:
11 | - Simple to use
12 | - Pluggable backends (memory, redis, etc.)
13 | - Configurable cache TTL
14 |
15 | ## Example
16 |
17 | ```rust
18 | // TODO: imports
19 |
20 | fn todo() -> Router2 {
21 | Router2::new()
22 | .setup(CacheState::builder(Memory::new()).mount())
23 | .procedure("my_query", {
24 | ::builder()
25 | .with(cache())
26 | .query(|_, _: ()| async {
27 | // if input.some_arg {}
28 | cache_ttl(10);
29 |
30 | Ok(SystemTime::now())
31 | })
32 | })
33 | }
34 | ```
35 |
--------------------------------------------------------------------------------
/crates/cache/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! rspc-cache: Caching middleware for rspc
2 | #![forbid(unsafe_code)]
3 | #![cfg_attr(docsrs, feature(doc_cfg))]
4 | #![doc(
5 | html_logo_url = "https://github.com/specta-rs/rspc/blob/main/.github/logo.png?raw=true",
6 | html_favicon_url = "https://github.com/specta-rs/rspc/blob/main/.github/logo.png?raw=true"
7 | )]
8 |
9 | mod memory;
10 | mod state;
11 | mod store;
12 |
13 | use std::{
14 | cell::Cell,
15 | future::{poll_fn, Future},
16 | pin::pin,
17 | };
18 |
19 | pub use memory::Memory;
20 | pub use state::CacheState;
21 | pub use store::Store;
22 |
23 | use rspc::middleware::Middleware;
24 | use store::Value;
25 |
26 | thread_local! {
27 | static CACHE_TTL: Cell