Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(service): Add thruster framework as service #389

Merged
merged 5 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
657 changes: 459 additions & 198 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 11 additions & 8 deletions cargo-shuttle/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,29 +137,32 @@ pub struct RunArgs {
#[derive(Parser, Debug)]
pub struct InitArgs {
/// Initialize with axum framework
#[clap(long, conflicts_with_all = &["rocket", "tide", "tower", "poem", "serenity", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["rocket", "tide", "tower", "poem", "serenity", "warp", "salvo", "thruster"])]
pub axum: bool,
/// Initialize with rocket framework
#[clap(long, conflicts_with_all = &["axum", "tide", "tower", "poem", "serenity", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "tide", "tower", "poem", "serenity", "warp", "salvo", "thruster"])]
pub rocket: bool,
/// Initialize with tide framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tower", "poem", "serenity", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tower", "poem", "serenity", "warp", "salvo", "thruster"])]
pub tide: bool,
/// Initialize with tower framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "poem", "serenity", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "poem", "serenity", "warp", "salvo", "thruster"])]
pub tower: bool,
/// Initialize with poem framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "serenity", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "serenity", "warp", "salvo", "thruster"])]
pub poem: bool,
/// Initialize with salvo framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "serenity"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "serenity", "thruster"])]
pub salvo: bool,
/// Initialize with serenity framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "salvo", "thruster"])]
pub serenity: bool,
/// Initialize with warp framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "serenity", "salvo"])]
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "serenity", "salvo", "thruster"])]
pub warp: bool,
/// Initialize with thruster framework
#[clap(long, conflicts_with_all = &["axum", "rocket", "tide", "tower", "poem", "warp", "salvo", "serenity"])]
pub thruster: bool,
/// Path to initialize a new shuttle project
#[clap(
parse(try_from_os_str = parse_init_path),
Expand Down
98 changes: 96 additions & 2 deletions cargo-shuttle/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl ShuttleInit for ShuttleInitPoem {
#[shuttle_service::main]
async fn poem() -> shuttle_service::ShuttlePoem<impl poem::Endpoint> {
let app = Route::new().at("/hello", get(hello_world));

Ok(app)
}"#}
}
Expand Down Expand Up @@ -481,6 +481,61 @@ impl ShuttleInit for ShuttleInitWarp {
}
}

pub struct ShuttleInitThruster;

impl ShuttleInit for ShuttleInitThruster {
fn set_cargo_dependencies(
&self,
dependencies: &mut Table,
manifest_path: &Path,
url: &Url,
get_dependency_version_fn: GetDependencyVersionFn,
) {
set_inline_table_dependency_features(
"shuttle-service",
dependencies,
vec!["web-thruster".to_string()],
);

set_inline_table_dependency_version(
"thruster",
dependencies,
manifest_path,
url,
false,
get_dependency_version_fn,
);

set_inline_table_dependency_features(
"thruster",
dependencies,
vec!["hyper_server".to_string()],
);
}

fn get_boilerplate_code_for_framework(&self) -> &'static str {
indoc! {r#"
use thruster::{
context::basic_hyper_context::{generate_context, BasicHyperContext as Ctx, HyperRequest},
m, middleware_fn, App, HyperServer, MiddlewareNext, MiddlewareResult, ThrusterServer,
};

#[middleware_fn]
async fn hello(mut context: Ctx, _next: MiddlewareNext<Ctx>) -> MiddlewareResult<Ctx> {
context.body("Hello, World!");
Ok(context)
}

#[shuttle_service::main]
async fn thruster() -> shuttle_service::ShuttleThruster<HyperServer<Ctx, ()>> {
Ok(HyperServer::new(
App::<HyperRequest, Ctx, ()>::create(generate_context, ()).get("/hello", m![hello]),
))
}
"#}
}
}

pub struct ShuttleInitNoOp;
impl ShuttleInit for ShuttleInitNoOp {
fn set_cargo_dependencies(
Expand Down Expand Up @@ -533,6 +588,10 @@ pub fn get_framework(init_args: &InitArgs) -> Box<dyn ShuttleInit> {
return Box::new(ShuttleInitWarp);
}

if init_args.thruster {
return Box::new(ShuttleInitThruster);
}

Box::new(ShuttleInitNoOp)
}

Expand Down Expand Up @@ -691,6 +750,7 @@ mod shuttle_init_tests {
salvo: false,
serenity: false,
warp: false,
thruster: false,
path: PathBuf::new(),
};

Expand All @@ -703,6 +763,7 @@ mod shuttle_init_tests {
"salvo" => init_args.salvo = true,
"serenity" => init_args.serenity = true,
"warp" => init_args.warp = true,
"thruster" => init_args.thruster = true,
_ => unreachable!(),
}

Expand All @@ -729,7 +790,7 @@ mod shuttle_init_tests {
#[test]
fn test_get_framework_via_get_boilerplate_code() {
let frameworks = vec![
"axum", "rocket", "tide", "tower", "poem", "salvo", "serenity", "warp",
"axum", "rocket", "tide", "tower", "poem", "salvo", "serenity", "warp", "thruster",
];
let framework_inits: Vec<Box<dyn ShuttleInit>> = vec![
Box::new(ShuttleInitAxum),
Expand All @@ -740,6 +801,7 @@ mod shuttle_init_tests {
Box::new(ShuttleInitSalvo),
Box::new(ShuttleInitSerenity),
Box::new(ShuttleInitWarp),
Box::new(ShuttleInitThruster),
];

for (framework, expected_framework_init) in frameworks.into_iter().zip(framework_inits) {
Expand Down Expand Up @@ -1079,6 +1141,38 @@ mod shuttle_init_tests {
assert_eq!(cargo_toml.to_string(), expected);
}

#[test]
fn test_set_cargo_dependencies_thruster() {
let mut cargo_toml = cargo_toml_factory();
let dependencies = cargo_toml["dependencies"].as_table_mut().unwrap();
let manifest_path = PathBuf::new();
let url = Url::parse("https://shuttle.rs").unwrap();

set_inline_table_dependency_version(
"shuttle-service",
dependencies,
&manifest_path,
&url,
false,
mock_get_latest_dependency_version,
);

ShuttleInitThruster.set_cargo_dependencies(
dependencies,
&manifest_path,
&url,
mock_get_latest_dependency_version,
);

let expected = indoc! {r#"
[dependencies]
shuttle-service = { version = "1.0", features = ["web-thruster"] }
thruster = { version = "1.0", features = ["hyper_server"] }
"#};

assert_eq!(cargo_toml.to_string(), expected);
}

#[test]
/// Makes sure that Rocket uses allow_prerelease flag when fetching the latest version
fn test_get_latest_dependency_version_rocket() {
Expand Down
8 changes: 5 additions & 3 deletions cargo-shuttle/tests/integration/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async fn cargo_shuttle_init(path: PathBuf) -> anyhow::Result<CommandOutcome> {
salvo: false,
serenity: false,
warp: false,
thruster: false,
path,
}),
})
Expand All @@ -53,6 +54,7 @@ async fn cargo_shuttle_init_framework(path: PathBuf) -> anyhow::Result<CommandOu
salvo: false,
serenity: false,
warp: false,
thruster: false,
path,
}),
})
Expand Down Expand Up @@ -93,16 +95,16 @@ async fn framework_init() {
let expected = indoc! {r#"
#[macro_use]
extern crate rocket;

#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}

#[shuttle_service::main]
async fn rocket() -> shuttle_service::ShuttleRocket {
let rocket = rocket::build().mount("/hello", routes![index]);

Ok(rocket)
}"#};

Expand Down
10 changes: 10 additions & 0 deletions examples/thruster/hello-world/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "hello-world"
version = "0.1.0"
edition = "2021"

[lib]

[dependencies]
shuttle-service = { version = "0.5.2", features = ["web-thruster"] }
thruster = { version = "1.2.6", features = ["hyper_server"] }
1 change: 1 addition & 0 deletions examples/thruster/hello-world/Shuttle.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "hello-world-thruster-app"
17 changes: 17 additions & 0 deletions examples/thruster/hello-world/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use thruster::{
context::basic_hyper_context::{generate_context, BasicHyperContext as Ctx, HyperRequest},
m, middleware_fn, App, HyperServer, MiddlewareNext, MiddlewareResult, ThrusterServer,
};

#[middleware_fn]
async fn hello(mut context: Ctx, _next: MiddlewareNext<Ctx>) -> MiddlewareResult<Ctx> {
context.body("Hello, World!");
Ok(context)
}

#[shuttle_service::main]
async fn thruster() -> shuttle_service::ShuttleThruster<HyperServer<Ctx, ()>> {
Ok(HyperServer::new(
App::<HyperRequest, Ctx, ()>::create(generate_context, ()).get("/hello", m![hello]),
))
}
17 changes: 17 additions & 0 deletions examples/thruster/postgres/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "postgres"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hyper = "0.14.20"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
shuttle-aws-rds = { version = "0.5.2", features = ["postgres"] }
shuttle-service = { version = "0.5.2", features = ["web-thruster"] }
sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "postgres"] }
thruster = { version = "1.2.6", features = ["hyper_server"] }
1 change: 1 addition & 0 deletions examples/thruster/postgres/Shuttle.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "postgres-tide-app"
6 changes: 6 additions & 0 deletions examples/thruster/postgres/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DROP TABLE IF EXISTS todos;

CREATE TABLE todos (
id serial PRIMARY KEY,
note TEXT NOT NULL
);
Loading