Skip to content

Commit

Permalink
✨ Added macros for getting the types && fixed other bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
nwrenger committed Jul 29, 2024
1 parent ba8d856 commit e71579e
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 354 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gluer"
version = "0.2.2"
version = "0.3.0"
edition = "2021"
authors = ["Nils Wrenger <[email protected]>"]
description = "A wrapper for rust frameworks which addresses the persistent issue of redundant type and function definitions between the frontend and backend"
Expand All @@ -18,7 +18,7 @@ proc-macro = true
quote = "1.0"
syn = { version = "2.0.62", features = ["full"] }
proc-macro2 = "1.0"
lazy_static = "1.5.0"
once_cell = "1.19.0"

[dev-dependencies]
axum = "0.7.5"
Expand Down
95 changes: 70 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
light_magic = "0.2.2"
light_magic = "0.3.0"
```

## Disclaimer
Expand All @@ -23,66 +23,111 @@ Please be informed that this crate is in a very early state and is expected to w
- Inferring the input and output types of functions (but only `Json<...>` for inputs)
- Converting them to ts types
- Generating the ts file with the functions and data types
- Using types from other modules works now but only if there are not 2 or more times nested from the router implementation

## How to use

Firstly you have to use the `add_route!` macro when adding api important routes to your router:
`gluer` generates an api endpoint `.ts` file which expects that you build your frontend statically and host it via `axum`'s static file serving. To use it, follow these steps:

### Step 1: Define Parameters and Functions

Start by using the `#[param]` and `fun!` macros to define your data structures and functions. These macros give `gluer` access to the necessary code for type inference and conversion.

```rust
use axum::{
routing::{get, post},
Router,
Json,
};
use gluer::add_route;
use gluer::{fun, param};

// Define a parameter with the param macro
#[param]
#[derive(Default, serde::Serialize)]
struct Book {
// imagine some fields here
}

// Define functions with the fun macro
fun! {
async fn root() -> Json<String> {
"Hello, World!".to_string().into()
}
async fn book() -> Json<Book> {
Book::default().into()
}
}
```

### Step 2: Add Routes

async fn root() -> Json<&'static str> {
"Hello, World!".into()
Use the `add_route!` macro to add API-important routes to your router. Note that inline functions cannot generally be used due to Rust's limitations in inferring types in macros.

```rust
use axum::{
routing::get,
Router,
Json,
};
use gluer::{add_route, fun};

// a part of the function above
fun! {
async fn root() -> String {
"Hello, World!".to_string()
}
async fn hello() -> Json<String> {
"Hello, World!".to_string().into()
}
}

let mut app: Router<()> = Router::new();

// Not api important, so adding without macro
// Add non-API-important route without macro
app = app.route("/", get(root));

// You cannot use inline functions because of rust limitations of inferring types in macros
add_route!(app, "/", post(root));
add_route!(app, "/user", post(root).delete(root));
// Add API-important routes with the add_route macro
add_route!(app, "/hello-world", get(hello));
```

Then you only have to use the `gen_spec!` macro which generates after specifying the path the api on comptime:
### Step 3: Generate API Specification

Generate the API specification file using the `gen_ts!` macro. This macro generates the TypeScript file at compile time.

```rust
use gluer::gen_spec;
use gluer::gen_ts;

gen_spec!("tests/api.ts");
// Generate the TypeScript API specification
gen_ts!("tests/api.ts");
```

It expects that you build your frontend statically and use it `axum`'s ability to serve static files!

### Complete Example

Below is a complete example demonstrating the use of gluer with `axum`:

```rust,no_run
use axum::{routing::post, Json, Router};
use gluer::{add_route, gen_spec};
use axum::{routing::get, Json, Router};
use gluer::{add_route, fun, gen_ts, param};
#[derive(serde::Deserialize)]
#[param]
#[derive(serde::Serialize, serde::Deserialize, Default)]
struct Hello {
name: String,
}
async fn root(Json(hello): Json<Hello>) -> Json<String> {
hello.name.into()
fun! {
async fn add_root(Json(hello): Json<Hello>) -> Json<Hello> {
hello.into()
}
async fn fetch_root() -> Json<Hello> {
Hello::default().into()
}
}
#[tokio::main]
async fn main() {
let mut app = Router::new();
let mut app: Router<()> = Router::new();
add_route!(app, "/", post(root));
add_route!(app, "/", get(fetch_root).post(add_root));
gen_spec!("tests/api.ts");
gen_ts!("tests/api.ts");
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")
.await
Expand Down
191 changes: 0 additions & 191 deletions src/extractors.rs

This file was deleted.

Loading

0 comments on commit e71579e

Please sign in to comment.