2023-08-16 13:44:57 +01:00

220 lines
5.6 KiB
Markdown

# Add a New Rust Project
The code for this example is available on GitHub:
{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/rust" /%}
**Supported Features**
We'll be using an Nx Plugin for Rust
called [@monodon/rust](https://github.com/cammisuli/monodon/tree/main/packages/rust).
{% pill url="/core-features/run-tasks" %}✅ Run Tasks{% /pill %}
{% pill url="/core-features/cache-task-results" %}✅ Cache Task Results{% /pill %}
{% pill url="/core-features/remote-cache" %}✅ Share Your Cache{% /pill %}
{% pill url="/core-features/explore-graph" %}✅ Explore the Graph{% /pill %}
{% pill url="/core-features/distribute-task-execution" %}✅ Distribute Task Execution{% /pill %}
{% pill url="/core-features/integrate-with-editors" %}✅ Integrate with Editors{% /pill %}
{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Nx{% /pill %}
{% pill url="/core-features/enforce-module-boundaries" %}✅ Enforce Module Boundaries{% /pill %}
{% pill url="/core-features/plugin-features/use-task-executors" %}✅ Use Task Executors{% /pill %}
{% pill url="/core-features/plugin-features/use-code-generators" %}✅ Use Code Generators{% /pill %}
{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Framework Dependencies{% /pill %}
## Create the workspace with the `@monodon/rust` preset
We'll use the preset created by the `@monodon/rust` plugin to create the workspace with everything we need to build Rust
applications.
{% tabs %}
{%tab label="npm"%}
```shell
npx -y create-nx-workspace@latest acme --preset=@monodon/rust
```
{% /tab %}
{%tab label="yarn"%}
```shell
npx -y create-nx-workspace@latest acme --preset=@monodon/rust --packageManager=yarn
```
{% /tab %}
{%tab label="pnpm"%}
```shell
npx -y create-nx-workspace@latest acme --preset=@monodon/rust --packageManager=pnpm
```
{% /tab %}
{% /tabs %}
Using the preset provided by `@monodon/rust` will:
- Remove any unnecessary configuration files for working with Rust projects, such as `tsconfig.json` and `.prettierrc`
- Remove unnecessary dependencies, such as `@nx/js`, as we're working with a Rust project
- Add a root `Cargo.toml` to manage workspace members
## Create the application
Let's generate a new application using `@monodon/rust`.
```shell
nx g @monodon/rust:binary myapp
```
## Create a library
Let's generate a new library using `@monodon/rust`.
```shell
nx g @monodon/rust:library cats
```
## Update the `cats` library
First, let's update the `Cargo.toml` file to define the dependencies for the library.
```toml {% fileName="libs/cats/Cargo.toml" %}
[package]
name = "cats"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-web = "4"
[dependencies.serde]
version = "1"
features = ["derive"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
```
Now, let's add the code to handle the `cats` route.
```rust {% fileName="libs/cats/src/lib.rs" %}
use std::collections::HashSet;
use std::sync::Mutex;
use actix_web::web::*;
use actix_web::{get, post, HttpResponse, Responder, Scope};
pub struct Cats {
cats: Mutex<HashSet<Cat>>,
}
#[derive(Eq, Hash, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)]
struct Cat {
name: String,
age: u8,
}
#[get("")]
async fn get_cats(data: Data<Cats>) -> impl Responder {
let cats = data.cats.lock().unwrap();
println!("Cats {:?}", &cats);
Json(cats.clone())
}
#[post("/add")]
async fn add_cat(cat: Json<Cat>, data: Data<Cats>) -> impl Responder {
let mut cats = data.cats.lock().unwrap();
println!("Adding {:?}", &cat);
cats.insert(cat.into_inner());
HttpResponse::Ok()
}
pub fn create_cat_data() -> Data<Cats> {
Data::new(Cats {
cats: Mutex::new(HashSet::new()),
})
}
pub fn create_cat_scope(data: &Data<Cats>) -> Scope {
scope("/cats")
// Cloning is cheap here because internally, Data uses `Arc`
.app_data(Data::clone(data))
.service(add_cat)
.service(get_cats)
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
```
## Update the application
Let's create the http-server application and use the library to add the `cats` route.
First, we need to update the `Cargo.toml` file to define the application's dependencies.
```toml {% fileName="apps/myapp/Cargo.toml" %}
[package]
name = "myapp"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-web = "4"
cats = { path = "../../libs/cats" }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
```
Now, let's update the application's code itself.
```rust {% fileName="apps/myapp/src/main.rs" %}
use actix_web::{App, HttpServer};
use cats::{create_cat_data, create_cat_scope};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// HttpServer:new creates multiple threads to handle requests.
// We need to make sure that the shared cat data is created once before the HttpServer
// We can then pass this reference to the create_cat_scope so that all threads have access to the same data
let cat_data = create_cat_data();
HttpServer::new(move || App::new().service(create_cat_scope(&cat_data)))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
```
## Build and Run the Application
To run the application, run the following command and then navigate your browser to `http://localhost:8080/cats`
```shell
nx run myapp:run
```
To build the application, run the following command:
```shell
nx build myapp
```
## More Documentation
- [Rust](https://www.rust-lang.org/)
- [@monodon/rust](https://github.com/cammisuli/monodon/tree/main/packages/rust)