Skip to content

Commit

Permalink
Merge pull request #63 from DarrenBaldwin07/build-command
Browse files Browse the repository at this point in the history
Build command
  • Loading branch information
DarrenBaldwin07 authored Sep 28, 2023
2 parents 96ad515 + 7fa32f0 commit e363db7
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 26 deletions.
17 changes: 9 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,56 @@

[![OSSRank](https://shields.io/endpoint?url=https://ossrank.com/shield/2856)](https://ossrank.com/p/2856)

# Example

You define a resolver in Rust and Rapid will automatically generate a type schema that enables full-stack type-safety from frontend to backend.

```rust
use rapid_web::actix::HttpResponse;
use rapid_web::{rapid_web_codegen::rapid_handler, request::RapidPath};
use serde::{Deserialize, Serialize};

// The name/alias for your route (you will use this to call it from the client)
pub const ROUTE_KEY: &str = "getUser";

#[derive(Serialize, Deserialize)]
pub struct User {
pub id: i32,
pub name: String,
pub age: u8,
}

pub type RapidOutput = User;

#[rapid_handler]
pub async fn query(user_id: RapidPath<i32>) -> HttpResponse {
let user = User {
id: user_id.into_inner(),
name: "John".to_string(),
age: 20,
};
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(user)
}
```

You can then make fully type-safe HTTP requests to your rust backend with the `rapid-react` bolt client:

```ts
import { createBoltClient } from '@rapid-web/react';
import { routes, type Handlers } from './bindings.ts';

// Init your bolt client that you can use throughout your entire app for making requests
export const bolt = createBoltClient<Handlers, typeof routes>(routes, {
transport: 'http://localhost:8080',
});

const userId = 1;

const req = await bolt('getUser').get(routes.getUser, userId);
```

# What is Rapid?

The complete fullstack toolkit for building advanced, scaleable, and highly efficient software.
Expand Down
1 change: 1 addition & 0 deletions crates/rapid-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ strum = "0.24.1"
strum_macros = "0.24.3"
terminal-emoji = "0.4.1"
tiny-gradient = "0.1.0"
rapid-web = "0.4.9"
toml = "0.7.2"
tui = "0.19.0"
walkdir = "2.3.3"
2 changes: 2 additions & 0 deletions crates/rapid-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl RapidCLI {
commands::run::Run::cmd(),
commands::templates::Templates::cmd(),
commands::routes::Routes::cmd(),
commands::build::Build::cmd()
]
}

Expand All @@ -68,6 +69,7 @@ impl RapidCLI {
"run" => commands::run::Run::execute,
"templates" => commands::templates::Templates::execute,
"routes" => commands::routes::Routes::execute,
"build" => commands::build::Build::execute,
_ => return None,
};

Expand Down
68 changes: 68 additions & 0 deletions crates/rapid-cli/src/commands/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use super::RapidCommand;
use crate::{cli::Config, tui::logo, rapid_config::config::find_rapid_config, util::{NEXTJS_ROUTE_PATH, REMIX_ROUTE_PATH, get_routes_dir, get_bindings_directory}, tui::chevrons};
use clap::{ArgMatches, Command};
use rapid_web::shift::generate::create_typescript_types;
use std::env::current_dir;

pub struct Build {}

impl RapidCommand for Build {
fn cmd() -> clap::Command {
Command::new("build").about("Trigger a traditional rapid build for generating types and validating handlers")
}

fn execute(_: &Config, _args: &ArgMatches) -> Result<(), crate::cli::CliError<'static>> {
println!("{}", logo());
// TODO: this command could also run a `cargo build` (only issue is that we would have to support all the args that cargo allows)

let config = find_rapid_config();
let routes_dir = match config.app_type.as_str() {
"server" => get_routes_dir(config.server.as_ref()),
"remix" => REMIX_ROUTE_PATH.to_owned(),
_ => NEXTJS_ROUTE_PATH.to_owned(),
};

let every_dir_types_gen = match config.clone().app_type.as_str() {
"server" => match config.clone().server {
Some(server) => match server.typescript_generation_directory {
Some(value) => value,
None => "".to_string(),
},
None => "".to_string(),
},
"remix" => match config.clone().remix {
Some(remix) => match remix.typescript_generation_directory {
Some(value) => value,
None => "".to_string(),
},
None => "".to_string(),
},
_ => match config.clone().nextjs {
Some(nextjs) => match nextjs.typescript_generation_directory {
Some(value) => value,
None => "".to_string(),
},
None => "".to_string(),
},
};

let routes_directory = current_dir()
.expect("Could not parse routes direcory path found in rapid config file.")
.join(std::path::PathBuf::from(routes_dir.clone()));

let type_generation_directory = if every_dir_types_gen != "" {
current_dir()
.expect("Could not parse current directory while executing type generation!")
.join(every_dir_types_gen)
} else {
// If the typegen directory was not defined by the user, simply fallback to only doing handler types in the routes directorys
routes_directory.clone()
};

create_typescript_types(get_bindings_directory(config), routes_directory, type_generation_directory);

println!("{} Rapid build completed!", chevrons());

Ok(())
}
}
1 change: 1 addition & 0 deletions crates/rapid-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod new;
pub mod run;
pub mod templates;
pub mod routes;
pub mod build;
use crate::cli::{CliError, Config};
use clap::Command;

Expand Down
19 changes: 3 additions & 16 deletions crates/rapid-cli/src/commands/routes.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use super::RapidCommand;
use crate::{cli::Config, tui::{logo, chevrons, clean_console}, rapid_config::config::{find_rapid_config, ServerConfig}};
use crate::{cli::Config, tui::{logo, chevrons, clean_console}, rapid_config::config::find_rapid_config, util::get_routes_dir};
use clap::{ArgMatches, Command};
use walkdir::WalkDir;
use std::fs::File;
use std::io::Read;
use colorful::{Color, Colorful};
use regex::Regex;

pub const REMIX_ROUTE_PATH: &'static str = "app/api/routes";
pub const NEXTJS_ROUTE_PATH: &'static str = "pages/api/routes";
use crate::util::{NEXTJS_ROUTE_PATH, REMIX_ROUTE_PATH};

// `rapid routes` command for showing all the route rust files and they map to in url form
pub struct Routes {}
Expand Down Expand Up @@ -89,18 +87,7 @@ pub fn remove_last_occurrence(s: &str, sub: &str) -> String {
front + back
}

pub fn get_routes_dir(rapid_server_config: Option<&ServerConfig>) -> String {
match rapid_server_config {
Some(server) => match server.routes_directory.clone() {
Some(dir) => match dir == "/" {
true => panic!("The 'routes_directory' variable cannot be set to a base path. Please use something nested!"),
false => dir,
},
None => panic!("Error: the 'routes_directory' variable must be set in your rapid config file!"),
},
None => panic!("You must have a valid rapid config file in the base project directory!"),
}
}



pub fn parse_route_path(route_path: String) -> String {
Expand Down
1 change: 1 addition & 0 deletions crates/rapid-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod commands;
pub mod constants;
pub mod rapid_config;
pub mod tui;
mod util;
59 changes: 59 additions & 0 deletions crates/rapid-cli/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::rapid_config::config::{ServerConfig, RapidConfig};
use std::{path::PathBuf, env::current_dir};

pub const REMIX_ROUTE_PATH: &'static str = "app/api/routes";
pub const NEXTJS_ROUTE_PATH: &'static str = "pages/api/routes";

pub fn get_routes_dir(rapid_server_config: Option<&ServerConfig>) -> String {
match rapid_server_config {
Some(server) => match server.routes_directory.clone() {
Some(dir) => match dir == "/" {
true => panic!("The 'routes_directory' variable cannot be set to a base path. Please use something nested!"),
false => dir,
},
None => panic!("Error: the 'routes_directory' variable must be set in your rapid config file!"),
},
None => panic!("You must have a valid rapid config file in the base project directory!"),
}
}

pub fn get_bindings_directory(config: RapidConfig) -> PathBuf {
match config.app_type.as_str() {
"server" => match config.server.as_ref() {
Some(server) => match server.bindings_export_path.clone() {
Some(dir) => match dir == "/" {
true => current_dir().expect("Could not parse bindings export path found in rapid config file."),
false => current_dir()
.expect("Could not parse bindings export path found in rapid config file.")
.join(PathBuf::from(dir)),
},
None => panic!("Error: the 'bindings_export_path' variable must be set in your rapid config file!"),
},
None => panic!("You must have a valid rapid config file in the base project directory!"),
},
"remix" => match config.remix.as_ref() {
Some(remix) => match remix.bindings_export_path.clone() {
Some(dir) => match dir == "/" {
true => current_dir().expect("Could not parse bindings export path found in rapid config file."),
false => current_dir()
.expect("Could not parse bindings export path found in rapid config file.")
.join(PathBuf::from(dir)),
},
None => panic!("Error: the 'bindings_export_path' variable must be set in your rapid config file!"),
},
None => panic!("You must have a valid rapid config file in the base project directory!"),
},
_ => match config.nextjs.as_ref() {
Some(nextjs) => match nextjs.bindings_export_path.clone() {
Some(dir) => match dir == "/" {
true => current_dir().expect("Could not parse bindings export path found in rapid config file."),
false => current_dir()
.expect("Could not parse bindings export path found in rapid config file.")
.join(PathBuf::from(dir)),
},
None => panic!("Error: the 'bindings_export_path' variable must be set in your rapid config file!"),
},
None => panic!("You must have a valid rapid config file in the base project directory!"),
},
}
}
2 changes: 1 addition & 1 deletion crates/rapid-web-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ regex = "1.7.3"
syn = { version = "2.0.15", features = ["full", "extra-traits"] }

[dev-dependencies]
rapid-web = "0.4.8"
rapid-web = "0.4.9"
2 changes: 1 addition & 1 deletion crates/rapid-web/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ pub fn generate_typescript_types(bindings_out_dir: PathBuf, routes_dir: String,
.expect("Could not parse current directory while executing type generation!")
.join(every_dir_types_gen)
} else {
// If the typegen directory was not defined by the user, simply fallback to only doing handler types in the routes directorys
// If the typegen directory was not defined by the user, simply fallback to only doing handler types in the routes directory
routes_directory.clone()
};

Expand Down
Empty file removed crates/rapid-web/test.ts
Empty file.

0 comments on commit e363db7

Please sign in to comment.